webapp: replace own formatNumber by vue-i18n $n

This commit is contained in:
Thomas Basler 2023-01-02 13:35:55 +01:00
parent 065aab7141
commit a88687eae6
7 changed files with 74 additions and 27 deletions

View File

@ -19,7 +19,12 @@
<tr v-for="(property, key) in channelData" :key="`prop-${key}`"> <tr v-for="(property, key) in channelData" :key="`prop-${key}`">
<template v-if="key != 'name' && property"> <template v-if="key != 'name' && property">
<th scope="row">{{ $t('inverterchannelproperty.' + key) }}</th> <th scope="row">{{ $t('inverterchannelproperty.' + key) }}</th>
<td style="text-align: right">{{ formatNumber(property.v, property.d) }}</td> <td style="text-align: right">
{{ $n(property.v, 'decimal', {
minimumFractionDigits: property.d,
maximumFractionDigits: property.d})
}}
</td>
<td>{{ property.u }}</td> <td>{{ property.u }}</td>
</template> </template>
</tr> </tr>
@ -31,7 +36,6 @@
<script lang="ts"> <script lang="ts">
import type { InverterStatistics } from '@/types/LiveDataStatus'; import type { InverterStatistics } from '@/types/LiveDataStatus';
import { formatNumber } from '@/utils';
import { defineComponent, type PropType } from 'vue'; import { defineComponent, type PropType } from 'vue';
export default defineComponent({ export default defineComponent({
@ -39,8 +43,5 @@ export default defineComponent({
channelData: { type: Object as PropType<InverterStatistics>, required: true }, channelData: { type: Object as PropType<InverterStatistics>, required: true },
channelNumber: { type: Number, required: true }, channelNumber: { type: Number, required: true },
}, },
methods: {
formatNumber,
},
}); });
</script> </script>

View File

@ -4,7 +4,11 @@
<div class="card"> <div class="card">
<div class="card-header text-bg-success">{{ $t('invertertotalinfo.TotalYieldTotal') }}</div> <div class="card-header text-bg-success">{{ $t('invertertotalinfo.TotalYieldTotal') }}</div>
<div class="card-body card-text text-center"> <div class="card-body card-text text-center">
<h2>{{ formatNumber(totalData.YieldTotal.v, totalData.YieldTotal.d) }} <h2>
{{ $n(totalData.YieldTotal.v, 'decimal', {
minimumFractionDigits: totalData.YieldTotal.d,
maximumFractionDigits: totalData.YieldTotal.d
})}}
<small class="text-muted">{{ totalData.YieldTotal.u }}</small> <small class="text-muted">{{ totalData.YieldTotal.u }}</small>
</h2> </h2>
</div> </div>
@ -14,7 +18,11 @@
<div class="card"> <div class="card">
<div class="card-header text-bg-success">{{ $t('invertertotalinfo.TotalYieldDay') }}</div> <div class="card-header text-bg-success">{{ $t('invertertotalinfo.TotalYieldDay') }}</div>
<div class="card-body card-text text-center"> <div class="card-body card-text text-center">
<h2>{{ formatNumber(totalData.YieldDay.v, totalData.YieldDay.d) }} <h2>
{{ $n(totalData.YieldDay.v, 'decimal', {
minimumFractionDigits: totalData.YieldDay.d,
maximumFractionDigits: totalData.YieldDay.d
})}}
<small class="text-muted">{{ totalData.YieldDay.u }}</small> <small class="text-muted">{{ totalData.YieldDay.u }}</small>
</h2> </h2>
</div> </div>
@ -24,7 +32,11 @@
<div class="card"> <div class="card">
<div class="card-header text-bg-success">{{ $t('invertertotalinfo.TotalPower') }}</div> <div class="card-header text-bg-success">{{ $t('invertertotalinfo.TotalPower') }}</div>
<div class="card-body card-text text-center"> <div class="card-body card-text text-center">
<h2>{{ formatNumber(totalData.Power.v, totalData.Power.d) }} <h2>
{{ $n(totalData.Power.v, 'decimal', {
minimumFractionDigits: totalData.Power.d,
maximumFractionDigits: totalData.Power.d
})}}
<small class="text-muted">{{ totalData.Power.u }}</small> <small class="text-muted">{{ totalData.Power.u }}</small>
</h2> </h2>
</div> </div>
@ -35,15 +47,11 @@
<script lang="ts"> <script lang="ts">
import type { Total } from '@/types/LiveDataStatus'; import type { Total } from '@/types/LiveDataStatus';
import { formatNumber } from '@/utils';
import { defineComponent, type PropType } from 'vue'; import { defineComponent, type PropType } from 'vue';
export default defineComponent({ export default defineComponent({
props: { props: {
totalData: { type: Object as PropType<Total>, required: true }, totalData: { type: Object as PropType<Total>, required: true },
}, },
methods: {
formatNumber,
},
}); });
</script> </script>

View File

