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;
|
name: string;
|
||||||
displayName: string;
|
displayName: string;
|
||||||
value: number;
|
value: number;
|
||||||
|
actualValue: number;
|
||||||
percent: number;
|
percent: number;
|
||||||
actualPercent: number;
|
paintPercent: number;
|
||||||
color: ColorStyleValue;
|
color: ColorStyleValue;
|
||||||
sourceItem: Record<string, unknown>;
|
sourceItem: Record<string, unknown>;
|
||||||
displayPercent?: string;
|
displayPercent?: string;
|
||||||
@@ -30,7 +31,6 @@ export interface CommonPieChartProps {
|
|||||||
percentField?: string;
|
percentField?: string;
|
||||||
colorField?: string;
|
colorField?: string;
|
||||||
hiddenField?: string;
|
hiddenField?: string;
|
||||||
minValidPercent?: number;
|
|
||||||
amountValue?: boolean;
|
amountValue?: boolean;
|
||||||
defaultCurrency?: string;
|
defaultCurrency?: string;
|
||||||
showValue?: boolean;
|
showValue?: boolean;
|
||||||
@@ -55,32 +55,38 @@ export function usePieChartBase(props: CommonPieChartProps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const validItems: CommonPieChartDataItem[] = [];
|
const validItems: CommonPieChartDataItem[] = [];
|
||||||
|
let accumulatedPaintPercent: number = 0;
|
||||||
|
|
||||||
for (const item of props.items) {
|
for (const item of props.items) {
|
||||||
const value = item[props.valueField];
|
const value = item[props.valueField];
|
||||||
const percent = props.percentField ? item[props.percentField] : -1;
|
const percent = props.percentField ? item[props.percentField] : -1;
|
||||||
|
|
||||||
if (isNumber(value) && value > 0 &&
|
if (isNumber(value) &&
|
||||||
(!props.hiddenField || !item[props.hiddenField]) &&
|
(!props.hiddenField || !item[props.hiddenField])) {
|
||||||
(!props.minValidPercent || value / totalValidValue > props.minValidPercent)) {
|
|
||||||
const finalItem: CommonPieChartDataItem = {
|
const finalItem: CommonPieChartDataItem = {
|
||||||
id: (props.idField && item[props.idField]) ? item[props.idField] as string : item[props.nameField] as string,
|
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,
|
name: (props.idField && item[props.idField]) ? item[props.idField] as string : item[props.nameField] as string,
|
||||||
displayName: item[props.nameField] as string,
|
displayName: item[props.nameField] as string,
|
||||||
value: value,
|
value: value > 0 ? value : 0,
|
||||||
percent: (isNumber(percent) && percent >= 0) ? percent : (value / totalValidValue * 100),
|
actualValue: value,
|
||||||
actualPercent: value / totalValidValue,
|
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]),
|
color: getDisplayColor((props.colorField && item[props.colorField]) ? item[props.colorField] as ColorValue : DEFAULT_CHART_COLORS[validItems.length % DEFAULT_CHART_COLORS.length]),
|
||||||
sourceItem: item
|
sourceItem: item
|
||||||
};
|
};
|
||||||
|
|
||||||
finalItem.displayPercent = formatPercentToLocalizedNumerals(finalItem.percent, 2, '<0.01');
|
accumulatedPaintPercent += finalItem.paintPercent;
|
||||||
finalItem.displayValue = props.amountValue ? formatAmountToLocalizedNumeralsWithCurrency(finalItem.value, props.defaultCurrency) : finalItem.value.toString();
|
finalItem.displayPercent = formatPercentToLocalizedNumerals(finalItem.percent, 2, '<0.01');
|
||||||
|
finalItem.displayValue = props.amountValue ? formatAmountToLocalizedNumeralsWithCurrency(value, props.defaultCurrency) : value.toString();
|
||||||
|
|
||||||
validItems.push(finalItem);
|
validItems.push(finalItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (validItems.length > 0) {
|
||||||
|
validItems[validItems.length - 1]!.paintPercent += 1 - accumulatedPaintPercent;
|
||||||
|
}
|
||||||
|
|
||||||
return validItems;
|
return validItems;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -267,7 +267,7 @@ const chartOptions = computed<object>(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isNumber(dataItem.percent) && dataItem.percent > 0) {
|
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>`;
|
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 {
|
function getDisplayValue(value: number): string {
|
||||||
if (props.oneHundredPercentStacked) {
|
if (props.oneHundredPercentStacked) {
|
||||||
return formatPercentToLocalizedNumerals(value, 2, '<0.01');
|
return formatPercentToLocalizedNumerals(value, 2, '<0.01');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (props.amountValue) {
|
if (props.amountValue) {
|
||||||
|
|||||||
@@ -142,11 +142,14 @@ const chartOptions = computed<object>(() => {
|
|||||||
tooltip += `<div class="d-inline-flex">${name}</div><br/>`;
|
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>`;
|
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>`;
|
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>`;
|
tooltip += `<div class="d-inline-flex">${percent}</div>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,6 @@ const props = defineProps<{
|
|||||||
percentField?: string;
|
percentField?: string;
|
||||||
colorField?: string;
|
colorField?: string;
|
||||||
hiddenField?: string;
|
hiddenField?: string;
|
||||||
minValidPercent?: number;
|
|
||||||
amountValue?: boolean;
|
amountValue?: boolean;
|
||||||
defaultCurrency?: string;
|
defaultCurrency?: string;
|
||||||
showValue?: boolean;
|
showValue?: boolean;
|
||||||
@@ -74,14 +73,13 @@ const radarData = computed<RadarChartData>(() => {
|
|||||||
const value = item[props.valueField];
|
const value = item[props.valueField];
|
||||||
const percent = props.percentField ? item[props.percentField] : -1;
|
const percent = props.percentField ? item[props.percentField] : -1;
|
||||||
|
|
||||||
if (isNumber(value) && value > 0 &&
|
if (isNumber(value) &&
|
||||||
(!props.hiddenField || !item[props.hiddenField]) &&
|
(!props.hiddenField || !item[props.hiddenField])) {
|
||||||
(!props.minValidPercent || value / totalValidValue > props.minValidPercent)) {
|
|
||||||
const name = item[props.nameField] as string;
|
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 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 finalPercent = (isNumber(percent) && percent >= 0) ? percent : (value > 0 ? value / totalValidValue * 100 : 0);
|
||||||
const displayPercent = formatPercentToLocalizedNumerals(finalPercent, 2, '<0.01');
|
const displayPercent = formatPercentToLocalizedNumerals(finalPercent, 2, '<0.01');
|
||||||
const displayValue = props.amountValue ? formatAmountToLocalizedNumeralsWithCurrency(value, props.defaultCurrency) : value.toString();
|
const displayValue = props.amountValue ? formatAmountToLocalizedNumeralsWithCurrency(value, props.defaultCurrency) : value.toString();
|
||||||
|
|
||||||
indicators.push({
|
indicators.push({
|
||||||
@@ -90,16 +88,19 @@ const radarData = computed<RadarChartData>(() => {
|
|||||||
color: isDarkMode.value ? '#ccc' : '#333'
|
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 += '<div><span class="chart-pointer" style="background-color: ' + color + '"></span>';
|
||||||
tooltip += `<span>${name}</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>`;
|
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>`;
|
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>`;
|
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}`">
|
<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-background" cx="0" cy="0" :r="diameter"></circle>
|
||||||
|
|
||||||
<circle class="pie-chart-item"
|
<template :key="idx" v-for="(item, idx) in validItems">
|
||||||
fill="transparent"
|
<circle class="pie-chart-item"
|
||||||
cx="0" cy="0"
|
fill="transparent"
|
||||||
:r="diameter / 2"
|
cx="0" cy="0"
|
||||||
:stroke="item.color"
|
:r="diameter / 2"
|
||||||
:stroke-width="diameter"
|
:stroke="item.color"
|
||||||
:stroke-dasharray="getItemStrokeDash(item)"
|
:stroke-width="diameter"
|
||||||
:stroke-dashoffset="getItemDashOffset(item, validItems, itemCommonDashOffset)"
|
:stroke-dasharray="getItemStrokeDash(item)"
|
||||||
:key="idx"
|
:stroke-dashoffset="getItemDashOffset(item, validItems, itemCommonDashOffset)"
|
||||||
v-for="(item, idx) in validItems"
|
@click="switchSelectedIndex(idx)"
|
||||||
@click="switchSelectedIndex(idx)">
|
v-if="item.actualValue > 0 && item.paintPercent > minPaintPercent">
|
||||||
</circle>
|
</circle>
|
||||||
|
</template>
|
||||||
|
|
||||||
<circle class="pie-chart-text-background"
|
<circle class="pie-chart-text-background"
|
||||||
cx="0" cy="0"
|
cx="0" cy="0"
|
||||||
@@ -44,7 +45,7 @@
|
|||||||
</f7-link>
|
</f7-link>
|
||||||
|
|
||||||
<div class="pie-chart-toolbox-info">
|
<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">
|
<f7-chip class="chip-placeholder" outline v-if="skeleton">
|
||||||
<span class="skeleton-text">Percent</span>
|
<span class="skeleton-text">Percent</span>
|
||||||
</f7-chip>
|
</f7-chip>
|
||||||
@@ -53,7 +54,7 @@
|
|||||||
:style="getColorStyle(selectedItem?.color, '--f7-chip-outline-border-color')"
|
:style="getColorStyle(selectedItem?.color, '--f7-chip-outline-border-color')"
|
||||||
v-else-if="!skeleton"></f7-chip>
|
v-else-if="!skeleton"></f7-chip>
|
||||||
</p>
|
</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>
|
<f7-chip outline text="---"></f7-chip>
|
||||||
</p>
|
</p>
|
||||||
<f7-link class="pie-chart-selected-item-info" :no-link-class="!enableClickItem" v-if="selectedItem" @click="clickItem(selectedItem)">
|
<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 { tt } = useI18n();
|
||||||
const { selectedIndex, validItems } = usePieChartBase(props);
|
const { selectedIndex, validItems } = usePieChartBase(props);
|
||||||
|
|
||||||
|
const minPaintPercent = 0.0001; // 0.01%
|
||||||
const diameter: number = 100;
|
const diameter: number = 100;
|
||||||
const circumference: number = diameter * Math.PI;
|
const circumference: number = diameter * Math.PI;
|
||||||
|
|
||||||
@@ -106,7 +108,9 @@ const totalValidValue = computed<number>(() => {
|
|||||||
let totalValidValue = 0;
|
let totalValidValue = 0;
|
||||||
|
|
||||||
for (const item of validItems.value) {
|
for (const item of validItems.value) {
|
||||||
totalValidValue += item.value;
|
if (item.actualValue > 0 && item.paintPercent > minPaintPercent) {
|
||||||
|
totalValidValue += item.value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return totalValidValue;
|
return totalValidValue;
|
||||||
@@ -122,11 +126,17 @@ const itemCommonDashOffset = computed<number>(() => {
|
|||||||
for (let i = 0; i < Math.min(selectedIndex.value + 1, validItems.value.length); i++) {
|
for (let i = 0; i < Math.min(selectedIndex.value + 1, validItems.value.length); i++) {
|
||||||
const item = validItems.value[i] as CommonPieChartDataItem;
|
const item = validItems.value[i] as CommonPieChartDataItem;
|
||||||
|
|
||||||
if (item.actualPercent > 0) {
|
if (item.actualValue > 0 && item.paintPercent > minPaintPercent) {
|
||||||
if (i === selectedIndex.value) {
|
if (i === selectedIndex.value) {
|
||||||
offset += -circumference * (1 - item.actualPercent) / 2;
|
offset += -circumference * (1 - item.paintPercent) / 2;
|
||||||
} else {
|
} 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 {
|
function getItemStrokeDash(item: CommonPieChartDataItem): string {
|
||||||
const length = item.actualPercent * circumference;
|
const length = item.paintPercent * circumference;
|
||||||
return `${length} ${circumference - length}`;
|
return `${length} ${circumference - length}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,7 +169,7 @@ function getItemDashOffset(item: CommonPieChartDataItem, items: CommonPieChartDa
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
allPreviousPercent += curItem.actualPercent;
|
allPreviousPercent += curItem.paintPercent > 0 ? curItem.paintPercent : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offset) {
|
if (offset) {
|
||||||
|
|||||||
@@ -117,7 +117,6 @@
|
|||||||
/>
|
/>
|
||||||
<radar-chart
|
<radar-chart
|
||||||
:items="categoryDimensionTransactionExplorerData && categoryDimensionTransactionExplorerData.length ? categoryDimensionTransactionExplorerData : []"
|
:items="categoryDimensionTransactionExplorerData && categoryDimensionTransactionExplorerData.length ? categoryDimensionTransactionExplorerData : []"
|
||||||
:min-valid-percent="0.0001"
|
|
||||||
:show-value="true"
|
:show-value="true"
|
||||||
:show-percent="true"
|
:show-percent="true"
|
||||||
:amount-value="currentExplorer.valueMetric !== TransactionExplorerValueMetric.TransactionCount.value"
|
:amount-value="currentExplorer.valueMetric !== TransactionExplorerValueMetric.TransactionCount.value"
|
||||||
|
|||||||
@@ -263,7 +263,6 @@
|
|||||||
/>
|
/>
|
||||||
<pie-chart
|
<pie-chart
|
||||||
:items="categoricalAnalysisData && categoricalAnalysisData.items && categoricalAnalysisData.items.length ? categoricalAnalysisData.items : []"
|
:items="categoricalAnalysisData && categoricalAnalysisData.items && categoricalAnalysisData.items.length ? categoricalAnalysisData.items : []"
|
||||||
:min-valid-percent="0.0001"
|
|
||||||
:show-value="showAmountInChart"
|
:show-value="showAmountInChart"
|
||||||
:show-percent="showPercentInCategoricalChart"
|
:show-percent="showPercentInCategoricalChart"
|
||||||
:enable-click-item="true"
|
:enable-click-item="true"
|
||||||
@@ -316,7 +315,7 @@
|
|||||||
<div class="d-flex flex-column ms-2">
|
<div class="d-flex flex-column ms-2">
|
||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
<span>{{ item.name }}</span>
|
<span>{{ item.name }}</span>
|
||||||
<small class="statistics-percent" v-if="showPercentInCategoricalChart && item.percent >= 0">{{ formatPercentToLocalizedNumerals(item.percent, 2, '<0.01') }}</small>
|
<small class="statistics-percent" v-if="showPercentInCategoricalChart && item.percent >= 0 && item.totalAmount >= 0">{{ formatPercentToLocalizedNumerals(item.percent, 2, '<0.01') }}</small>
|
||||||
<v-spacer/>
|
<v-spacer/>
|
||||||
<span class="statistics-amount">{{ getDisplayAmount(item.totalAmount, defaultCurrency) }}</span>
|
<span class="statistics-amount">{{ getDisplayAmount(item.totalAmount, defaultCurrency) }}</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -351,7 +350,6 @@
|
|||||||
/>
|
/>
|
||||||
<radar-chart
|
<radar-chart
|
||||||
:items="categoricalAnalysisData && categoricalAnalysisData.items && categoricalAnalysisData.items.length ? categoricalAnalysisData.items : []"
|
:items="categoricalAnalysisData && categoricalAnalysisData.items && categoricalAnalysisData.items.length ? categoricalAnalysisData.items : []"
|
||||||
:min-valid-percent="0.0001"
|
|
||||||
:show-value="showAmountInChart"
|
:show-value="showAmountInChart"
|
||||||
:show-percent="showPercentInCategoricalChart"
|
:show-percent="showPercentInCategoricalChart"
|
||||||
:amount-value="true"
|
:amount-value="true"
|
||||||
|
|||||||
@@ -80,7 +80,6 @@
|
|||||||
></pie-chart>
|
></pie-chart>
|
||||||
<pie-chart
|
<pie-chart
|
||||||
:items="categoricalAnalysisData.items"
|
:items="categoricalAnalysisData.items"
|
||||||
:min-valid-percent="0.0001"
|
|
||||||
:show-value="showAmountInChart"
|
:show-value="showAmountInChart"
|
||||||
:show-percent="showPercentInCategoricalChart"
|
:show-percent="showPercentInCategoricalChart"
|
||||||
:show-center-text="true"
|
:show-center-text="true"
|
||||||
@@ -183,7 +182,7 @@
|
|||||||
<template #title>
|
<template #title>
|
||||||
<div class="statistics-list-item-text">
|
<div class="statistics-list-item-text">
|
||||||
<span>{{ item.name }}</span>
|
<span>{{ item.name }}</span>
|
||||||
<small class="statistics-percent" v-if="showPercentInCategoricalChart && item.percent >= 0">{{ formatPercentToLocalizedNumerals(item.percent, 2, '<0.01') }}</small>
|
<small class="statistics-percent" v-if="showPercentInCategoricalChart && item.percent >= 0 && item.totalAmount >= 0">{{ formatPercentToLocalizedNumerals(item.percent, 2, '<0.01') }}</small>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user