@ -57,4 +57,49 @@ export const dateTimeFormats: I18nOptions["datetimeFormats"] = {
} }
}; };
export const numberFormats: I18nOptions["numberFormats"] = {
[Locales.EN]: {
decimal: {
style: 'decimal',
},
decimalNoDigits: {
style: 'decimal', minimumFractionDigits: 0, maximumFractionDigits: 0
},
decimalTwoDigits: {
style: 'decimal', minimumFractionDigits: 2, maximumFractionDigits: 2
},
percent: {
style: 'percent',
},
},
[Locales.DE]: {
decimal: {
style: 'decimal',
},
decimalNoDigits: {
style: 'decimal', minimumFractionDigits: 0, maximumFractionDigits: 0
},
decimalTwoDigits: {
style: 'decimal', minimumFractionDigits: 2, maximumFractionDigits: 2
},
percent: {
style: 'percent',
},
},
[Locales.FR]: {
decimal: {
style: 'decimal',
},
decimalNoDigits: {
style: 'decimal', minimumFractionDigits: 0, maximumFractionDigits: 0
},
decimalTwoDigits: {
style: 'decimal', minimumFractionDigits: 2, maximumFractionDigits: 2
},
percent: {
style: 'percent',
},
},
};
export const defaultLocale = Locales.EN; export const defaultLocale = Locales.EN;

View File

@ -2,7 +2,7 @@ import mitt from 'mitt'
import { createApp } from 'vue' import { createApp } from 'vue'
import { createI18n } from 'vue-i18n' import { createI18n } from 'vue-i18n'
import App from './App.vue' import App from './App.vue'
import { defaultLocale, messages, dateTimeFormats } from './locales' import { defaultLocale, messages, dateTimeFormats, numberFormats } from './locales'
import { tooltip } from './plugins/bootstrap' import { tooltip } from './plugins/bootstrap'
import router from './router' import router from './router'
@ -23,6 +23,7 @@ const i18n = createI18n({
fallbackLocale: defaultLocale, fallbackLocale: defaultLocale,
messages, messages,
datetimeFormats: dateTimeFormats, datetimeFormats: dateTimeFormats,
numberFormats: numberFormats
}) })
app.use(router) app.use(router)

View File

@ -1,10 +1,8 @@
import { isLoggedIn, login, logout } from './authentication'; import { isLoggedIn, login, logout } from './authentication';
import { formatNumber } from './number';
import { timestampToString } from './time'; import { timestampToString } from './time';
export { export {
timestampToString, timestampToString,
formatNumber,
login, login,
logout, logout,
isLoggedIn, isLoggedIn,
@ -12,7 +10,6 @@ export {
export default { export default {
timestampToString, timestampToString,
formatNumber,
login, login,
logout, logout,
isLoggedIn, isLoggedIn,

View File

@ -1,5 +0,0 @@
export const formatNumber = (num: number, digits: number): string => {
return new Intl.NumberFormat(
undefined, { minimumFractionDigits: digits, maximumFractionDigits: digits }
).format(num);
}

View File

@ -41,8 +41,8 @@
</div> </div>
<div style="padding-right: 2em;"> <div style="padding-right: 2em;">
{{ $t('home.CurrentLimit') }}<template v-if="inverter.limit_absolute > -1"> {{ {{ $t('home.CurrentLimit') }}<template v-if="inverter.limit_absolute > -1"> {{
formatNumber(inverter.limit_absolute, 0) $n(inverter.limit_absolute, 'decimalNoDigits')
}} W | </template>{{ formatNumber(inverter.limit_relative, 0) }} % }} W | </template>{{ $n(inverter.limit_relative / 100, 'percent') }}
</div> </div>
<div style="padding-right: 2em;"> <div style="padding-right: 2em;">
{{ $t('home.DataAge') }} {{ $t('home.Seconds', {'val': inverter.data_age }) }} {{ $t('home.DataAge') }} {{ $t('home.Seconds', {'val': inverter.data_age }) }}
@ -320,7 +320,6 @@ import type { EventlogItems } from '@/types/EventlogStatus';
import type { LimitConfig } from '@/types/LimitConfig'; import type { LimitConfig } from '@/types/LimitConfig';
import type { LimitStatus } from '@/types/LimitStatus'; import type { LimitStatus } from '@/types/LimitStatus';
import type { Inverter, LiveData } from '@/types/LiveDataStatus'; import type { Inverter, LiveData } from '@/types/LiveDataStatus';
import { formatNumber } from '@/utils';
import { authHeader, authUrl, handleResponse, isLoggedIn } from '@/utils/authentication'; import { authHeader, authUrl, handleResponse, isLoggedIn } from '@/utils/authentication';
import * as bootstrap from 'bootstrap'; import * as bootstrap from 'bootstrap';
import { import {
@ -439,19 +438,20 @@ export default defineComponent({
computed: { computed: {
currentLimitAbsolute(): string { currentLimitAbsolute(): string {
if (this.currentLimitList.max_power > 0) { if (this.currentLimitList.max_power > 0) {
return formatNumber(this.currentLimitList.limit_relative * this.currentLimitList.max_power / 100, 2); return this.$n(this.currentLimitList.limit_relative * this.currentLimitList.max_power / 100,
'decimalTwoDigits');
} }
return "0"; return "0";
}, },
currentLimitRelative(): string { currentLimitRelative(): string {
return formatNumber(this.currentLimitList.limit_relative, 2); return this.$n(this.currentLimitList.limit_relative,
'decimalTwoDigits');
}, },
inverterData(): Inverter[] { inverterData(): Inverter[] {
return this.liveData.inverters; return this.liveData.inverters;
} }
}, },
methods: { methods: {
formatNumber,
isLoggedIn, isLoggedIn,
getInitialData() { getInitialData() {
this.dataLoading = true; this.dataLoading = true;