support setting decimal separator and digit grouping symbol
This commit is contained in:
@@ -618,6 +618,9 @@ func printUserInfo(user *models.User) {
|
||||
fmt.Printf("[ShortDateFormat] %s (%d)\n", user.ShortDateFormat, user.ShortDateFormat)
|
||||
fmt.Printf("[LongTimeFormat] %s (%d)\n", user.LongTimeFormat, user.LongTimeFormat)
|
||||
fmt.Printf("[ShortTimeFormat] %s (%d)\n", user.ShortTimeFormat, user.ShortTimeFormat)
|
||||
fmt.Printf("[DecimalSeparator] %s (%d)\n", user.DecimalSeparator, user.DecimalSeparator)
|
||||
fmt.Printf("[DigitGroupingSymbol] %s (%d)\n", user.DigitGroupingSymbol, user.DigitGroupingSymbol)
|
||||
fmt.Printf("[DigitGrouping] %s (%d)\n", user.DigitGrouping, user.DigitGrouping)
|
||||
fmt.Printf("[Deleted] %t\n", user.Deleted)
|
||||
fmt.Printf("[EmailVerified] %t\n", user.EmailVerified)
|
||||
fmt.Printf("[CreatedAt] %s (%d)\n", utils.FormatUnixTimeToLongDateTimeInServerTimezone(user.CreatedUnixTime), user.CreatedUnixTime)
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
|
||||
"github.com/mayswind/ezbookkeeping/pkg/core"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/errs"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/locales"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/log"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/models"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/services"
|
||||
@@ -336,6 +337,57 @@ func (a *UsersApi) UserUpdateProfileHandler(c *core.Context) (any, *errs.Error)
|
||||
userNew.ShortTimeFormat = models.SHORT_TIME_FORMAT_INVALID
|
||||
}
|
||||
|
||||
if userUpdateReq.DecimalSeparator != nil && *userUpdateReq.DecimalSeparator != user.DecimalSeparator {
|
||||
user.DecimalSeparator = *userUpdateReq.DecimalSeparator
|
||||
userNew.DecimalSeparator = *userUpdateReq.DecimalSeparator
|
||||
anythingUpdate = true
|
||||
} else {
|
||||
userNew.DecimalSeparator = models.DECIMAL_SEPARATOR_INVALID
|
||||
}
|
||||
|
||||
if userUpdateReq.DigitGroupingSymbol != nil && *userUpdateReq.DigitGroupingSymbol != user.DigitGroupingSymbol {
|
||||
user.DigitGroupingSymbol = *userUpdateReq.DigitGroupingSymbol
|
||||
userNew.DigitGroupingSymbol = *userUpdateReq.DigitGroupingSymbol
|
||||
anythingUpdate = true
|
||||
} else {
|
||||
userNew.DigitGroupingSymbol = models.DIGIT_GROUPING_SYMBOL_INVALID
|
||||
}
|
||||
|
||||
if userUpdateReq.DigitGrouping != nil && *userUpdateReq.DigitGrouping != user.DigitGrouping {
|
||||
user.DigitGrouping = *userUpdateReq.DigitGrouping
|
||||
userNew.DigitGrouping = *userUpdateReq.DigitGrouping
|
||||
anythingUpdate = true
|
||||
} else {
|
||||
userNew.DigitGrouping = models.DIGIT_GROUPING_TYPE_INVALID
|
||||
}
|
||||
|
||||
if modifyUserLanguage || userNew.DecimalSeparator != models.DECIMAL_SEPARATOR_INVALID || userNew.DigitGroupingSymbol != models.DIGIT_GROUPING_SYMBOL_INVALID {
|
||||
decimalSeparator := userNew.DecimalSeparator
|
||||
digitGroupingSymbol := userNew.DigitGroupingSymbol
|
||||
|
||||
if userNew.DecimalSeparator == models.DECIMAL_SEPARATOR_INVALID {
|
||||
decimalSeparator = user.DecimalSeparator
|
||||
}
|
||||
|
||||
if userNew.DigitGroupingSymbol == models.DIGIT_GROUPING_SYMBOL_INVALID {
|
||||
digitGroupingSymbol = user.DigitGroupingSymbol
|
||||
}
|
||||
|
||||
locale := user.Language
|
||||
|
||||
if modifyUserLanguage {
|
||||
locale = userNew.Language
|
||||
}
|
||||
|
||||
if locale == "" {
|
||||
locale = c.GetClientLocale()
|
||||
}
|
||||
|
||||
if locales.IsDecimalSeparatorEqualsDigitGroupingSymbol(decimalSeparator, digitGroupingSymbol, locale) {
|
||||
return nil, errs.ErrDecimalSeparatorAndDigitGroupingSymbolCannotBeEqual
|
||||
}
|
||||
}
|
||||
|
||||
if !anythingUpdate {
|
||||
return nil, errs.ErrNothingWillBeUpdated
|
||||
}
|
||||
|
||||
+24
-23
@@ -6,27 +6,28 @@ import (
|
||||
|
||||
// Error codes related to users
|
||||
var (
|
||||
ErrLoginNameInvalid = NewNormalError(NormalSubcategoryUser, 0, http.StatusUnauthorized, "login name is invalid")
|
||||
ErrLoginNameOrPasswordInvalid = NewNormalError(NormalSubcategoryUser, 1, http.StatusUnauthorized, "login name or password is invalid")
|
||||
ErrLoginNameOrPasswordWrong = NewNormalError(NormalSubcategoryUser, 2, http.StatusUnauthorized, "login name or password is wrong")
|
||||
ErrUserIdInvalid = NewNormalError(NormalSubcategoryUser, 3, http.StatusBadRequest, "user id is invalid")
|
||||
ErrUsernameIsEmpty = NewNormalError(NormalSubcategoryUser, 4, http.StatusBadRequest, "username is empty")
|
||||
ErrEmailIsEmpty = NewNormalError(NormalSubcategoryUser, 5, http.StatusBadRequest, "email is empty")
|
||||
ErrNicknameIsEmpty = NewNormalError(NormalSubcategoryUser, 6, http.StatusBadRequest, "nickname is empty")
|
||||
ErrPasswordIsEmpty = NewNormalError(NormalSubcategoryUser, 7, http.StatusBadRequest, "password is empty")
|
||||
ErrUserDefaultCurrencyIsEmpty = NewNormalError(NormalSubcategoryUser, 8, http.StatusBadRequest, "user default currency is empty")
|
||||
ErrUserDefaultCurrencyIsInvalid = NewNormalError(NormalSubcategoryUser, 9, http.StatusBadRequest, "user default currency is invalid")
|
||||
ErrUserNotFound = NewNormalError(NormalSubcategoryUser, 10, http.StatusBadRequest, "user not found")
|
||||
ErrUserPasswordWrong = NewNormalError(NormalSubcategoryUser, 11, http.StatusBadRequest, "password is wrong")
|
||||
ErrUsernameAlreadyExists = NewNormalError(NormalSubcategoryUser, 12, http.StatusBadRequest, "username already exists")
|
||||
ErrUserEmailAlreadyExists = NewNormalError(NormalSubcategoryUser, 13, http.StatusBadRequest, "email already exists")
|
||||
ErrUserRegistrationNotAllowed = NewNormalError(NormalSubcategoryUser, 14, http.StatusBadRequest, "user registration not allowed")
|
||||
ErrUserDefaultAccountIsInvalid = NewNormalError(NormalSubcategoryUser, 15, http.StatusBadRequest, "user default account is invalid")
|
||||
ErrUserIsDisabled = NewNormalError(NormalSubcategoryUser, 16, http.StatusBadRequest, "user is disabled")
|
||||
ErrEmptyIsInvalid = NewNormalError(NormalSubcategoryUser, 17, http.StatusBadRequest, "email is invalid")
|
||||
ErrEmailIsEmptyOrInvalid = NewNormalError(NormalSubcategoryUser, 18, http.StatusBadRequest, "email is empty or invalid")
|
||||
ErrNewPasswordEqualsOldInvalid = NewNormalError(NormalSubcategoryUser, 19, http.StatusBadRequest, "new password equals old password")
|
||||
ErrEmailIsNotVerified = NewNormalError(NormalSubcategoryUser, 20, http.StatusBadRequest, "email is not verified")
|
||||
ErrEmailIsVerified = NewNormalError(NormalSubcategoryUser, 21, http.StatusBadRequest, "email is verified")
|
||||
ErrEmailValidationNotAllowed = NewNormalError(NormalSubcategoryUser, 22, http.StatusBadRequest, "email validation not allowed")
|
||||
ErrLoginNameInvalid = NewNormalError(NormalSubcategoryUser, 0, http.StatusUnauthorized, "login name is invalid")
|
||||
ErrLoginNameOrPasswordInvalid = NewNormalError(NormalSubcategoryUser, 1, http.StatusUnauthorized, "login name or password is invalid")
|
||||
ErrLoginNameOrPasswordWrong = NewNormalError(NormalSubcategoryUser, 2, http.StatusUnauthorized, "login name or password is wrong")
|
||||
ErrUserIdInvalid = NewNormalError(NormalSubcategoryUser, 3, http.StatusBadRequest, "user id is invalid")
|
||||
ErrUsernameIsEmpty = NewNormalError(NormalSubcategoryUser, 4, http.StatusBadRequest, "username is empty")
|
||||
ErrEmailIsEmpty = NewNormalError(NormalSubcategoryUser, 5, http.StatusBadRequest, "email is empty")
|
||||
ErrNicknameIsEmpty = NewNormalError(NormalSubcategoryUser, 6, http.StatusBadRequest, "nickname is empty")
|
||||
ErrPasswordIsEmpty = NewNormalError(NormalSubcategoryUser, 7, http.StatusBadRequest, "password is empty")
|
||||
ErrUserDefaultCurrencyIsEmpty = NewNormalError(NormalSubcategoryUser, 8, http.StatusBadRequest, "user default currency is empty")
|
||||
ErrUserDefaultCurrencyIsInvalid = NewNormalError(NormalSubcategoryUser, 9, http.StatusBadRequest, "user default currency is invalid")
|
||||
ErrUserNotFound = NewNormalError(NormalSubcategoryUser, 10, http.StatusBadRequest, "user not found")
|
||||
ErrUserPasswordWrong = NewNormalError(NormalSubcategoryUser, 11, http.StatusBadRequest, "password is wrong")
|
||||
ErrUsernameAlreadyExists = NewNormalError(NormalSubcategoryUser, 12, http.StatusBadRequest, "username already exists")
|
||||
ErrUserEmailAlreadyExists = NewNormalError(NormalSubcategoryUser, 13, http.StatusBadRequest, "email already exists")
|
||||
ErrUserRegistrationNotAllowed = NewNormalError(NormalSubcategoryUser, 14, http.StatusBadRequest, "user registration not allowed")
|
||||
ErrUserDefaultAccountIsInvalid = NewNormalError(NormalSubcategoryUser, 15, http.StatusBadRequest, "user default account is invalid")
|
||||
ErrUserIsDisabled = NewNormalError(NormalSubcategoryUser, 16, http.StatusBadRequest, "user is disabled")
|
||||
ErrEmptyIsInvalid = NewNormalError(NormalSubcategoryUser, 17, http.StatusBadRequest, "email is invalid")
|
||||
ErrEmailIsEmptyOrInvalid = NewNormalError(NormalSubcategoryUser, 18, http.StatusBadRequest, "email is empty or invalid")
|
||||
ErrNewPasswordEqualsOldInvalid = NewNormalError(NormalSubcategoryUser, 19, http.StatusBadRequest, "new password equals old password")
|
||||
ErrEmailIsNotVerified = NewNormalError(NormalSubcategoryUser, 20, http.StatusBadRequest, "email is not verified")
|
||||
ErrEmailIsVerified = NewNormalError(NormalSubcategoryUser, 21, http.StatusBadRequest, "email is verified")
|
||||
ErrEmailValidationNotAllowed = NewNormalError(NormalSubcategoryUser, 22, http.StatusBadRequest, "email validation not allowed")
|
||||
ErrDecimalSeparatorAndDigitGroupingSymbolCannotBeEqual = NewNormalError(NormalSubcategoryUser, 23, http.StatusBadRequest, "decimal separator and digit grouping symbol cannot be equal")
|
||||
)
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package locales
|
||||
|
||||
import "github.com/mayswind/ezbookkeeping/pkg/models"
|
||||
|
||||
// DefaultLanguage represents the default language
|
||||
var DefaultLanguage = en
|
||||
|
||||
@@ -22,3 +24,25 @@ func GetLocaleTextItems(locale string) *LocaleTextItems {
|
||||
|
||||
return DefaultLanguage
|
||||
}
|
||||
|
||||
func IsDecimalSeparatorEqualsDigitGroupingSymbol(decimalSeparator models.DecimalSeparator, digitGroupingSymbol models.DigitGroupingSymbol, locale string) bool {
|
||||
if decimalSeparator == models.DECIMAL_SEPARATOR_DEFAULT && digitGroupingSymbol == models.DIGIT_GROUPING_SYMBOL_DEFAULT {
|
||||
return false
|
||||
}
|
||||
|
||||
if byte(decimalSeparator) == byte(digitGroupingSymbol) {
|
||||
return true
|
||||
}
|
||||
|
||||
localeTextItems := GetLocaleTextItems(locale)
|
||||
|
||||
if decimalSeparator == models.DECIMAL_SEPARATOR_DEFAULT {
|
||||
decimalSeparator = localeTextItems.DefaultTypes.DecimalSeparator
|
||||
}
|
||||
|
||||
if digitGroupingSymbol == models.DIGIT_GROUPING_SYMBOL_DEFAULT {
|
||||
digitGroupingSymbol = localeTextItems.DefaultTypes.DigitGroupingSymbol
|
||||
}
|
||||
|
||||
return byte(decimalSeparator) == byte(digitGroupingSymbol)
|
||||
}
|
||||
|
||||
@@ -1,11 +1,19 @@
|
||||
package locales
|
||||
|
||||
import "github.com/mayswind/ezbookkeeping/pkg/models"
|
||||
|
||||
// LocaleTextItems represents all text items need to be translated
|
||||
type LocaleTextItems struct {
|
||||
DefaultTypes *DefaultTypes
|
||||
VerifyEmailTextItems *VerifyEmailTextItems
|
||||
ForgetPasswordMailTextItems *ForgetPasswordMailTextItems
|
||||
}
|
||||
|
||||
type DefaultTypes struct {
|
||||
DecimalSeparator models.DecimalSeparator
|
||||
DigitGroupingSymbol models.DigitGroupingSymbol
|
||||
}
|
||||
|
||||
// VerifyEmailTextItems represents text items need to be translated in verify mail
|
||||
type VerifyEmailTextItems struct {
|
||||
Title string
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
package locales
|
||||
|
||||
import "github.com/mayswind/ezbookkeeping/pkg/models"
|
||||
|
||||
var en = &LocaleTextItems{
|
||||
DefaultTypes: &DefaultTypes{
|
||||
DecimalSeparator: models.DECIMAL_SEPARATOR_DOT,
|
||||
DigitGroupingSymbol: models.DIGIT_GROUPING_SYMBOL_COMMA,
|
||||
},
|
||||
VerifyEmailTextItems: &VerifyEmailTextItems{
|
||||
Title: "Verify Email",
|
||||
SalutationFormat: "Hi %s,",
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
package locales
|
||||
|
||||
import "github.com/mayswind/ezbookkeeping/pkg/models"
|
||||
|
||||
var zhHans = &LocaleTextItems{
|
||||
DefaultTypes: &DefaultTypes{
|
||||
DecimalSeparator: models.DECIMAL_SEPARATOR_DOT,
|
||||
DigitGroupingSymbol: models.DIGIT_GROUPING_SYMBOL_COMMA,
|
||||
},
|
||||
VerifyEmailTextItems: &VerifyEmailTextItems{
|
||||
Title: "验证邮箱",
|
||||
SalutationFormat: "%s 您好,",
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// DecimalSeparator represents the type of decimal separator
|
||||
type DecimalSeparator byte
|
||||
|
||||
// Decimal Separator
|
||||
const (
|
||||
DECIMAL_SEPARATOR_DEFAULT DecimalSeparator = 0
|
||||
DECIMAL_SEPARATOR_DOT DecimalSeparator = 1
|
||||
DECIMAL_SEPARATOR_COMMA DecimalSeparator = 2
|
||||
DECIMAL_SEPARATOR_SPACE DecimalSeparator = 3
|
||||
DECIMAL_SEPARATOR_INVALID DecimalSeparator = 255
|
||||
)
|
||||
|
||||
// String returns a textual representation of the decimal separator enum
|
||||
func (f DecimalSeparator) String() string {
|
||||
switch f {
|
||||
case DECIMAL_SEPARATOR_DEFAULT:
|
||||
return "Default"
|
||||
case DECIMAL_SEPARATOR_DOT:
|
||||
return "Dot"
|
||||
case DECIMAL_SEPARATOR_COMMA:
|
||||
return "Comma"
|
||||
case DECIMAL_SEPARATOR_SPACE:
|
||||
return "Space"
|
||||
case DECIMAL_SEPARATOR_INVALID:
|
||||
return "Invalid"
|
||||
default:
|
||||
return fmt.Sprintf("Invalid(%d)", int(f))
|
||||
}
|
||||
}
|
||||
|
||||
// DigitGroupingSymbol represents the digit grouping symbol
|
||||
type DigitGroupingSymbol byte
|
||||
|
||||
// Digit Grouping Symbol
|
||||
const (
|
||||
DIGIT_GROUPING_SYMBOL_DEFAULT DigitGroupingSymbol = 0
|
||||
DIGIT_GROUPING_SYMBOL_DOT DigitGroupingSymbol = 1
|
||||
DIGIT_GROUPING_SYMBOL_COMMA DigitGroupingSymbol = 2
|
||||
DIGIT_GROUPING_SYMBOL_SPACE DigitGroupingSymbol = 3
|
||||
DIGIT_GROUPING_SYMBOL_APOSTROPHE DigitGroupingSymbol = 4
|
||||
DIGIT_GROUPING_SYMBOL_INVALID DigitGroupingSymbol = 255
|
||||
)
|
||||
|
||||
// String returns a textual representation of the digit grouping symbol enum
|
||||
func (f DigitGroupingSymbol) String() string {
|
||||
switch f {
|
||||
case DIGIT_GROUPING_SYMBOL_DEFAULT:
|
||||
return "Default"
|
||||
case DIGIT_GROUPING_SYMBOL_DOT:
|
||||
return "Dot"
|
||||
case DIGIT_GROUPING_SYMBOL_COMMA:
|
||||
return "Comma"
|
||||
case DIGIT_GROUPING_SYMBOL_SPACE:
|
||||
return "Space"
|
||||
case DIGIT_GROUPING_SYMBOL_APOSTROPHE:
|
||||
return "Apostrophe"
|
||||
case DIGIT_GROUPING_SYMBOL_INVALID:
|
||||
return "Invalid"
|
||||
default:
|
||||
return fmt.Sprintf("Invalid(%d)", int(f))
|
||||
}
|
||||
}
|
||||
|
||||
// DigitGroupingType represents digit grouping type
|
||||
type DigitGroupingType byte
|
||||
|
||||
// Digit Grouping Type
|
||||
const (
|
||||
DIGIT_GROUPING_TYPE_DEFAULT DigitGroupingType = 0
|
||||
DIGIT_GROUPING_TYPE_NONE DigitGroupingType = 1
|
||||
DIGIT_GROUPING_TYPE_THOUSANDS_SEPARATOR DigitGroupingType = 2
|
||||
DIGIT_GROUPING_TYPE_INVALID DigitGroupingType = 255
|
||||
)
|
||||
|
||||
// String returns a textual representation of the digit grouping type enum
|
||||
func (d DigitGroupingType) String() string {
|
||||
switch d {
|
||||
case DIGIT_GROUPING_TYPE_DEFAULT:
|
||||
return "Default"
|
||||
case DIGIT_GROUPING_TYPE_NONE:
|
||||
return "None"
|
||||
case DIGIT_GROUPING_TYPE_THOUSANDS_SEPARATOR:
|
||||
return "Thousands Separator"
|
||||
case DIGIT_GROUPING_TYPE_INVALID:
|
||||
return "Invalid"
|
||||
default:
|
||||
return fmt.Sprintf("Invalid(%d)", int(d))
|
||||
}
|
||||
}
|
||||
@@ -64,6 +64,9 @@ type User struct {
|
||||
ShortDateFormat ShortDateFormat `xorm:"TINYINT"`
|
||||
LongTimeFormat LongTimeFormat `xorm:"TINYINT"`
|
||||
ShortTimeFormat ShortTimeFormat `xorm:"TINYINT"`
|
||||
DecimalSeparator DecimalSeparator `xorm:"TINYINT"`
|
||||
DigitGroupingSymbol DigitGroupingSymbol `xorm:"TINYINT"`
|
||||
DigitGrouping DigitGroupingType `xorm:"TINYINT"`
|
||||
Disabled bool
|
||||
Deleted bool `xorm:"NOT NULL"`
|
||||
EmailVerified bool `xorm:"NOT NULL"`
|
||||
@@ -89,6 +92,9 @@ type UserBasicInfo struct {
|
||||
ShortDateFormat ShortDateFormat `json:"shortDateFormat"`
|
||||
LongTimeFormat LongTimeFormat `json:"longTimeFormat"`
|
||||
ShortTimeFormat ShortTimeFormat `json:"shortTimeFormat"`
|
||||
DecimalSeparator DecimalSeparator `json:"decimalSeparator"`
|
||||
DigitGroupingSymbol DigitGroupingSymbol `json:"digitGroupingSymbol"`
|
||||
DigitGrouping DigitGroupingType `json:"digitGrouping"`
|
||||
EmailVerified bool `json:"emailVerified"`
|
||||
}
|
||||
|
||||
@@ -142,6 +148,9 @@ type UserProfileUpdateRequest struct {
|
||||
ShortDateFormat *ShortDateFormat `json:"shortDateFormat" binding:"omitempty,min=0,max=3"`
|
||||
LongTimeFormat *LongTimeFormat `json:"longTimeFormat" binding:"omitempty,min=0,max=3"`
|
||||
ShortTimeFormat *ShortTimeFormat `json:"shortTimeFormat" binding:"omitempty,min=0,max=3"`
|
||||
DecimalSeparator *DecimalSeparator `json:"decimalSeparator" binding:"omitempty,min=0,max=3"`
|
||||
DigitGroupingSymbol *DigitGroupingSymbol `json:"digitGroupingSymbol" binding:"omitempty,min=0,max=4"`
|
||||
DigitGrouping *DigitGroupingType `json:"digitGrouping" binding:"omitempty,min=0,max=2"`
|
||||
}
|
||||
|
||||
// UserProfileUpdateResponse represents the data returns to frontend after updating profile
|
||||
@@ -166,6 +175,9 @@ type UserProfileResponse struct {
|
||||
ShortDateFormat ShortDateFormat `json:"shortDateFormat"`
|
||||
LongTimeFormat LongTimeFormat `json:"longTimeFormat"`
|
||||
ShortTimeFormat ShortTimeFormat `json:"shortTimeFormat"`
|
||||
DecimalSeparator DecimalSeparator `json:"decimalSeparator"`
|
||||
DigitGroupingSymbol DigitGroupingSymbol `json:"digitGroupingSymbol"`
|
||||
DigitGrouping DigitGroupingType `json:"digitGrouping"`
|
||||
EmailVerified bool `json:"emailVerified"`
|
||||
LastLoginAt int64 `json:"lastLoginAt"`
|
||||
}
|
||||
@@ -229,6 +241,9 @@ func (u *User) ToUserBasicInfo() *UserBasicInfo {
|
||||
ShortDateFormat: u.ShortDateFormat,
|
||||
LongTimeFormat: u.LongTimeFormat,
|
||||
ShortTimeFormat: u.ShortTimeFormat,
|
||||
DecimalSeparator: u.DecimalSeparator,
|
||||
DigitGroupingSymbol: u.DigitGroupingSymbol,
|
||||
DigitGrouping: u.DigitGrouping,
|
||||
EmailVerified: u.EmailVerified,
|
||||
}
|
||||
}
|
||||
@@ -250,6 +265,9 @@ func (u *User) ToUserProfileResponse() *UserProfileResponse {
|
||||
ShortDateFormat: u.ShortDateFormat,
|
||||
LongTimeFormat: u.LongTimeFormat,
|
||||
ShortTimeFormat: u.ShortTimeFormat,
|
||||
DecimalSeparator: u.DecimalSeparator,
|
||||
DigitGroupingSymbol: u.DigitGroupingSymbol,
|
||||
DigitGrouping: u.DigitGrouping,
|
||||
EmailVerified: u.EmailVerified,
|
||||
LastLoginAt: u.LastLoginUnixTime,
|
||||
}
|
||||
|
||||
@@ -248,6 +248,18 @@ func (s *UserService) UpdateUser(c *core.Context, user *models.User, modifyUserL
|
||||
updateCols = append(updateCols, "short_time_format")
|
||||
}
|
||||
|
||||
if models.DECIMAL_SEPARATOR_DEFAULT <= user.DecimalSeparator && user.DecimalSeparator <= models.DECIMAL_SEPARATOR_SPACE {
|
||||
updateCols = append(updateCols, "decimal_separator")
|
||||
}
|
||||
|
||||
if models.DIGIT_GROUPING_SYMBOL_DEFAULT <= user.DigitGroupingSymbol && user.DigitGroupingSymbol <= models.DIGIT_GROUPING_SYMBOL_APOSTROPHE {
|
||||
updateCols = append(updateCols, "digit_grouping_symbol")
|
||||
}
|
||||
|
||||
if models.DIGIT_GROUPING_TYPE_DEFAULT <= user.DigitGrouping && user.DigitGrouping <= models.DIGIT_GROUPING_TYPE_THOUSANDS_SEPARATOR {
|
||||
updateCols = append(updateCols, "digit_grouping")
|
||||
}
|
||||
|
||||
user.UpdatedUnixTime = now
|
||||
updateCols = append(updateCols, "updated_unix_time")
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<template>
|
||||
<v-text-field class="text-field-with-colored-label"
|
||||
:type="hide ? 'password' : 'number'" :class="extraClass"
|
||||
:type="hide ? 'password' : 'text'" :class="extraClass"
|
||||
:color="color" :base-color="color"
|
||||
:density="density" :readonly="!!readonly" :disabled="!!disabled"
|
||||
:label="label" :placeholder="placeholder"
|
||||
:persistent-placeholder="!!persistentPlaceholder"
|
||||
:rules="enableRules ? rules : []" v-model="currentValue"
|
||||
@keydown="onKeyUpDown" @keyup="onKeyUpDown">
|
||||
@keydown="onKeyUpDown" @keyup="onKeyUpDown" @paste="onPaste">
|
||||
<template #prepend-inner v-if="currency && prependText">
|
||||
<div>{{ prependText }}</div>
|
||||
</template>
|
||||
@@ -19,9 +19,10 @@
|
||||
<script>
|
||||
import { mapStores } from 'pinia';
|
||||
import { useSettingsStore } from '@/stores/setting.js';
|
||||
import { useUserStore } from '@/stores/user.js';
|
||||
|
||||
import transactionConstants from '@/consts/transaction.js';
|
||||
import { numericCurrencyToString, stringCurrencyToNumeric } from '@/lib/currency.js';
|
||||
import { removeAll } from '@/lib/common.js';
|
||||
|
||||
export default {
|
||||
props: [
|
||||
@@ -43,9 +44,10 @@ export default {
|
||||
],
|
||||
data() {
|
||||
const self = this;
|
||||
const userStore = useUserStore();
|
||||
|
||||
return {
|
||||
currentValue: numericCurrencyToString(self.modelValue),
|
||||
currentValue: self.getFormattedValue(userStore, self.modelValue),
|
||||
rules: [
|
||||
(v) => {
|
||||
if (v === '') {
|
||||
@@ -53,8 +55,13 @@ export default {
|
||||
}
|
||||
|
||||
try {
|
||||
const val = parseFloat(v);
|
||||
return (val >= transactionConstants.minAmount && val <= transactionConstants.maxAmount) || self.$t('Amount value exceeds limitation');
|
||||
const val = self.$locale.parseAmount(userStore, v);
|
||||
|
||||
if (Number.isNaN(val) || !Number.isFinite(val)) {
|
||||
return self.$t('Amount value is not number');
|
||||
}
|
||||
|
||||
return (val >= transactionConstants.minAmountNumber && val <= transactionConstants.maxAmountNumber) || self.$t('Amount value exceeds limitation');
|
||||
} catch (e) {
|
||||
return self.$t('Amount value is not number');
|
||||
}
|
||||
@@ -63,7 +70,7 @@ export default {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapStores(useSettingsStore),
|
||||
...mapStores(useSettingsStore, useUserStore),
|
||||
extraClass() {
|
||||
let finalClass = this.class;
|
||||
|
||||
@@ -106,10 +113,10 @@ export default {
|
||||
},
|
||||
watch: {
|
||||
'modelValue': function (newValue) {
|
||||
const numericCurrentValue = stringCurrencyToNumeric(this.currentValue);
|
||||
const numericCurrentValue = this.$locale.parseAmount(this.userStore, this.currentValue);
|
||||
|
||||
if (newValue !== numericCurrentValue) {
|
||||
const newStringValue = numericCurrencyToString(newValue, false, true);
|
||||
const newStringValue = this.getFormattedValue(this.userStore, newValue);
|
||||
|
||||
if (!(newStringValue === '0' && this.currentValue === '')) {
|
||||
this.currentValue = newStringValue;
|
||||
@@ -117,57 +124,156 @@ export default {
|
||||
}
|
||||
},
|
||||
'currentValue': function (newValue) {
|
||||
this.$emit('update:modelValue', stringCurrencyToNumeric(newValue));
|
||||
this.$emit('update:modelValue', this.$locale.parseAmount(this.userStore, newValue));
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onKeyUpDown(e) {
|
||||
if (e.target.value === '' || e.target.value === 0) {
|
||||
if (e.altKey || e.ctrlKey || e.metaKey || (e.code.indexOf('F') === 0 && (e.code.length === 2 || e.code.length === 3))
|
||||
|| e.code === 'ArrowLeft' || e.code === 'ArrowRight'
|
||||
|| e.code === 'Home' || e.code === 'End' || e.code === 'Tab'
|
||||
|| e.code === 'Backspace' || e.code === 'Delete' || e.code === 'Del') {
|
||||
return;
|
||||
}
|
||||
|
||||
const digitGroupingSymbol = this.$locale.getCurrentDigitGroupingSymbol(this.userStore);
|
||||
const decimalSeparator = this.$locale.getCurrentDecimalSeparator(this.userStore);
|
||||
|
||||
if (e.code.indexOf('Digit') !== 0 && e.code !== 'Minus' && e.key !== decimalSeparator) {
|
||||
e.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
let str = e.target.value;
|
||||
|
||||
if (str.indexOf(digitGroupingSymbol) >= 0) {
|
||||
str = removeAll(str, digitGroupingSymbol);
|
||||
}
|
||||
|
||||
if (e.code === 'Minus' && str.lastIndexOf('-') > 0) {
|
||||
const lastMinusPos = str.lastIndexOf('-');
|
||||
e.target.value = str.substring(0, lastMinusPos) + str.substring(lastMinusPos + 1, str.length);
|
||||
this.currentValue = e.target.value;
|
||||
e.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.key === decimalSeparator && str.indexOf(decimalSeparator) !== str.lastIndexOf(decimalSeparator)) {
|
||||
const lastDecimalSeparatorPos = str.lastIndexOf(decimalSeparator);
|
||||
e.target.value = str.substring(0, lastDecimalSeparatorPos) + str.substring(lastDecimalSeparatorPos + 1, str.length);
|
||||
this.currentValue = e.target.value;
|
||||
e.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.key === decimalSeparator && (str.indexOf(decimalSeparator) === 0 || (str.indexOf(decimalSeparator) === 1 && str.charAt(0) === '-'))) {
|
||||
const negative = str.charAt(0) === '-';
|
||||
|
||||
if (negative) {
|
||||
str = str.substring(1);
|
||||
}
|
||||
|
||||
str = (negative ? '-0' : '0') + str;
|
||||
e.target.value = str;
|
||||
this.currentValue = e.target.value;
|
||||
e.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
let decimalLength = 0;
|
||||
let decimalIndex = e.target.value.indexOf('.');
|
||||
let decimalIndex = str.indexOf(decimalSeparator);
|
||||
|
||||
if (decimalIndex >= 0) {
|
||||
decimalLength = e.target.value.length - e.target.value.indexOf('.') - 1;
|
||||
}
|
||||
decimalLength = str.length - str.indexOf(decimalSeparator) - 1;
|
||||
} else if ((str.startsWith('0') && str.length >= 2) || (str.startsWith('-0') && str.length >= 3)) {
|
||||
const negative = str.charAt(0) === '-';
|
||||
|
||||
if (negative) {
|
||||
str = str.substring(1);
|
||||
}
|
||||
|
||||
while (str.charAt(0) === '0' && (str.length >= 2 || e.code !== 'Digit0')) {
|
||||
str = str.substring(1);
|
||||
}
|
||||
|
||||
e.target.value = (negative ? '-' : '') + str;
|
||||
this.currentValue = e.target.value;
|
||||
e.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
if (decimalLength > 2) {
|
||||
e.target.value = e.target.value.substring(0, Math.min(decimalIndex + 3, e.target.value.length - 1));
|
||||
e.target.value = str.substring(0, Math.min(decimalIndex + 3, str.length - 1));
|
||||
this.currentValue = e.target.value;
|
||||
e.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const val = this.$locale.parseAmount(this.userStore, str);
|
||||
const finalValue = this.getValidFormattedValue(val, str, decimalIndex >= 0);
|
||||
|
||||
const val = parseFloat(e.target.value);
|
||||
let maxLength = transactionConstants.maxAmount.toString().length;
|
||||
|
||||
if (val < 0) {
|
||||
maxLength = transactionConstants.minAmount.toString().length;
|
||||
}
|
||||
|
||||
if (val < transactionConstants.minAmount) {
|
||||
e.target.value = transactionConstants.minAmount;
|
||||
this.currentValue = e.target.value;
|
||||
e.preventDefault();
|
||||
} else if (val > transactionConstants.maxAmount) {
|
||||
e.target.value = transactionConstants.maxAmount;
|
||||
this.currentValue = e.target.value;
|
||||
e.preventDefault();
|
||||
} else if (e.target.value.length > maxLength) {
|
||||
e.target.value = e.target.value.substring(0, maxLength);
|
||||
this.currentValue = e.target.value;
|
||||
if (finalValue !== str) {
|
||||
e.target.value = finalValue;
|
||||
this.currentValue = finalValue;
|
||||
e.preventDefault();
|
||||
}
|
||||
} catch (e) {
|
||||
e.target.value = 0;
|
||||
e.target.value = '0';
|
||||
}
|
||||
},
|
||||
onPaste(e) {
|
||||
if (!e.clipboardData) {
|
||||
e.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
const text = e.clipboardData.getData('Text');
|
||||
|
||||
if (!text) {
|
||||
e.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
const value = this.$locale.parseAmount(this.userStore, text);
|
||||
const textualValue = this.getFormattedValue(this.userStore, value);
|
||||
const decimalSeparator = this.$locale.getCurrentDecimalSeparator(this.userStore);
|
||||
const hasDecimalSeparator = text.indexOf(decimalSeparator) >= 0;
|
||||
|
||||
this.currentValue = this.getValidFormattedValue(value, textualValue, hasDecimalSeparator);
|
||||
e.preventDefault();
|
||||
},
|
||||
getValidFormattedValue(value, textualValue, hasDecimalSeparator) {
|
||||
let maxLength = transactionConstants.maxAmountNumber.toString().length;
|
||||
|
||||
if (value < 0) {
|
||||
maxLength = transactionConstants.minAmountNumber.toString().length;
|
||||
}
|
||||
|
||||
if (value < transactionConstants.minAmountNumber) {
|
||||
return this.getFormattedValue(this.userStore, transactionConstants.minAmountNumber);
|
||||
} else if (value > transactionConstants.maxAmountNumber) {
|
||||
return this.getFormattedValue(this.userStore, transactionConstants.maxAmountNumber);
|
||||
}
|
||||
|
||||
if (!hasDecimalSeparator && textualValue.length > maxLength) {
|
||||
return textualValue.substring(0, maxLength);
|
||||
} else if (hasDecimalSeparator && textualValue.length > maxLength + 1) {
|
||||
return textualValue.substring(0, maxLength + 1);
|
||||
}
|
||||
|
||||
return textualValue;
|
||||
},
|
||||
getFormattedValue(userStore, value) {
|
||||
if (!Number.isNaN(value) && Number.isFinite(value)) {
|
||||
const digitGroupingSymbol = this.$locale.getCurrentDigitGroupingSymbol(userStore);
|
||||
return removeAll(this.$locale.formatAmount(userStore, value), digitGroupingSymbol);
|
||||
}
|
||||
|
||||
return '0';
|
||||
},
|
||||
getDisplayCurrencyPrependAndAppendText() {
|
||||
return this.$locale.getDisplayCurrencyPrependAndAppendText(this.currency, this.settingsStore.appSettings.currencyDisplayMode);
|
||||
return this.$locale.getAmountPrependAndAppendText(this.settingsStore, this.userStore, this.currency);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import { useTheme } from 'vuetify';
|
||||
|
||||
import { mapStores } from 'pinia';
|
||||
import { useSettingsStore } from '@/stores/setting.js';
|
||||
import { useUserStore } from '@/stores/user.js';
|
||||
|
||||
import colorConstants from '@/consts/color.js';
|
||||
import { formatPercent } from '@/lib/numeral.js';
|
||||
@@ -37,7 +38,7 @@ export default {
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapStores(useSettingsStore),
|
||||
...mapStores(useSettingsStore, useUserStore),
|
||||
isDarkMode() {
|
||||
return this.globalTheme.global.name.value === 'dark';
|
||||
},
|
||||
@@ -289,10 +290,7 @@ export default {
|
||||
return color;
|
||||
},
|
||||
getDisplayCurrency(value, currencyCode) {
|
||||
return this.$locale.getDisplayCurrency(value, currencyCode, {
|
||||
currencyDisplayMode: this.settingsStore.appSettings.currencyDisplayMode,
|
||||
enableThousandsSeparator: this.settingsStore.appSettings.thousandsSeparator
|
||||
});
|
||||
return this.$locale.formatAmountWithCurrency(this.settingsStore, this.userStore, value, currencyCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -353,10 +353,7 @@ export default {
|
||||
this.selectedLegends = e.selected;
|
||||
},
|
||||
getDisplayCurrency(value, currencyCode) {
|
||||
return this.$locale.getDisplayCurrency(value, currencyCode, {
|
||||
currencyDisplayMode: this.settingsStore.appSettings.currencyDisplayMode,
|
||||
enableThousandsSeparator: this.settingsStore.appSettings.thousandsSeparator
|
||||
});
|
||||
return this.$locale.formatAmountWithCurrency(this.settingsStore, this.userStore, value, currencyCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,8 +43,8 @@
|
||||
<f7-button class="numpad-button numpad-button-function no-right-border" @click="setSymbol('+')">
|
||||
<span class="numpad-button-text numpad-button-text-normal">+</span>
|
||||
</f7-button>
|
||||
<f7-button class="numpad-button numpad-button-num" @click="inputDot()">
|
||||
<span class="numpad-button-text numpad-button-text-normal">.</span>
|
||||
<f7-button class="numpad-button numpad-button-num" @click="inputDecimalSeparator()">
|
||||
<span class="numpad-button-text numpad-button-text-normal">{{ decimalSeparator }}</span>
|
||||
</f7-button>
|
||||
<f7-button class="numpad-button numpad-button-num" @click="inputNum(0)">
|
||||
<span class="numpad-button-text numpad-button-text-normal">0</span>
|
||||
@@ -64,11 +64,9 @@
|
||||
|
||||
<script>
|
||||
import { mapStores } from 'pinia';
|
||||
import { useSettingsStore } from '@/stores/setting.js';
|
||||
import { useUserStore } from '@/stores/user.js';
|
||||
|
||||
import { isString } from '@/lib/common.js';
|
||||
import { appendThousandsSeparator } from '@/lib/numeral.js';
|
||||
import { numericCurrencyToString, stringCurrencyToNumeric } from '@/lib/currency.js';
|
||||
import { isNumber, removeAll } from '@/lib/common.js';
|
||||
|
||||
export default {
|
||||
props: [
|
||||
@@ -83,21 +81,22 @@ export default {
|
||||
],
|
||||
data() {
|
||||
const self = this;
|
||||
const userStore = useUserStore();
|
||||
|
||||
return {
|
||||
previousValue: '',
|
||||
currentSymbol: '',
|
||||
currentValue: self.getStringValue(self.modelValue)
|
||||
currentValue: self.getStringValue(userStore, self.modelValue)
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapStores(useSettingsStore),
|
||||
isEnableThousandsSeparator() {
|
||||
return this.settingsStore.appSettings.thousandsSeparator;
|
||||
...mapStores(useUserStore),
|
||||
decimalSeparator() {
|
||||
return this.$locale.getCurrentDecimalSeparator(this.userStore);
|
||||
},
|
||||
currentDisplay() {
|
||||
const previousValue = appendThousandsSeparator(this.previousValue, this.isEnableThousandsSeparator);
|
||||
const currentValue = appendThousandsSeparator(this.currentValue, this.isEnableThousandsSeparator);
|
||||
const previousValue = this.$locale.appendDigitGroupingSymbol(this.userStore, this.previousValue);
|
||||
const currentValue = this.$locale.appendDigitGroupingSymbol(this.userStore, this.currentValue);
|
||||
|
||||
if (this.currentSymbol) {
|
||||
return `${previousValue} ${this.currentSymbol} ${currentValue}`;
|
||||
@@ -125,16 +124,19 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getStringValue(value) {
|
||||
let str = numericCurrencyToString(value, this.isEnableThousandsSeparator);
|
||||
getStringValue(userStore, value) {
|
||||
let str = this.$locale.formatAmount(userStore, value);
|
||||
|
||||
if (str.indexOf(',')) {
|
||||
str = str.replaceAll(/,/g, '');
|
||||
const digitGroupingSymbol = this.$locale.getCurrentDigitGroupingSymbol(userStore);
|
||||
|
||||
if (str.indexOf(digitGroupingSymbol) >= 0) {
|
||||
str = removeAll(str, digitGroupingSymbol);
|
||||
}
|
||||
|
||||
const dotPos = str.indexOf('.');
|
||||
const decimalSeparator = this.$locale.getCurrentDecimalSeparator(userStore);
|
||||
const decimalSeparatorPos = str.indexOf(decimalSeparator);
|
||||
|
||||
if (dotPos < 0) {
|
||||
if (decimalSeparatorPos < 0) {
|
||||
if (str === '0') {
|
||||
return '';
|
||||
}
|
||||
@@ -142,8 +144,8 @@ export default {
|
||||
return str;
|
||||
}
|
||||
|
||||
let integer = str.substring(0, dotPos);
|
||||
let decimals = str.substring(dotPos + 1, str.length);
|
||||
let integer = str.substring(0, decimalSeparatorPos);
|
||||
let decimals = str.substring(decimalSeparatorPos + 1, str.length);
|
||||
let newDecimals = '';
|
||||
|
||||
for (let i = decimals.length - 1; i >= 0; i--) {
|
||||
@@ -160,7 +162,7 @@ export default {
|
||||
return integer;
|
||||
}
|
||||
|
||||
return `${integer}.${newDecimals}`;
|
||||
return `${integer}${decimalSeparator}${newDecimals}`;
|
||||
},
|
||||
inputNum(num) {
|
||||
if (!this.previousValue && this.currentSymbol === '−') {
|
||||
@@ -176,36 +178,34 @@ export default {
|
||||
return;
|
||||
}
|
||||
|
||||
const dotPos = this.currentValue.indexOf('.');
|
||||
const decimalSeparatorPos = this.currentValue.indexOf(this.decimalSeparator);
|
||||
|
||||
if (dotPos >= 0 && this.currentValue.substring(dotPos + 1, this.currentValue.length).length >= 2) {
|
||||
if (decimalSeparatorPos >= 0 && this.currentValue.substring(decimalSeparatorPos + 1, this.currentValue.length).length >= 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
const newValue = this.currentValue + num.toString();
|
||||
|
||||
if (isString(this.minValue) && this.minValue !== '') {
|
||||
const min = stringCurrencyToNumeric(this.minValue);
|
||||
const current = stringCurrencyToNumeric(newValue);
|
||||
if (isNumber(this.minValue)) {
|
||||
const current = this.$locale.parseAmount(this.userStore, newValue);
|
||||
|
||||
if (current < min) {
|
||||
if (current < this.minValue) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (isString(this.maxValue) && this.maxValue !== '') {
|
||||
const max = stringCurrencyToNumeric(this.maxValue);
|
||||
const current = stringCurrencyToNumeric(newValue);
|
||||
if (isNumber(this.maxValue)) {
|
||||
const current = this.$locale.parseAmount(this.userStore, newValue);
|
||||
|
||||
if (current > max) {
|
||||
if (current > this.maxValue) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.currentValue = newValue;
|
||||
},
|
||||
inputDot() {
|
||||
if (this.currentValue.indexOf('.') >= 0) {
|
||||
inputDecimalSeparator() {
|
||||
if (this.currentValue.indexOf(this.decimalSeparator) >= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -220,7 +220,7 @@ export default {
|
||||
this.currentValue = '-0';
|
||||
}
|
||||
|
||||
this.currentValue = this.currentValue + '.';
|
||||
this.currentValue = this.currentValue + this.decimalSeparator;
|
||||
},
|
||||
setSymbol(symbol) {
|
||||
if (this.currentValue) {
|
||||
@@ -258,8 +258,8 @@ export default {
|
||||
},
|
||||
confirm() {
|
||||
if (this.currentSymbol && this.currentValue.length >= 1) {
|
||||
const previousValue = stringCurrencyToNumeric(this.previousValue);
|
||||
const currentValue = stringCurrencyToNumeric(this.currentValue);
|
||||
const previousValue = this.$locale.parseAmount(this.userStore, this.previousValue);
|
||||
const currentValue = this.$locale.parseAmount(this.userStore, this.currentValue);
|
||||
let finalValue = 0;
|
||||
|
||||
switch (this.currentSymbol) {
|
||||
@@ -276,25 +276,21 @@ export default {
|
||||
finalValue = previousValue;
|
||||
}
|
||||
|
||||
if (isString(this.minValue) && this.minValue !== '') {
|
||||
const min = stringCurrencyToNumeric(this.minValue);
|
||||
|
||||
if (finalValue < min) {
|
||||
if (isNumber(this.minValue)) {
|
||||
if (finalValue < this.minValue) {
|
||||
this.$toast('Numeric Overflow');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (isString(this.maxValue) && this.maxValue !== '') {
|
||||
const max = stringCurrencyToNumeric(this.maxValue);
|
||||
|
||||
if (finalValue > max) {
|
||||
if (isNumber(this.maxValue)) {
|
||||
if (finalValue > this.maxValue) {
|
||||
this.$toast('Numeric Overflow');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
this.currentValue = this.getStringValue(finalValue);
|
||||
this.currentValue = this.getStringValue(this.userStore, finalValue);
|
||||
this.previousValue = '';
|
||||
this.currentSymbol = '';
|
||||
|
||||
@@ -306,7 +302,7 @@ export default {
|
||||
|
||||
return true;
|
||||
} else {
|
||||
const value = stringCurrencyToNumeric(this.currentValue);
|
||||
const value = this.$locale.parseAmount(this.userStore, this.currentValue);
|
||||
|
||||
this.$emit('update:modelValue', value);
|
||||
this.close();
|
||||
@@ -318,7 +314,7 @@ export default {
|
||||
this.$emit('update:show', false);
|
||||
},
|
||||
onSheetOpen() {
|
||||
this.currentValue = this.getStringValue(this.modelValue);
|
||||
this.currentValue = this.getStringValue(this.userStore, this.modelValue);
|
||||
},
|
||||
onSheetClosed() {
|
||||
this.close();
|
||||
|
||||
@@ -79,6 +79,7 @@
|
||||
<script>
|
||||
import { mapStores } from 'pinia';
|
||||
import { useSettingsStore } from '@/stores/setting.js';
|
||||
import { useUserStore } from '@/stores/user.js';
|
||||
|
||||
import colorConstants from '@/consts/color.js';
|
||||
import { formatPercent } from '@/lib/numeral.js';
|
||||
@@ -113,7 +114,7 @@ export default {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapStores(useSettingsStore),
|
||||
...mapStores(useSettingsStore, useUserStore),
|
||||
validItems: function () {
|
||||
let totalValidValue = 0;
|
||||
|
||||
@@ -272,10 +273,7 @@ export default {
|
||||
return this.circumference - allPreviousLength + offset;
|
||||
},
|
||||
getDisplayCurrency(value, currencyCode) {
|
||||
return this.$locale.getDisplayCurrency(value, currencyCode, {
|
||||
currencyDisplayMode: this.settingsStore.appSettings.currencyDisplayMode,
|
||||
enableThousandsSeparator: this.settingsStore.appSettings.thousandsSeparator
|
||||
});
|
||||
return this.$locale.formatAmountWithCurrency(this.settingsStore, this.userStore, value, currencyCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
const allDecimalSeparator = {
|
||||
Dot: {
|
||||
type: 1,
|
||||
name: 'Dot',
|
||||
symbol: '.'
|
||||
},
|
||||
Comma: {
|
||||
type: 2,
|
||||
name: 'Comma',
|
||||
symbol: ','
|
||||
},
|
||||
Space: {
|
||||
type: 3,
|
||||
name: 'Space',
|
||||
symbol: ' '
|
||||
}
|
||||
};
|
||||
|
||||
const allDecimalSeparatorArray = [
|
||||
allDecimalSeparator.Dot,
|
||||
allDecimalSeparator.Comma,
|
||||
allDecimalSeparator.Space
|
||||
];
|
||||
|
||||
const allDecimalSeparatorMap = {
|
||||
[allDecimalSeparator.Dot.type]: allDecimalSeparator.Dot,
|
||||
[allDecimalSeparator.Comma.type]: allDecimalSeparator.Comma,
|
||||
[allDecimalSeparator.Space.type]: allDecimalSeparator.Space
|
||||
};
|
||||
|
||||
const allDigitGroupingSymbol = {
|
||||
Dot: {
|
||||
type: 1,
|
||||
name: 'Dot',
|
||||
symbol: '.'
|
||||
},
|
||||
Comma: {
|
||||
type: 2,
|
||||
name: 'Comma',
|
||||
symbol: ','
|
||||
},
|
||||
Space: {
|
||||
type: 3,
|
||||
name: 'Space',
|
||||
symbol: ' '
|
||||
},
|
||||
Apostrophe: {
|
||||
type: 4,
|
||||
name: 'Apostrophe',
|
||||
symbol: '\''
|
||||
}
|
||||
};
|
||||
|
||||
const allDigitGroupingSymbolArray = [
|
||||
allDigitGroupingSymbol.Dot,
|
||||
allDigitGroupingSymbol.Comma,
|
||||
allDigitGroupingSymbol.Space,
|
||||
allDigitGroupingSymbol.Apostrophe
|
||||
];
|
||||
|
||||
const allDigitGroupingSymbolMap = {
|
||||
[allDigitGroupingSymbol.Dot.type]: allDigitGroupingSymbol.Dot,
|
||||
[allDigitGroupingSymbol.Comma.type]: allDigitGroupingSymbol.Comma,
|
||||
[allDigitGroupingSymbol.Space.type]: allDigitGroupingSymbol.Space,
|
||||
[allDigitGroupingSymbol.Apostrophe.type]: allDigitGroupingSymbol.Apostrophe
|
||||
};
|
||||
|
||||
const allDigitGroupingType = {
|
||||
None: {
|
||||
type: 1,
|
||||
name: 'None'
|
||||
},
|
||||
ThousandsSeparator: {
|
||||
type: 2,
|
||||
name: 'Thousands Separator'
|
||||
}
|
||||
};
|
||||
|
||||
const allDigitGroupingTypeArray = [
|
||||
allDigitGroupingType.None,
|
||||
allDigitGroupingType.ThousandsSeparator
|
||||
];
|
||||
|
||||
const allDigitGroupingTypeMap = {
|
||||
[allDigitGroupingType.None.type]: allDigitGroupingType.None,
|
||||
[allDigitGroupingType.ThousandsSeparator.type]: allDigitGroupingType.ThousandsSeparator
|
||||
};
|
||||
|
||||
const defaultDecimalSeparator = allDecimalSeparator.Dot;
|
||||
const defaultDigitGroupingSymbol = allDigitGroupingSymbol.Comma;
|
||||
const defaultDigitGroupingType = allDigitGroupingType.ThousandsSeparator;
|
||||
const defaultValue = 0;
|
||||
|
||||
export default {
|
||||
allDecimalSeparator: allDecimalSeparator,
|
||||
allDecimalSeparatorArray: allDecimalSeparatorArray,
|
||||
allDecimalSeparatorMap: allDecimalSeparatorMap,
|
||||
allDigitGroupingSymbol: allDigitGroupingSymbol,
|
||||
allDigitGroupingSymbolArray: allDigitGroupingSymbolArray,
|
||||
allDigitGroupingSymbolMap: allDigitGroupingSymbolMap,
|
||||
allDigitGroupingType: allDigitGroupingType,
|
||||
allDigitGroupingTypeArray: allDigitGroupingTypeArray,
|
||||
allDigitGroupingTypeMap: allDigitGroupingTypeMap,
|
||||
defaultDecimalSeparator: defaultDecimalSeparator,
|
||||
defaultDigitGroupingSymbol: defaultDigitGroupingSymbol,
|
||||
defaultDigitGroupingType: defaultDigitGroupingType,
|
||||
defaultValue: defaultValue,
|
||||
};
|
||||
@@ -5,11 +5,11 @@ const allTransactionTypes = {
|
||||
Transfer: 4
|
||||
};
|
||||
|
||||
const minAmount = '-999999999.99';
|
||||
const maxAmount = '999999999.99';
|
||||
const minAmountNumber = -99999999999; // -999999999.99
|
||||
const maxAmountNumber = 99999999999; // 999999999.99
|
||||
|
||||
export default {
|
||||
allTransactionTypes: allTransactionTypes,
|
||||
minAmount: minAmount,
|
||||
maxAmount: maxAmount,
|
||||
minAmountNumber: minAmountNumber,
|
||||
maxAmountNumber: maxAmountNumber,
|
||||
};
|
||||
|
||||
@@ -109,6 +109,14 @@ export function getObjectOwnFieldCount(object) {
|
||||
return count;
|
||||
}
|
||||
|
||||
export function replaceAll(value, originalValue, targetValue) {
|
||||
return value.replaceAll(new RegExp(originalValue, 'g'), targetValue);
|
||||
}
|
||||
|
||||
export function removeAll(value, originalValue) {
|
||||
return replaceAll(value, originalValue, '');
|
||||
}
|
||||
|
||||
export function limitText(value, maxLength) {
|
||||
let length = 0;
|
||||
|
||||
|
||||
@@ -1,153 +0,0 @@
|
||||
import { isNumber } from './common.js';
|
||||
import { appendThousandsSeparator } from './numeral.js';
|
||||
|
||||
export function numericCurrencyToString(num, enableThousandsSeparator, trimTailZero) {
|
||||
let str = num.toString();
|
||||
const negative = str.charAt(0) === '-';
|
||||
|
||||
if (negative) {
|
||||
str = str.substring(1);
|
||||
}
|
||||
|
||||
let integer = '0';
|
||||
let decimals = '00';
|
||||
|
||||
if (str.length > 2) {
|
||||
integer = str.substring(0, str.length - 2);
|
||||
decimals = str.substring(str.length - 2);
|
||||
} else if (str.length === 2) {
|
||||
decimals = str;
|
||||
} else if (str.length === 1) {
|
||||
decimals = '0' + str;
|
||||
}
|
||||
|
||||
if (trimTailZero) {
|
||||
if (decimals.charAt(0) === '0' && decimals.charAt(1) === '0') {
|
||||
decimals = '';
|
||||
} else if (decimals.charAt(0) !== '0' && decimals.charAt(1) === '0') {
|
||||
decimals = decimals.charAt(0);
|
||||
}
|
||||
}
|
||||
|
||||
integer = appendThousandsSeparator(integer, enableThousandsSeparator);
|
||||
|
||||
if (decimals !== '') {
|
||||
str = `${integer}.${decimals}`;
|
||||
} else {
|
||||
str = integer;
|
||||
}
|
||||
|
||||
if (negative) {
|
||||
str = `-${str}`;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
export function stringCurrencyToNumeric(str) {
|
||||
if (!str || str.length < 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const negative = str.charAt(0) === '-';
|
||||
|
||||
if (negative) {
|
||||
str = str.substring(1);
|
||||
}
|
||||
|
||||
if (!str || str.length < 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const sign = negative ? -1 : 1;
|
||||
|
||||
if (str.indexOf(',')) {
|
||||
str = str.replaceAll(/,/g, '');
|
||||
}
|
||||
|
||||
let dotPos = str.indexOf('.');
|
||||
|
||||
if (dotPos < 0) {
|
||||
return sign * parseInt(str) * 100;
|
||||
} else if (dotPos === 0) {
|
||||
str = '0' + str;
|
||||
dotPos++;
|
||||
}
|
||||
|
||||
const integer = str.substring(0, dotPos);
|
||||
const decimals = str.substring(dotPos + 1, str.length);
|
||||
|
||||
if (decimals.length < 1) {
|
||||
return sign * parseInt(integer) * 100;
|
||||
} else if (decimals.length === 1) {
|
||||
return sign * parseInt(integer) * 100 + sign * parseInt(decimals) * 10;
|
||||
} else if (decimals.length === 2) {
|
||||
return sign * parseInt(integer) * 100 + sign * parseInt(decimals);
|
||||
} else {
|
||||
return sign * parseInt(integer) * 100 + sign * parseInt(decimals.substring(0, 2));
|
||||
}
|
||||
}
|
||||
|
||||
export function getExchangedAmount(amount, fromRate, toRate) {
|
||||
const exchangeRate = parseFloat(toRate) / parseFloat(fromRate);
|
||||
|
||||
if (!isNumber(exchangeRate)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return amount * exchangeRate;
|
||||
}
|
||||
|
||||
export function getConvertedAmount(baseAmount, fromExchangeRate, toExchangeRate) {
|
||||
if (!fromExchangeRate || !toExchangeRate) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (baseAmount === '') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return getExchangedAmount(baseAmount, fromExchangeRate.rate, toExchangeRate.rate);
|
||||
}
|
||||
|
||||
export function getDisplayExchangeRateAmount(rateStr, isEnableThousandsSeparator) {
|
||||
if (rateStr.indexOf('.') < 0) {
|
||||
return appendThousandsSeparator(rateStr, isEnableThousandsSeparator);
|
||||
} else {
|
||||
let firstNonZeroPos = 0;
|
||||
|
||||
for (let i = 0; i < rateStr.length; i++) {
|
||||
if (rateStr.charAt(i) !== '.' && rateStr.charAt(i) !== '0') {
|
||||
firstNonZeroPos = Math.min(i + 4, rateStr.length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const trimmedRateStr = rateStr.substring(0, Math.max(6, Math.max(firstNonZeroPos, rateStr.indexOf('.') + 2)));
|
||||
return appendThousandsSeparator(trimmedRateStr, isEnableThousandsSeparator);
|
||||
}
|
||||
}
|
||||
|
||||
export function getAdaptiveDisplayAmountRate(amount1, amount2, fromExchangeRate, toExchangeRate, isEnableThousandsSeparator) {
|
||||
if (!amount1 || !amount2 || amount1 === amount2) {
|
||||
if (!fromExchangeRate || !fromExchangeRate.rate || !toExchangeRate || !toExchangeRate.rate) {
|
||||
return null;
|
||||
}
|
||||
|
||||
amount1 = fromExchangeRate.rate;
|
||||
amount2 = toExchangeRate.rate;
|
||||
}
|
||||
|
||||
amount1 = parseFloat(amount1);
|
||||
amount2 = parseFloat(amount2);
|
||||
|
||||
if (amount1 > amount2) {
|
||||
const rateStr = (amount1 / amount2).toString();
|
||||
const displayRateStr = getDisplayExchangeRateAmount(rateStr, isEnableThousandsSeparator);
|
||||
return `${displayRateStr} : 1`;
|
||||
} else {
|
||||
const rateStr = (amount2 / amount1).toString();
|
||||
const displayRateStr = getDisplayExchangeRateAmount(rateStr, isEnableThousandsSeparator);
|
||||
return `1 : ${displayRateStr}`;
|
||||
}
|
||||
}
|
||||
+251
-93
@@ -1,6 +1,7 @@
|
||||
import moment from 'moment-timezone';
|
||||
|
||||
import { defaultLanguage, allLanguages } from '@/locales/index.js';
|
||||
import numeral from '@/consts/numeral.js';
|
||||
import datetime from '@/consts/datetime.js';
|
||||
import timezone from '@/consts/timezone.js';
|
||||
import currency from '@/consts/currency.js';
|
||||
@@ -11,6 +12,7 @@ import statistics from '@/consts/statistics.js';
|
||||
import {
|
||||
isString,
|
||||
isNumber,
|
||||
isBoolean,
|
||||
getTextBefore,
|
||||
getTextAfter,
|
||||
copyObjectTo,
|
||||
@@ -36,8 +38,12 @@ import {
|
||||
} from './datetime.js';
|
||||
|
||||
import {
|
||||
numericCurrencyToString
|
||||
} from './currency.js';
|
||||
appendDigitGroupingSymbol,
|
||||
parseAmount,
|
||||
formatAmount,
|
||||
formatExchangeRateAmount,
|
||||
getAdaptiveDisplayAmountRate
|
||||
} from './numeral.js';
|
||||
|
||||
import {
|
||||
getCategorizedAccounts,
|
||||
@@ -781,6 +787,231 @@ function getAllTimezoneTypesUsedForStatistics(currentTimezone, translateFn) {
|
||||
];
|
||||
}
|
||||
|
||||
function getAllDecimalSeparators(translateFn) {
|
||||
const defaultDecimalSeparatorTypeName = translateFn('default.decimalSeparator');
|
||||
return getNumeralSeparatorFormats(translateFn, numeral.allDecimalSeparator, numeral.allDecimalSeparatorArray, defaultDecimalSeparatorTypeName, numeral.defaultDecimalSeparator);
|
||||
}
|
||||
|
||||
function getAllDigitGroupingSymbols(translateFn) {
|
||||
const defaultDigitGroupingSymbolTypeName = translateFn('default.digitGroupingSymbol');
|
||||
return getNumeralSeparatorFormats(translateFn, numeral.allDigitGroupingSymbol, numeral.allDigitGroupingSymbolArray, defaultDigitGroupingSymbolTypeName, numeral.defaultDigitGroupingSymbol);
|
||||
}
|
||||
|
||||
function getNumeralSeparatorFormats(translateFn, allSeparatorMap, allSeparatorArray, localeDefaultTypeName, systemDefaultType) {
|
||||
let defaultSeparatorType = allSeparatorMap[localeDefaultTypeName];
|
||||
|
||||
if (!defaultSeparatorType) {
|
||||
defaultSeparatorType = systemDefaultType;
|
||||
}
|
||||
|
||||
const ret = [];
|
||||
|
||||
ret.push({
|
||||
type: numeral.defaultValue,
|
||||
symbol: defaultSeparatorType.symbol,
|
||||
displayName: `${translateFn('Language Default')} (${defaultSeparatorType.symbol})`
|
||||
});
|
||||
|
||||
for (let i = 0; i < allSeparatorArray.length; i++) {
|
||||
const type = allSeparatorArray[i];
|
||||
|
||||
ret.push({
|
||||
type: type.type,
|
||||
symbol: type.symbol,
|
||||
displayName: `${translateFn('numeral.' + type.name)} (${type.symbol})`
|
||||
});
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
function getAllDigitGroupingTypes(translateFn) {
|
||||
const defaultDigitGroupingTypeName = translateFn('default.digitGrouping');
|
||||
let defaultDigitGroupingType = numeral.allDigitGroupingType[defaultDigitGroupingTypeName];
|
||||
|
||||
if (!defaultDigitGroupingType) {
|
||||
defaultDigitGroupingType = numeral.defaultDigitGroupingType;
|
||||
}
|
||||
|
||||
const ret = [];
|
||||
|
||||
ret.push({
|
||||
type: numeral.defaultValue,
|
||||
displayName: `${translateFn('Language Default')} (${translateFn('numeral.' + defaultDigitGroupingType.name)})`
|
||||
});
|
||||
|
||||
for (let i = 0; i < numeral.allDigitGroupingTypeArray.length; i++) {
|
||||
const type = numeral.allDigitGroupingTypeArray[i];
|
||||
|
||||
ret.push({
|
||||
type: type.type,
|
||||
displayName: translateFn('numeral.' + type.name)
|
||||
});
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
function getCurrentDecimalSeparator(translateFn, decimalSeparator) {
|
||||
let decimalSeparatorType = numeral.allDecimalSeparatorMap[decimalSeparator];
|
||||
|
||||
if (!decimalSeparatorType) {
|
||||
const defaultDecimalSeparatorTypeName = translateFn('default.decimalSeparator');
|
||||
decimalSeparatorType = numeral.allDecimalSeparator[defaultDecimalSeparatorTypeName];
|
||||
|
||||
if (!decimalSeparatorType) {
|
||||
decimalSeparatorType = numeral.defaultDecimalSeparator;
|
||||
}
|
||||
}
|
||||
|
||||
return decimalSeparatorType.symbol;
|
||||
}
|
||||
|
||||
function getCurrentDigitGroupingSymbol(translateFn, digitGroupingSymbol) {
|
||||
let digitGroupingSymbolType = numeral.allDigitGroupingSymbolMap[digitGroupingSymbol];
|
||||
|
||||
if (!digitGroupingSymbolType) {
|
||||
const defaultDigitGroupingSymbolTypeName = translateFn('default.digitGroupingSymbol');
|
||||
digitGroupingSymbolType = numeral.allDigitGroupingSymbol[defaultDigitGroupingSymbolTypeName];
|
||||
|
||||
if (!digitGroupingSymbolType) {
|
||||
digitGroupingSymbolType = numeral.defaultDigitGroupingSymbol;
|
||||
}
|
||||
}
|
||||
|
||||
return digitGroupingSymbolType.symbol;
|
||||
}
|
||||
|
||||
function getCurrentDigitGroupingType(translateFn, digitGrouping) {
|
||||
let digitGroupingType = numeral.allDigitGroupingTypeMap[digitGrouping];
|
||||
|
||||
if (!digitGroupingType) {
|
||||
const defaultDigitGroupingTypeName = translateFn('default.digitGrouping');
|
||||
digitGroupingType = numeral.allDigitGroupingType[defaultDigitGroupingTypeName];
|
||||
|
||||
if (!digitGroupingType) {
|
||||
digitGroupingType = numeral.defaultDigitGroupingType;
|
||||
}
|
||||
}
|
||||
|
||||
return digitGroupingType.type;
|
||||
}
|
||||
|
||||
function getNumberFormatOptions(translateFn, userStore) {
|
||||
return {
|
||||
decimalSeparator: getCurrentDecimalSeparator(translateFn, userStore.currentUserDecimalSeparator),
|
||||
digitGroupingSymbol: getCurrentDigitGroupingSymbol(translateFn, userStore.currentUserDigitGroupingSymbol),
|
||||
digitGrouping: getCurrentDigitGroupingType(translateFn, userStore.currentUserDigitGrouping),
|
||||
};
|
||||
}
|
||||
|
||||
function getNumberWithDigitGroupingSymbol(value, translateFn, userStore) {
|
||||
const numberFormatOptions = getNumberFormatOptions(translateFn, userStore);
|
||||
return appendDigitGroupingSymbol(value, numberFormatOptions);
|
||||
}
|
||||
|
||||
function getParsedAmountNumber(value, translateFn, userStore) {
|
||||
const numberFormatOptions = getNumberFormatOptions(translateFn, userStore);
|
||||
return parseAmount(value, numberFormatOptions);
|
||||
}
|
||||
|
||||
function getFormatedAmount(value, translateFn, userStore) {
|
||||
const numberFormatOptions = getNumberFormatOptions(translateFn, userStore);
|
||||
return formatAmount(value, numberFormatOptions);
|
||||
}
|
||||
|
||||
function getFormatedAmountWithCurrency(value, currencyCode, translateFn, userStore, settingsStore, notConvertValue) {
|
||||
if (!isNumber(value) && !isString(value)) {
|
||||
return value;
|
||||
}
|
||||
|
||||
if (isNumber(value)) {
|
||||
value = value.toString();
|
||||
}
|
||||
|
||||
if (!notConvertValue) {
|
||||
const numberFormatOptions = getNumberFormatOptions(translateFn, userStore);
|
||||
const hasIncompleteFlag = isString(value) && value.charAt(value.length - 1) === '+';
|
||||
|
||||
if (hasIncompleteFlag) {
|
||||
value = value.substring(0, value.length - 1);
|
||||
}
|
||||
|
||||
value = formatAmount(value, numberFormatOptions);
|
||||
|
||||
if (hasIncompleteFlag) {
|
||||
value = value + '+';
|
||||
}
|
||||
}
|
||||
|
||||
if (!isBoolean(currencyCode) && !currencyCode) {
|
||||
currencyCode = userStore.currentUserDefaultCurrency;
|
||||
} else if (isBoolean(currencyCode) && !currencyCode) {
|
||||
currencyCode = '';
|
||||
}
|
||||
|
||||
const currencyDisplayMode = settingsStore.appSettings.currencyDisplayMode;
|
||||
|
||||
if (currencyCode && currencyDisplayMode === currency.allCurrencyDisplayModes.Symbol) {
|
||||
const currencyInfo = currency.all[currencyCode];
|
||||
let currencySymbol = currency.defaultCurrencySymbol;
|
||||
|
||||
if (currencyInfo && currencyInfo.symbol) {
|
||||
currencySymbol = currencyInfo.symbol;
|
||||
} else if (currencyInfo && currencyInfo.code) {
|
||||
currencySymbol = currencyInfo.code;
|
||||
}
|
||||
|
||||
return translateFn('format.currency.symbol', {
|
||||
amount: value,
|
||||
symbol: currencySymbol
|
||||
});
|
||||
} else if (currencyCode && currencyDisplayMode === currency.allCurrencyDisplayModes.Code) {
|
||||
return `${value} ${currencyCode}`;
|
||||
} else if (currencyCode && currencyDisplayMode === currency.allCurrencyDisplayModes.Name) {
|
||||
const currencyName = getCurrencyName(currencyCode, translateFn);
|
||||
return `${value} ${currencyName}`;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
function getFormatedExchangeRateAmount(value, translateFn, userStore) {
|
||||
const numberFormatOptions = getNumberFormatOptions(translateFn, userStore);
|
||||
return formatExchangeRateAmount(value, numberFormatOptions);
|
||||
}
|
||||
|
||||
function getAdaptiveAmountRate(amount1, amount2, fromExchangeRate, toExchangeRate, translateFn, userStore) {
|
||||
const numberFormatOptions = getNumberFormatOptions(translateFn, userStore);
|
||||
return getAdaptiveDisplayAmountRate(amount1, amount2, fromExchangeRate, toExchangeRate, numberFormatOptions);
|
||||
}
|
||||
|
||||
function getAmountPrependAndAppendText(currencyCode, translateFn, userStore, settingsStore) {
|
||||
const placeholder = '***';
|
||||
const finalText = getFormatedAmountWithCurrency(placeholder, currencyCode, translateFn, userStore, settingsStore, true);
|
||||
|
||||
if (!finalText) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let prependText = getTextBefore(finalText, placeholder);
|
||||
|
||||
if (prependText) {
|
||||
prependText = prependText.trim();
|
||||
}
|
||||
|
||||
let appendText = getTextAfter(finalText, placeholder);
|
||||
|
||||
if (appendText) {
|
||||
appendText = appendText.trim();
|
||||
}
|
||||
|
||||
return {
|
||||
prependText: prependText,
|
||||
appendText: appendText
|
||||
};
|
||||
}
|
||||
|
||||
function getAllAccountCategories(translateFn) {
|
||||
const allAccountCategories = [];
|
||||
|
||||
@@ -996,91 +1227,7 @@ function getEnableDisableOptions(translateFn) {
|
||||
}];
|
||||
}
|
||||
|
||||
function getDisplayCurrency(value, currencyCode, options, translateFn) {
|
||||
if (!isNumber(value) && !isString(value)) {
|
||||
return value;
|
||||
}
|
||||
|
||||
if (isNumber(value)) {
|
||||
value = value.toString();
|
||||
}
|
||||
|
||||
if (!options) {
|
||||
options = {};
|
||||
}
|
||||
|
||||
if (!options.notConvertValue) {
|
||||
const hasIncompleteFlag = isString(value) && value.charAt(value.length - 1) === '+';
|
||||
|
||||
if (hasIncompleteFlag) {
|
||||
value = value.substring(0, value.length - 1);
|
||||
}
|
||||
|
||||
value = numericCurrencyToString(value, options.enableThousandsSeparator);
|
||||
|
||||
if (hasIncompleteFlag) {
|
||||
value = value + '+';
|
||||
}
|
||||
}
|
||||
|
||||
const currencyDisplayMode = options.currencyDisplayMode;
|
||||
|
||||
if (currencyCode && currencyDisplayMode === currency.allCurrencyDisplayModes.Symbol) {
|
||||
const currencyInfo = currency.all[currencyCode];
|
||||
let currencySymbol = currency.defaultCurrencySymbol;
|
||||
|
||||
if (currencyInfo && currencyInfo.symbol) {
|
||||
currencySymbol = currencyInfo.symbol;
|
||||
} else if (currencyInfo && currencyInfo.code) {
|
||||
currencySymbol = currencyInfo.code;
|
||||
}
|
||||
|
||||
return translateFn('format.currency.symbol', {
|
||||
amount: value,
|
||||
symbol: currencySymbol
|
||||
});
|
||||
} else if (currencyCode && currencyDisplayMode === currency.allCurrencyDisplayModes.Code) {
|
||||
return `${value} ${currencyCode}`;
|
||||
} else if (currencyCode && currencyDisplayMode === currency.allCurrencyDisplayModes.Name) {
|
||||
const currencyName = getCurrencyName(currencyCode, translateFn);
|
||||
return `${value} ${currencyName}`;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
function getDisplayCurrencyPrependAndAppendText(currencyCode, currencyDisplayMode, translateFn) {
|
||||
const options = {
|
||||
currencyDisplayMode: currencyDisplayMode,
|
||||
notConvertValue: true
|
||||
};
|
||||
|
||||
const placeholder = '***';
|
||||
const finalText = getDisplayCurrency(placeholder, currencyCode, options, translateFn);
|
||||
|
||||
if (!finalText) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let prependText = getTextBefore(finalText, placeholder);
|
||||
|
||||
if (prependText) {
|
||||
prependText = prependText.trim();
|
||||
}
|
||||
|
||||
let appendText = getTextAfter(finalText, placeholder);
|
||||
|
||||
if (appendText) {
|
||||
appendText = appendText.trim();
|
||||
}
|
||||
|
||||
return {
|
||||
prependText: prependText,
|
||||
appendText: appendText
|
||||
};
|
||||
}
|
||||
|
||||
function getCategorizedAccountsWithDisplayBalance(exchangeRatesStore, allVisibleAccounts, showAccountBalance, defaultCurrency, options, translateFn) {
|
||||
function getCategorizedAccountsWithDisplayBalance(allVisibleAccounts, showAccountBalance, defaultCurrency, userStore, settingsStore, exchangeRatesStore, translateFn) {
|
||||
const categorizedAccounts = copyObjectTo(getCategorizedAccounts(allVisibleAccounts), {});
|
||||
|
||||
for (let category in categorizedAccounts) {
|
||||
@@ -1095,9 +1242,9 @@ function getCategorizedAccountsWithDisplayBalance(exchangeRatesStore, allVisible
|
||||
const account = accountCategory.accounts[i];
|
||||
|
||||
if (showAccountBalance && account.isAsset) {
|
||||
account.displayBalance = getDisplayCurrency(account.balance, account.currency, options, translateFn);
|
||||
account.displayBalance = getFormatedAmountWithCurrency(account.balance, account.currency, translateFn, userStore, settingsStore);
|
||||
} else if (showAccountBalance && account.isLiability) {
|
||||
account.displayBalance = getDisplayCurrency(-account.balance, account.currency, options, translateFn);
|
||||
account.displayBalance = getFormatedAmountWithCurrency(-account.balance, account.currency, translateFn, userStore, settingsStore);
|
||||
} else {
|
||||
account.displayBalance = '***';
|
||||
}
|
||||
@@ -1136,7 +1283,7 @@ function getCategorizedAccountsWithDisplayBalance(exchangeRatesStore, allVisible
|
||||
totalBalance = totalBalance + '+';
|
||||
}
|
||||
|
||||
accountCategory.displayBalance = getDisplayCurrency(totalBalance, defaultCurrency, options, translateFn);
|
||||
accountCategory.displayBalance = getFormatedAmountWithCurrency(totalBalance, defaultCurrency, translateFn, userStore, settingsStore);
|
||||
} else {
|
||||
accountCategory.displayBalance = '***';
|
||||
}
|
||||
@@ -1384,6 +1531,19 @@ export function i18nFunctions(i18nGlobal) {
|
||||
getAllRecentMonthDateRanges: (userStore, includeAll, includeCustom) => getAllRecentMonthDateRanges(userStore, includeAll, includeCustom, i18nGlobal.t),
|
||||
getDateRangeDisplayName: (userStore, dateType, startTime, endTime) => getDateRangeDisplayName(userStore, dateType, startTime, endTime, i18nGlobal.t),
|
||||
getAllTimezoneTypesUsedForStatistics: (currentTimezone) => getAllTimezoneTypesUsedForStatistics(currentTimezone, i18nGlobal.t),
|
||||
getAllDecimalSeparators: () => getAllDecimalSeparators(i18nGlobal.t),
|
||||
getAllDigitGroupingSymbols: () => getAllDigitGroupingSymbols(i18nGlobal.t),
|
||||
getAllDigitGroupingTypes: () => getAllDigitGroupingTypes(i18nGlobal.t),
|
||||
getCurrentDecimalSeparator: (userStore) => getCurrentDecimalSeparator(i18nGlobal.t, userStore.currentUserDecimalSeparator),
|
||||
getCurrentDigitGroupingSymbol: (userStore) => getCurrentDigitGroupingSymbol(i18nGlobal.t, userStore.currentUserDigitGroupingSymbol),
|
||||
getCurrentDigitGroupingType: (userStore) => getCurrentDigitGroupingType(i18nGlobal.t, userStore.currentUserDigitGrouping),
|
||||
appendDigitGroupingSymbol: (userStore, value) => getNumberWithDigitGroupingSymbol(value, i18nGlobal.t, userStore),
|
||||
parseAmount: (userStore, value) => getParsedAmountNumber(value, i18nGlobal.t, userStore),
|
||||
formatAmount: (userStore, value) => getFormatedAmount(value, i18nGlobal.t, userStore),
|
||||
formatAmountWithCurrency: (settingsStore, userStore, value, currencyCode) => getFormatedAmountWithCurrency(value, currencyCode, i18nGlobal.t, userStore, settingsStore),
|
||||
formatExchangeRateAmount: (userStore, value) => getFormatedExchangeRateAmount(value, i18nGlobal.t, userStore),
|
||||
getAdaptiveAmountRate: (userStore, amount1, amount2, fromExchangeRate, toExchangeRate) => getAdaptiveAmountRate(amount1, amount2, fromExchangeRate, toExchangeRate, i18nGlobal.t, userStore),
|
||||
getAmountPrependAndAppendText: (settingsStore, userStore, currencyCode) => getAmountPrependAndAppendText(currencyCode, i18nGlobal.t, userStore, settingsStore),
|
||||
getAllAccountCategories: () => getAllAccountCategories(i18nGlobal.t),
|
||||
getAllAccountTypes: () => getAllAccountTypes(i18nGlobal.t),
|
||||
getAllCategoricalChartTypes: () => getAllCategoricalChartTypes(i18nGlobal.t),
|
||||
@@ -1394,9 +1554,7 @@ export function i18nFunctions(i18nGlobal) {
|
||||
getAllTransactionDefaultCategories: (categoryType, locale) => getAllTransactionDefaultCategories(categoryType, locale, i18nGlobal.t),
|
||||
getAllDisplayExchangeRates: (exchangeRatesData) => getAllDisplayExchangeRates(exchangeRatesData, i18nGlobal.t),
|
||||
getEnableDisableOptions: () => getEnableDisableOptions(i18nGlobal.t),
|
||||
getDisplayCurrency: (value, currencyCode, options) => getDisplayCurrency(value, currencyCode, options, i18nGlobal.t),
|
||||
getDisplayCurrencyPrependAndAppendText: (currencyCode, currencyDisplayMode) => getDisplayCurrencyPrependAndAppendText(currencyCode, currencyDisplayMode, i18nGlobal.t),
|
||||
getCategorizedAccountsWithDisplayBalance: (exchangeRatesStore, allVisibleAccounts, showAccountBalance, defaultCurrency, options) => getCategorizedAccountsWithDisplayBalance(exchangeRatesStore, allVisibleAccounts, showAccountBalance, defaultCurrency, options, i18nGlobal.t),
|
||||
getCategorizedAccountsWithDisplayBalance: (allVisibleAccounts, showAccountBalance, defaultCurrency, settingsStore, userStore, exchangeRatesStore) => getCategorizedAccountsWithDisplayBalance(allVisibleAccounts, showAccountBalance, defaultCurrency, userStore, settingsStore, exchangeRatesStore, i18nGlobal.t),
|
||||
joinMultiText: (textArray) => joinMultiText(textArray, i18nGlobal.t),
|
||||
setLanguage: (locale, force) => setLanguage(i18nGlobal, locale, force),
|
||||
setTimeZone: (timezone) => setTimeZone(timezone),
|
||||
|
||||
+231
-16
@@ -1,5 +1,25 @@
|
||||
export function appendThousandsSeparator(value, enable) {
|
||||
if (!enable || value.length <= 3) {
|
||||
import numeralConstants from '@/consts/numeral.js';
|
||||
|
||||
import { isString, isNumber, removeAll } from './common.js';
|
||||
|
||||
export function appendDigitGroupingSymbol(value, options) {
|
||||
if (isNumber(value)) {
|
||||
value = value.toString();
|
||||
}
|
||||
|
||||
if (!isString(value)) {
|
||||
return value;
|
||||
}
|
||||
|
||||
if (!options) {
|
||||
options = {};
|
||||
}
|
||||
|
||||
if (!isNumber(options.digitGrouping) || options.digitGrouping === numeralConstants.allDigitGroupingType.None.type) {
|
||||
return value;
|
||||
}
|
||||
|
||||
if (value.length <= 3) {
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -9,35 +29,159 @@ export function appendThousandsSeparator(value, enable) {
|
||||
value = value.substring(1);
|
||||
}
|
||||
|
||||
const dotPos = value.indexOf('.');
|
||||
const integer = dotPos < 0 ? value : value.substring(0, dotPos);
|
||||
const decimals = dotPos < 0 ? '' : value.substring(dotPos + 1, value.length);
|
||||
const digitGroupingSymbol = options.digitGroupingSymbol || numeralConstants.defaultDigitGroupingSymbol.symbol;
|
||||
const decimalSeparator = options.decimalSeparator || numeralConstants.defaultDecimalSeparator.symbol;
|
||||
|
||||
const finalChars = [];
|
||||
let integerChars = [];
|
||||
let currentDecimalSeparator = '';
|
||||
let decimals = '';
|
||||
|
||||
for (let i = 0; i < integer.length; i++) {
|
||||
if (i % 3 === 0 && i > 0) {
|
||||
finalChars.push(',');
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
const ch = value.charAt(i);
|
||||
|
||||
if ('0' <= ch && ch <= '9') {
|
||||
integerChars.push(ch);
|
||||
} else {
|
||||
currentDecimalSeparator = ch;
|
||||
decimals = value.substring(i + 1);
|
||||
break;
|
||||
}
|
||||
|
||||
finalChars.push(integer.charAt(integer.length - 1 - i));
|
||||
}
|
||||
|
||||
finalChars.reverse();
|
||||
let newInteger = '';
|
||||
|
||||
let newInteger = finalChars.join('');
|
||||
if (options.digitGrouping === numeralConstants.allDigitGroupingType.ThousandsSeparator.type) {
|
||||
for (let i = integerChars.length - 1, j = 0; i >= 0; i--, j++) {
|
||||
if (j % 3 === 0 && j > 0) {
|
||||
newInteger = digitGroupingSymbol + newInteger;
|
||||
}
|
||||
|
||||
newInteger = integerChars[i] + newInteger;
|
||||
}
|
||||
}
|
||||
|
||||
if (negative) {
|
||||
newInteger = `-${newInteger}`;
|
||||
}
|
||||
|
||||
if (dotPos < 0) {
|
||||
return newInteger;
|
||||
if (currentDecimalSeparator) {
|
||||
return `${newInteger}${decimalSeparator}${decimals}`;
|
||||
} else {
|
||||
return `${newInteger}.${decimals}`;
|
||||
return newInteger;
|
||||
}
|
||||
}
|
||||
|
||||
export function parseAmount(str, options) {
|
||||
if (!isString(str)) {
|
||||
return str;
|
||||
}
|
||||
|
||||
if (!options) {
|
||||
options = {};
|
||||
}
|
||||
|
||||
if (!str || str.length < 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const negative = str.charAt(0) === '-';
|
||||
|
||||
if (negative) {
|
||||
str = str.substring(1);
|
||||
}
|
||||
|
||||
if (!str || str.length < 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const sign = negative ? -1 : 1;
|
||||
|
||||
const decimalSeparator = options.decimalSeparator || numeralConstants.defaultDecimalSeparator.symbol;
|
||||
const digitGroupingSymbol = options.digitGroupingSymbol || numeralConstants.defaultDigitGroupingSymbol.symbol;
|
||||
|
||||
if (str.indexOf(digitGroupingSymbol) >= 0) {
|
||||
str = removeAll(str, digitGroupingSymbol);
|
||||
}
|
||||
|
||||
let decimalSeparatorPos = str.indexOf(decimalSeparator);
|
||||
|
||||
if (decimalSeparatorPos < 0) {
|
||||
return sign * parseInt(str) * 100;
|
||||
} else if (decimalSeparatorPos === 0) {
|
||||
str = '0' + str;
|
||||
decimalSeparatorPos++;
|
||||
}
|
||||
|
||||
const integer = str.substring(0, decimalSeparatorPos);
|
||||
const decimals = str.substring(decimalSeparatorPos + 1, str.length);
|
||||
|
||||
if (decimals.length < 1) {
|
||||
return sign * parseInt(integer) * 100;
|
||||
} else if (decimals.length === 1) {
|
||||
return sign * parseInt(integer) * 100 + sign * parseInt(decimals) * 10;
|
||||
} else if (decimals.length === 2) {
|
||||
return sign * parseInt(integer) * 100 + sign * parseInt(decimals);
|
||||
} else {
|
||||
return sign * parseInt(integer) * 100 + sign * parseInt(decimals.substring(0, 2));
|
||||
}
|
||||
}
|
||||
|
||||
export function formatAmount(value, options) {
|
||||
if (isNumber(value)) {
|
||||
value = value.toString();
|
||||
}
|
||||
|
||||
if (!isString(value)) {
|
||||
return value;
|
||||
}
|
||||
|
||||
if (!options) {
|
||||
options = {};
|
||||
}
|
||||
|
||||
const negative = value.charAt(0) === '-';
|
||||
|
||||
if (negative) {
|
||||
value = value.substring(1);
|
||||
}
|
||||
|
||||
const decimalSeparator = options.decimalSeparator || numeralConstants.defaultDecimalSeparator.symbol;
|
||||
|
||||
let integer = '0';
|
||||
let decimals = '00';
|
||||
|
||||
if (value.length > 2) {
|
||||
integer = value.substring(0, value.length - 2);
|
||||
decimals = value.substring(value.length - 2);
|
||||
} else if (value.length === 2) {
|
||||
decimals = value;
|
||||
} else if (value.length === 1) {
|
||||
decimals = '0' + value;
|
||||
}
|
||||
|
||||
if (options.trimTailZero) {
|
||||
if (decimals.charAt(0) === '0' && decimals.charAt(1) === '0') {
|
||||
decimals = '';
|
||||
} else if (decimals.charAt(0) !== '0' && decimals.charAt(1) === '0') {
|
||||
decimals = decimals.charAt(0);
|
||||
}
|
||||
}
|
||||
|
||||
integer = appendDigitGroupingSymbol(integer, options);
|
||||
|
||||
if (decimals !== '') {
|
||||
value = `${integer}${decimalSeparator}${decimals}`;
|
||||
} else {
|
||||
value = integer;
|
||||
}
|
||||
|
||||
if (negative) {
|
||||
value = `-${value}`;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
export function formatPercent(value, precision, lowPrecisionValue) {
|
||||
const ratio = Math.pow(10, precision);
|
||||
const normalizedValue = Math.floor(value * ratio);
|
||||
@@ -49,3 +193,74 @@ export function formatPercent(value, precision, lowPrecisionValue) {
|
||||
const result = normalizedValue / ratio;
|
||||
return result + '%';
|
||||
}
|
||||
|
||||
export function formatExchangeRateAmount(exchangeRateAmount, options) {
|
||||
if (!options) {
|
||||
options = {};
|
||||
}
|
||||
|
||||
const rateStr = exchangeRateAmount.toString();
|
||||
const decimalSeparator = numeralConstants.allDecimalSeparator.Dot.symbol;
|
||||
|
||||
if (rateStr.indexOf(decimalSeparator) < 0) {
|
||||
return appendDigitGroupingSymbol(rateStr, options);
|
||||
} else {
|
||||
let firstNonZeroPos = 0;
|
||||
|
||||
for (let i = 0; i < rateStr.length; i++) {
|
||||
if (rateStr.charAt(i) !== decimalSeparator && rateStr.charAt(i) !== '0') {
|
||||
firstNonZeroPos = Math.min(i + 4, rateStr.length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const trimmedRateStr = rateStr.substring(0, Math.max(6, Math.max(firstNonZeroPos, rateStr.indexOf(decimalSeparator) + 2)));
|
||||
return appendDigitGroupingSymbol(trimmedRateStr, options);
|
||||
}
|
||||
}
|
||||
|
||||
export function getAdaptiveDisplayAmountRate(amount1, amount2, fromExchangeRate, toExchangeRate, options) {
|
||||
if (!amount1 || !amount2 || amount1 === amount2) {
|
||||
if (!fromExchangeRate || !fromExchangeRate.rate || !toExchangeRate || !toExchangeRate.rate) {
|
||||
return null;
|
||||
}
|
||||
|
||||
amount1 = fromExchangeRate.rate;
|
||||
amount2 = toExchangeRate.rate;
|
||||
}
|
||||
|
||||
amount1 = parseFloat(amount1);
|
||||
amount2 = parseFloat(amount2);
|
||||
|
||||
if (amount1 > amount2) {
|
||||
const rateStr = (amount1 / amount2).toString();
|
||||
const displayRateStr = formatExchangeRateAmount(rateStr, options);
|
||||
return `${displayRateStr} : 1`;
|
||||
} else {
|
||||
const rateStr = (amount2 / amount1).toString();
|
||||
const displayRateStr = formatExchangeRateAmount(rateStr, options);
|
||||
return `1 : ${displayRateStr}`;
|
||||
}
|
||||
}
|
||||
|
||||
export function getExchangedAmount(amount, fromRate, toRate) {
|
||||
const exchangeRate = parseFloat(toRate) / parseFloat(fromRate);
|
||||
|
||||
if (!isNumber(exchangeRate)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return amount * exchangeRate;
|
||||
}
|
||||
|
||||
export function getConvertedAmount(baseAmount, fromExchangeRate, toExchangeRate) {
|
||||
if (!fromExchangeRate || !toExchangeRate) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (baseAmount === '') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return getExchangedAmount(baseAmount, fromExchangeRate.rate, toExchangeRate.rate);
|
||||
}
|
||||
|
||||
+5
-2
@@ -169,7 +169,7 @@ export default {
|
||||
getProfile: () => {
|
||||
return axios.get('v1/users/profile/get.json');
|
||||
},
|
||||
updateProfile: ({ email, nickname, password, oldPassword, defaultAccountId, transactionEditScope, language, defaultCurrency, firstDayOfWeek, longDateFormat, shortDateFormat, longTimeFormat, shortTimeFormat }) => {
|
||||
updateProfile: ({ email, nickname, password, oldPassword, defaultAccountId, transactionEditScope, language, defaultCurrency, firstDayOfWeek, longDateFormat, shortDateFormat, longTimeFormat, shortTimeFormat, decimalSeparator, digitGroupingSymbol, digitGrouping }) => {
|
||||
return axios.post('v1/users/profile/update.json', {
|
||||
email,
|
||||
nickname,
|
||||
@@ -183,7 +183,10 @@ export default {
|
||||
longDateFormat,
|
||||
shortDateFormat,
|
||||
longTimeFormat,
|
||||
shortTimeFormat
|
||||
shortTimeFormat,
|
||||
decimalSeparator,
|
||||
digitGroupingSymbol,
|
||||
digitGrouping
|
||||
});
|
||||
},
|
||||
resendVerifyEmailByLoginedUser: () => {
|
||||
|
||||
@@ -13,7 +13,6 @@ const defaultSettings = {
|
||||
applicationLockWebAuthn: false,
|
||||
autoUpdateExchangeRatesData: true,
|
||||
autoGetCurrentGeoLocation: false,
|
||||
thousandsSeparator: true,
|
||||
currencyDisplayMode: currencyConstants.defaultCurrencyDisplayMode,
|
||||
showAmountInHomePage: true,
|
||||
timezoneUsedForStatisticsInHomePage: timezoneConstants.defaultTimezoneTypesUsedForStatistics,
|
||||
@@ -167,14 +166,6 @@ export function setAutoGetCurrentGeoLocation(value) {
|
||||
setOption('autoGetCurrentGeoLocation', value);
|
||||
}
|
||||
|
||||
export function isEnableThousandsSeparator() {
|
||||
return getOption('thousandsSeparator');
|
||||
}
|
||||
|
||||
export function setEnableThousandsSeparator(value) {
|
||||
setOption('thousandsSeparator', value);
|
||||
}
|
||||
|
||||
export function getCurrencyDisplayMode() {
|
||||
return getOption('currencyDisplayMode');
|
||||
}
|
||||
|
||||
+16
-2
@@ -10,7 +10,10 @@ export default {
|
||||
'longDateFormat': 'MMDDYYYY',
|
||||
'shortDateFormat': 'MMDDYYYY',
|
||||
'longTimeFormat': 'HHMMSSA',
|
||||
'shortTimeFormat': 'HHMMA'
|
||||
'shortTimeFormat': 'HHMMA',
|
||||
'decimalSeparator': 'Dot',
|
||||
'digitGroupingSymbol': 'Comma',
|
||||
'digitGrouping': 'ThousandsSeparator'
|
||||
},
|
||||
'format': { // The type of date or time format is moment format, ref: https://momentjs.com/docs/#/displaying/
|
||||
'longDate': {
|
||||
@@ -172,6 +175,14 @@ export default {
|
||||
'long': 'December'
|
||||
}
|
||||
},
|
||||
'numeral': {
|
||||
'Dot': 'Dot',
|
||||
'Comma': 'Comma',
|
||||
'Space': 'Space',
|
||||
'Apostrophe': 'Apostrophe',
|
||||
'None': 'None',
|
||||
'Thousands Separator': 'Thousands Separator',
|
||||
},
|
||||
'timezone': {
|
||||
'International Date Line West': 'International Date Line West',
|
||||
'Coordinated Universal Time-11': 'Coordinated Universal Time-11',
|
||||
@@ -604,6 +615,7 @@ export default {
|
||||
'email is not verified': 'Email is not verified',
|
||||
'email is verified': 'Email is verified',
|
||||
'email validation not allowed': 'Email validation is not allowed',
|
||||
'decimal separator and digit grouping symbol cannot be equal': 'Decimal separator and digit grouping symbol cannot be equal',
|
||||
'unauthorized access': 'Unauthorized access',
|
||||
'current token is invalid': 'Current token is invalid',
|
||||
'current token is expired': 'Current token is expired',
|
||||
@@ -844,6 +856,9 @@ export default {
|
||||
'Short Date Format': 'Short Date Format',
|
||||
'Long Time Format': 'Long Time Format',
|
||||
'Short Time Format': 'Short Time Format',
|
||||
'Decimal Separator': 'Decimal Separator',
|
||||
'Digit Grouping Symbol': 'Digit Grouping Symbol',
|
||||
'Digit Grouping': 'Digit Grouping',
|
||||
'Editable Transaction Range': 'Editable Transaction Range',
|
||||
'Today or later': 'Today or later',
|
||||
'Recent 24 hours or later': 'Recent 24 hours or later',
|
||||
@@ -1071,7 +1086,6 @@ export default {
|
||||
'System Default': 'System Default',
|
||||
'Language Default': 'Language Default',
|
||||
'Auto-update Exchange Rates Data': 'Auto-update Exchange Rates Data',
|
||||
'Enable Thousands Separator': 'Enable Thousands Separator',
|
||||
'Currency Display Mode': 'Currency Display Mode',
|
||||
'Currency Code': 'Currency Code',
|
||||
'Currency Name': 'Currency Name',
|
||||
|
||||
+16
-2
@@ -10,7 +10,10 @@ export default {
|
||||
'longDateFormat': 'YYYYMMDD',
|
||||
'shortDateFormat': 'YYYYMMDD',
|
||||
'longTimeFormat': 'HHMMSS',
|
||||
'shortTimeFormat': 'HHMM'
|
||||
'shortTimeFormat': 'HHMM',
|
||||
'decimalSeparator': 'Dot',
|
||||
'digitGroupingSymbol': 'Comma',
|
||||
'digitGrouping': 'ThousandsSeparator'
|
||||
},
|
||||
'format': {
|
||||
'longDate': {
|
||||
@@ -172,6 +175,14 @@ export default {
|
||||
'long': '十二月'
|
||||
}
|
||||
},
|
||||
'numeral': {
|
||||
'Dot': '句点',
|
||||
'Comma': '逗号',
|
||||
'Space': '空格',
|
||||
'Apostrophe': '撇号',
|
||||
'None': '无',
|
||||
'Thousands Separator': '千位分隔符',
|
||||
},
|
||||
'timezone': {
|
||||
'International Date Line West': '国际日期变更线西',
|
||||
'Coordinated Universal Time-11': '协调世界时-11',
|
||||
@@ -604,6 +615,7 @@ export default {
|
||||
'email is not verified': '邮箱还未验证通过',
|
||||
'email is verified': '邮箱已经验证过',
|
||||
'email validation not allowed': '不允许邮箱验证',
|
||||
'decimal separator and digit grouping symbol cannot be equal': '小数点和数字分组符号不能相同',
|
||||
'unauthorized access': '未授权的登录',
|
||||
'current token is invalid': '当前认证令牌无效',
|
||||
'current token is expired': '当前认证令牌已过期',
|
||||
@@ -844,6 +856,9 @@ export default {
|
||||
'Short Date Format': '短日期格式',
|
||||
'Long Time Format': '长时间格式',
|
||||
'Short Time Format': '短时间格式',
|
||||
'Decimal Separator': '小数点',
|
||||
'Digit Grouping Symbol': '数字分组符号',
|
||||
'Digit Grouping': '数字分组',
|
||||
'Editable Transaction Range': '可编辑交易范围',
|
||||
'Today or later': '今天或更晚',
|
||||
'Recent 24 hours or later': '最近24小时或更晚',
|
||||
@@ -1071,7 +1086,6 @@ export default {
|
||||
'System Default': '系统默认',
|
||||
'Language Default': '语言默认',
|
||||
'Auto-update Exchange Rates Data': '自动更新汇率数据',
|
||||
'Enable Thousands Separator': '启用千位分隔符',
|
||||
'Currency Display Mode': '货币显示模式',
|
||||
'Currency Code': '货币代码',
|
||||
'Currency Name': '货币名称',
|
||||
|
||||
@@ -4,7 +4,7 @@ import services from '@/lib/services.js';
|
||||
import logger from '@/lib/logger.js';
|
||||
import { isEquals } from '@/lib/common.js';
|
||||
import { getCurrentUnixTime, formatUnixTime } from '@/lib/datetime.js';
|
||||
import { getExchangedAmount } from '@/lib/currency.js';
|
||||
import { getExchangedAmount } from '@/lib/numeral.js';
|
||||
|
||||
const exchangeRatesLocalStorageKey = 'ebk_app_exchange_rates';
|
||||
|
||||
|
||||
+4
-1
@@ -380,7 +380,10 @@ export const useRootStore = defineStore('root', {
|
||||
longDateFormat: profile.longDateFormat,
|
||||
shortDateFormat: profile.shortDateFormat,
|
||||
longTimeFormat: profile.longTimeFormat,
|
||||
shortTimeFormat: profile.shortTimeFormat
|
||||
shortTimeFormat: profile.shortTimeFormat,
|
||||
decimalSeparator: profile.decimalSeparator,
|
||||
digitGroupingSymbol: profile.digitGroupingSymbol,
|
||||
digitGrouping: profile.digitGrouping
|
||||
}).then(response => {
|
||||
const data = response.data;
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@ export const useSettingsStore = defineStore('settings', {
|
||||
applicationLockWebAuthn: settings.isEnableApplicationLockWebAuthn(),
|
||||
autoUpdateExchangeRatesData: settings.isAutoUpdateExchangeRatesData(),
|
||||
autoGetCurrentGeoLocation: settings.isAutoGetCurrentGeoLocation(),
|
||||
thousandsSeparator: settings.isEnableThousandsSeparator(),
|
||||
currencyDisplayMode: settings.getCurrencyDisplayMode(),
|
||||
showAmountInHomePage: settings.isShowAmountInHomePage(),
|
||||
timezoneUsedForStatisticsInHomePage: settings.getTimezoneUsedForStatisticsInHomePage(),
|
||||
@@ -68,10 +67,6 @@ export const useSettingsStore = defineStore('settings', {
|
||||
settings.setAutoGetCurrentGeoLocation(value);
|
||||
this.appSettings.autoGetCurrentGeoLocation = value;
|
||||
},
|
||||
setEnableThousandsSeparator(value) {
|
||||
settings.setEnableThousandsSeparator(value);
|
||||
this.appSettings.thousandsSeparator = value;
|
||||
},
|
||||
setCurrencyDisplayMode(value) {
|
||||
settings.setCurrencyDisplayMode(value);
|
||||
this.appSettings.currencyDisplayMode = value;
|
||||
|
||||
@@ -25,9 +25,6 @@ import {
|
||||
getDay,
|
||||
getDayOfWeekName
|
||||
} from '@/lib/datetime.js';
|
||||
import {
|
||||
stringCurrencyToNumeric
|
||||
} from '@/lib/currency.js';
|
||||
|
||||
const emptyTransactionResult = {
|
||||
items: [],
|
||||
@@ -353,8 +350,7 @@ export const useTransactionsStore = defineStore('transactions', {
|
||||
}
|
||||
|
||||
if ((!sourceAccount || !destinationAccount || transaction.destinationAmount === oldValue || transaction.destinationAmount === 0) &&
|
||||
(stringCurrencyToNumeric(transactionConstants.minAmount) <= newValue &&
|
||||
newValue <= stringCurrencyToNumeric(transactionConstants.maxAmount))) {
|
||||
(transactionConstants.minAmountNumber <= newValue && newValue <= transactionConstants.maxAmountNumber)) {
|
||||
transaction.destinationAmount = newValue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,6 +58,18 @@ export const useUserStore = defineStore('user', {
|
||||
const settingsStore = useSettingsStore();
|
||||
const userInfo = state.currentUserInfo || {};
|
||||
return isNumber(userInfo.shortTimeFormat) ? userInfo.shortTimeFormat : settingsStore.shortTimeFormat;
|
||||
},
|
||||
currentUserDecimalSeparator(state) {
|
||||
const userInfo = state.currentUserInfo || {};
|
||||
return userInfo.decimalSeparator;
|
||||
},
|
||||
currentUserDigitGroupingSymbol(state) {
|
||||
const userInfo = state.currentUserInfo || {};
|
||||
return userInfo.digitGroupingSymbol;
|
||||
},
|
||||
currentUserDigitGrouping(state) {
|
||||
const userInfo = state.currentUserInfo || {};
|
||||
return userInfo.digitGrouping;
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
|
||||
@@ -114,7 +114,7 @@
|
||||
@click="setAsBaseline(exchangeRate.currencyCode, getConvertedAmount(exchangeRate))">
|
||||
{{ $t('Set as Base') }}
|
||||
</v-btn>
|
||||
<span>{{ getDisplayConvertedAmount(exchangeRate, isEnableThousandsSeparator) }}</span>
|
||||
<span>{{ getConvertedAmount(exchangeRate) }}</span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -140,12 +140,8 @@ import { useSettingsStore } from '@/stores/setting.js';
|
||||
import { useUserStore } from '@/stores/user.js';
|
||||
import { useExchangeRatesStore } from '@/stores/exchangeRates.js';
|
||||
|
||||
import { isNumber } from '@/lib/common.js';
|
||||
import {
|
||||
stringCurrencyToNumeric,
|
||||
getConvertedAmount,
|
||||
getDisplayExchangeRateAmount
|
||||
} from '@/lib/currency.js';
|
||||
import logger from '@/lib/logger.js';
|
||||
import { getConvertedAmount } from '@/lib/numeral.js';
|
||||
|
||||
import {
|
||||
mdiRefresh,
|
||||
@@ -172,9 +168,6 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
...mapStores(useSettingsStore, useUserStore, useExchangeRatesStore),
|
||||
isEnableThousandsSeparator() {
|
||||
return this.settingsStore.appSettings.thousandsSeparator;
|
||||
},
|
||||
exchangeRatesData() {
|
||||
return this.exchangeRatesStore.latestExchangeRates.data;
|
||||
},
|
||||
@@ -248,24 +241,20 @@ export default {
|
||||
}
|
||||
|
||||
const fromExchangeRate = this.exchangeRatesStore.latestExchangeRateMap[this.baseCurrency];
|
||||
let exchangeRateAmount = 0;
|
||||
|
||||
try {
|
||||
return getConvertedAmount(this.baseAmount / 100, fromExchangeRate, toExchangeRate);
|
||||
exchangeRateAmount = getConvertedAmount(this.baseAmount / 100, fromExchangeRate, toExchangeRate);
|
||||
} catch (e) {
|
||||
return 0;
|
||||
}
|
||||
},
|
||||
getDisplayConvertedAmount(toExchangeRate, isEnableThousandsSeparator) {
|
||||
const rateStr = this.getConvertedAmount(toExchangeRate).toString();
|
||||
return getDisplayExchangeRateAmount(rateStr, isEnableThousandsSeparator);
|
||||
},
|
||||
setAsBaseline(currency, amount) {
|
||||
if (!isNumber(amount)) {
|
||||
amount = '';
|
||||
exchangeRateAmount = 0;
|
||||
logger.warn('failed to convert amount by exchange rates, original base amount is ' + this.baseAmount)
|
||||
}
|
||||
|
||||
return this.$locale.formatExchangeRateAmount(this.userStore, exchangeRateAmount);
|
||||
},
|
||||
setAsBaseline(currency, amount) {
|
||||
this.baseCurrency = currency;
|
||||
this.baseAmount = stringCurrencyToNumeric(amount.toString());
|
||||
this.baseAmount = this.$locale.parseAmount(this.userStore, amount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -391,10 +391,7 @@ export default {
|
||||
this.$router.push(`/transaction/list?type=${type}&dateType=${datetimeConstants.allDateRanges.Custom.type}&maxTime=${maxTime}&minTime=${minTime}`);
|
||||
},
|
||||
getDisplayCurrency(value, currencyCode) {
|
||||
return this.$locale.getDisplayCurrency(value, currencyCode, {
|
||||
currencyDisplayMode: this.settingsStore.appSettings.currencyDisplayMode,
|
||||
enableThousandsSeparator: this.settingsStore.appSettings.thousandsSeparator
|
||||
});
|
||||
return this.$locale.formatAmountWithCurrency(this.settingsStore, this.userStore, value, currencyCode);
|
||||
},
|
||||
getDisplayAmount(amount, incomplete) {
|
||||
if (!this.showAmountInHomePage) {
|
||||
|
||||
@@ -594,10 +594,7 @@ export default {
|
||||
});
|
||||
},
|
||||
getDisplayCurrency(value, currencyCode) {
|
||||
return this.$locale.getDisplayCurrency(value, currencyCode, {
|
||||
currencyDisplayMode: this.settingsStore.appSettings.currencyDisplayMode,
|
||||
enableThousandsSeparator: this.settingsStore.appSettings.thousandsSeparator
|
||||
});
|
||||
return this.$locale.formatAmountWithCurrency(this.settingsStore, this.userStore, value, currencyCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,18 +47,6 @@
|
||||
/>
|
||||
</v-col>
|
||||
|
||||
<v-col cols="12" md="6">
|
||||
<v-select
|
||||
item-title="displayName"
|
||||
item-value="value"
|
||||
persistent-placeholder
|
||||
:label="$t('Enable Thousands Separator')"
|
||||
:placeholder="$t('Enable Thousands Separator')"
|
||||
:items="enableDisableOptions"
|
||||
v-model="isEnableThousandsSeparator"
|
||||
/>
|
||||
</v-col>
|
||||
|
||||
<v-col cols="12" md="6">
|
||||
<v-select
|
||||
item-title="displayName"
|
||||
@@ -248,14 +236,6 @@ export default {
|
||||
this.settingsStore.setAutoUpdateExchangeRatesData(value);
|
||||
}
|
||||
},
|
||||
isEnableThousandsSeparator: {
|
||||
get: function () {
|
||||
return this.settingsStore.appSettings.thousandsSeparator;
|
||||
},
|
||||
set: function (value) {
|
||||
this.settingsStore.setEnableThousandsSeparator(value);
|
||||
}
|
||||
},
|
||||
currencyDisplayMode: {
|
||||
get: function () {
|
||||
return this.settingsStore.appSettings.currencyDisplayMode;
|
||||
|
||||
@@ -277,10 +277,7 @@ export default {
|
||||
}
|
||||
},
|
||||
getDisplayCurrency(value, currencyCode) {
|
||||
return this.$locale.getDisplayCurrency(value, currencyCode, {
|
||||
currencyDisplayMode: this.settingsStore.appSettings.currencyDisplayMode,
|
||||
enableThousandsSeparator: this.settingsStore.appSettings.thousandsSeparator
|
||||
});
|
||||
return this.$locale.formatAmountWithCurrency(this.settingsStore, this.userStore, value, currencyCode);
|
||||
},
|
||||
getDisplayAmount(amount, incomplete) {
|
||||
if (!this.showAmountInHomePage) {
|
||||
|
||||
@@ -827,10 +827,7 @@ export default {
|
||||
return amount;
|
||||
},
|
||||
getDisplayCurrency(value, currencyCode) {
|
||||
return this.$locale.getDisplayCurrency(value, currencyCode, {
|
||||
currencyDisplayMode: this.settingsStore.appSettings.currencyDisplayMode,
|
||||
enableThousandsSeparator: this.settingsStore.appSettings.thousandsSeparator
|
||||
});
|
||||
return this.$locale.formatAmountWithCurrency(this.settingsStore, this.userStore, value, currencyCode);
|
||||
},
|
||||
getDisplayPercent(value, precision, lowPrecisionValue) {
|
||||
return formatPercent(value, precision, lowPrecisionValue);
|
||||
|
||||
@@ -960,10 +960,7 @@ export default {
|
||||
return symbol + displayAmount + (incomplete ? '+' : '');
|
||||
},
|
||||
getDisplayCurrency(value, currencyCode) {
|
||||
return this.$locale.getDisplayCurrency(value, currencyCode, {
|
||||
currencyDisplayMode: this.settingsStore.appSettings.currencyDisplayMode,
|
||||
enableThousandsSeparator: this.settingsStore.appSettings.thousandsSeparator
|
||||
});
|
||||
return this.$locale.formatAmountWithCurrency(this.settingsStore, this.userStore, value, currencyCode);
|
||||
},
|
||||
getLongDate(transaction) {
|
||||
const transactionTime = getUnixTime(parseDateFromUnixTime(transaction.time, transaction.utcOffset, this.currentTimezoneOffsetMinutes));
|
||||
|
||||
@@ -338,9 +338,6 @@ import {
|
||||
getTimezoneOffsetMinutes,
|
||||
getCurrentUnixTime
|
||||
} from '@/lib/datetime.js';
|
||||
import {
|
||||
getAdaptiveDisplayAmountRate
|
||||
} from '@/lib/currency.js';
|
||||
import {
|
||||
getFirstAvailableCategoryId
|
||||
} from '@/lib/category.js';
|
||||
@@ -445,7 +442,7 @@ export default {
|
||||
|
||||
const fromExchangeRate = this.exchangeRatesStore.latestExchangeRateMap[sourceAccount.currency];
|
||||
const toExchangeRate = this.exchangeRatesStore.latestExchangeRateMap[destinationAccount.currency];
|
||||
const amountRate = getAdaptiveDisplayAmountRate(this.transaction.sourceAmount, this.transaction.destinationAmount, fromExchangeRate, toExchangeRate, this.settingsStore.appSettings.thousandsSeparator);
|
||||
const amountRate = this.$locale.getAdaptiveAmountRate(this.userStore, this.transaction.sourceAmount, this.transaction.destinationAmount, fromExchangeRate, toExchangeRate);
|
||||
|
||||
if (!amountRate) {
|
||||
return this.$t('Transfer In Amount');
|
||||
@@ -475,10 +472,7 @@ export default {
|
||||
return this.accountsStore.allVisiblePlainAccounts;
|
||||
},
|
||||
categorizedAccounts() {
|
||||
return this.$locale.getCategorizedAccountsWithDisplayBalance(this.exchangeRatesStore, this.allVisibleAccounts, this.showAccountBalance, this.defaultCurrency, {
|
||||
currencyDisplayMode: this.settingsStore.appSettings.currencyDisplayMode,
|
||||
enableThousandsSeparator: this.settingsStore.appSettings.thousandsSeparator
|
||||
});
|
||||
return this.$locale.getCategorizedAccountsWithDisplayBalance(this.allVisibleAccounts, this.showAccountBalance, this.defaultCurrency, this.settingsStore, this.userStore, this.exchangeRatesStore);
|
||||
},
|
||||
allAccountsMap() {
|
||||
return this.accountsStore.allAccountsMap;
|
||||
|
||||
@@ -204,6 +204,47 @@
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12" md="6">
|
||||
<v-select
|
||||
item-title="displayName"
|
||||
item-value="type"
|
||||
persistent-placeholder
|
||||
:disabled="loading || saving"
|
||||
:label="$t('Decimal Separator')"
|
||||
:placeholder="$t('Decimal Separator')"
|
||||
:items="allDecimalSeparators"
|
||||
v-model="newProfile.decimalSeparator"
|
||||
/>
|
||||
</v-col>
|
||||
|
||||
<v-col cols="12" md="6">
|
||||
<v-select
|
||||
item-title="displayName"
|
||||
item-value="type"
|
||||
persistent-placeholder
|
||||
:disabled="loading || saving"
|
||||
:label="$t('Digit Grouping Symbol')"
|
||||
:placeholder="$t('Digit Grouping Symbol')"
|
||||
:items="allDigitGroupingSymbols"
|
||||
v-model="newProfile.digitGroupingSymbol"
|
||||
/>
|
||||
</v-col>
|
||||
|
||||
<v-col cols="12" md="6">
|
||||
<v-select
|
||||
item-title="displayName"
|
||||
item-value="type"
|
||||
persistent-placeholder
|
||||
:disabled="loading || saving"
|
||||
:label="$t('Digit Grouping')"
|
||||
:placeholder="$t('Digit Grouping')"
|
||||
:items="allDigitGroupingTypes"
|
||||
v-model="newProfile.digitGrouping"
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card-text>
|
||||
|
||||
<v-card-text class="d-flex flex-wrap gap-4">
|
||||
@@ -259,7 +300,10 @@ export default {
|
||||
longDateFormat: 0,
|
||||
shortDateFormat: 0,
|
||||
longTimeFormat: 0,
|
||||
shortTimeFormat: 0
|
||||
shortTimeFormat: 0,
|
||||
decimalSeparator: 0,
|
||||
digitGroupingSymbol: 0,
|
||||
digitGrouping: 0
|
||||
},
|
||||
oldProfile: {
|
||||
email: '',
|
||||
@@ -272,7 +316,10 @@ export default {
|
||||
longDateFormat: 0,
|
||||
shortDateFormat: 0,
|
||||
longTimeFormat: 0,
|
||||
shortTimeFormat: 0
|
||||
shortTimeFormat: 0,
|
||||
decimalSeparator: 0,
|
||||
digitGroupingSymbol: 0,
|
||||
digitGrouping: 0
|
||||
},
|
||||
emailVerified: false,
|
||||
loading: true,
|
||||
@@ -315,6 +362,15 @@ export default {
|
||||
allShortTimeFormats() {
|
||||
return this.$locale.getAllShortTimeFormats();
|
||||
},
|
||||
allDecimalSeparators() {
|
||||
return this.$locale.getAllDecimalSeparators();
|
||||
},
|
||||
allDigitGroupingSymbols() {
|
||||
return this.$locale.getAllDigitGroupingSymbols();
|
||||
},
|
||||
allDigitGroupingTypes() {
|
||||
return this.$locale.getAllDigitGroupingTypes();
|
||||
},
|
||||
allTransactionEditScopeTypes() {
|
||||
return this.$locale.getAllTransactionEditScopeTypes();
|
||||
},
|
||||
@@ -346,7 +402,10 @@ export default {
|
||||
this.newProfile.longDateFormat === this.oldProfile.longDateFormat &&
|
||||
this.newProfile.shortDateFormat === this.oldProfile.shortDateFormat &&
|
||||
this.newProfile.longTimeFormat === this.oldProfile.longTimeFormat &&
|
||||
this.newProfile.shortTimeFormat === this.oldProfile.shortTimeFormat) {
|
||||
this.newProfile.shortTimeFormat === this.oldProfile.shortTimeFormat &&
|
||||
this.newProfile.decimalSeparator === this.oldProfile.decimalSeparator &&
|
||||
this.newProfile.digitGroupingSymbol === this.oldProfile.digitGroupingSymbol &&
|
||||
this.newProfile.digitGrouping === this.oldProfile.digitGrouping) {
|
||||
return 'Nothing has been modified';
|
||||
} else {
|
||||
return null;
|
||||
@@ -473,6 +532,9 @@ export default {
|
||||
this.oldProfile.shortDateFormat = profile.shortDateFormat;
|
||||
this.oldProfile.longTimeFormat = profile.longTimeFormat;
|
||||
this.oldProfile.shortTimeFormat = profile.shortTimeFormat;
|
||||
this.oldProfile.decimalSeparator = profile.decimalSeparator;
|
||||
this.oldProfile.digitGroupingSymbol = profile.digitGroupingSymbol;
|
||||
this.oldProfile.digitGrouping = profile.digitGrouping;
|
||||
|
||||
this.newProfile.email = this.oldProfile.email
|
||||
this.newProfile.nickname = this.oldProfile.nickname;
|
||||
@@ -485,6 +547,9 @@ export default {
|
||||
this.newProfile.shortDateFormat = this.oldProfile.shortDateFormat;
|
||||
this.newProfile.longTimeFormat = this.oldProfile.longTimeFormat;
|
||||
this.newProfile.shortTimeFormat = this.oldProfile.shortTimeFormat;
|
||||
this.newProfile.decimalSeparator = this.oldProfile.decimalSeparator;
|
||||
this.newProfile.digitGroupingSymbol = this.oldProfile.digitGroupingSymbol;
|
||||
this.newProfile.digitGrouping = this.oldProfile.digitGrouping;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -167,7 +167,6 @@ import { useSettingsStore } from '@/stores/setting.js';
|
||||
import { useUserStore } from '@/stores/user.js';
|
||||
|
||||
import { isEquals } from '@/lib/common.js';
|
||||
import { appendThousandsSeparator } from '@/lib/numeral.js';
|
||||
import { isDataExportingEnabled } from '@/lib/server_settings.js';
|
||||
import { startDownloadFile } from '@/lib/ui.js';
|
||||
|
||||
@@ -205,9 +204,6 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
...mapStores(useRootStore, useSettingsStore, useUserStore),
|
||||
isEnableThousandsSeparator() {
|
||||
return this.settingsStore.appSettings.thousandsSeparator;
|
||||
},
|
||||
displayDataStatistics() {
|
||||
const self = this;
|
||||
|
||||
@@ -216,10 +212,10 @@ export default {
|
||||
}
|
||||
|
||||
return {
|
||||
totalAccountCount: appendThousandsSeparator(self.dataStatistics.totalAccountCount, self.isEnableThousandsSeparator),
|
||||
totalTransactionCategoryCount: appendThousandsSeparator(self.dataStatistics.totalTransactionCategoryCount, self.isEnableThousandsSeparator),
|
||||
totalTransactionTagCount: appendThousandsSeparator(self.dataStatistics.totalTransactionTagCount, self.isEnableThousandsSeparator),
|
||||
totalTransactionCount: appendThousandsSeparator(self.dataStatistics.totalTransactionCount, self.isEnableThousandsSeparator)
|
||||
totalAccountCount: self.$locale.appendDigitGroupingSymbol(self.userStore, self.dataStatistics.totalAccountCount),
|
||||
totalTransactionCategoryCount: self.$locale.appendDigitGroupingSymbol(self.userStore, self.dataStatistics.totalTransactionCategoryCount),
|
||||
totalTransactionTagCount: self.$locale.appendDigitGroupingSymbol(self.userStore, self.dataStatistics.totalTransactionTagCount),
|
||||
totalTransactionCount: self.$locale.appendDigitGroupingSymbol(self.userStore, self.dataStatistics.totalTransactionCount)
|
||||
};
|
||||
},
|
||||
isDataExportingEnabled() {
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
|
||||
<f7-list strong inset dividers class="margin-vertical" v-if="exchangeRatesData && exchangeRatesData.exchangeRates && exchangeRatesData.exchangeRates.length">
|
||||
<f7-list-item swipeout
|
||||
:after="getDisplayConvertedAmount(exchangeRate)"
|
||||
:after="getConvertedAmount(exchangeRate)"
|
||||
:key="exchangeRate.currencyCode" v-for="exchangeRate in availableExchangeRates">
|
||||
<template #title>
|
||||
<div class="no-padding no-margin">
|
||||
@@ -97,12 +97,7 @@ import { useExchangeRatesStore } from '@/stores/exchangeRates.js';
|
||||
|
||||
import transactionConstants from '@/consts/transaction.js';
|
||||
import { isNumber } from '@/lib/common.js';
|
||||
import {
|
||||
numericCurrencyToString,
|
||||
stringCurrencyToNumeric,
|
||||
getConvertedAmount,
|
||||
getDisplayExchangeRateAmount
|
||||
} from '@/lib/currency.js';
|
||||
import { getConvertedAmount } from '@/lib/numeral.js';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
@@ -118,9 +113,6 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
...mapStores(useSettingsStore, useUserStore, useExchangeRatesStore),
|
||||
isEnableThousandsSeparator() {
|
||||
return this.settingsStore.appSettings.thousandsSeparator;
|
||||
},
|
||||
exchangeRatesData() {
|
||||
return this.exchangeRatesStore.latestExchangeRates.data;
|
||||
},
|
||||
@@ -132,7 +124,7 @@ export default {
|
||||
return this.$locale.getAllDisplayExchangeRates(this.exchangeRatesData);
|
||||
},
|
||||
displayBaseAmount() {
|
||||
return numericCurrencyToString(this.baseAmount, this.isEnableThousandsSeparator);
|
||||
return this.$locale.formatAmount(this.userStore, this.baseAmount);
|
||||
},
|
||||
baseAmountFontSizeClass() {
|
||||
if (this.baseAmount >= 100000000 || this.baseAmount <= -100000000) {
|
||||
@@ -144,10 +136,10 @@ export default {
|
||||
}
|
||||
},
|
||||
allowedMinAmount() {
|
||||
return transactionConstants.minAmount;
|
||||
return transactionConstants.minAmountNumber;
|
||||
},
|
||||
allowedMaxAmount() {
|
||||
return transactionConstants.maxAmount;
|
||||
return transactionConstants.maxAmountNumber;
|
||||
}
|
||||
},
|
||||
created() {
|
||||
@@ -212,19 +204,12 @@ export default {
|
||||
},
|
||||
getConvertedAmount(toExchangeRate) {
|
||||
const fromExchangeRate = this.exchangeRatesStore.latestExchangeRateMap[this.baseCurrency];
|
||||
return getConvertedAmount(this.baseAmount / 100, fromExchangeRate, toExchangeRate);
|
||||
},
|
||||
getDisplayConvertedAmount(toExchangeRate) {
|
||||
const rateStr = this.getConvertedAmount(toExchangeRate).toString();
|
||||
return getDisplayExchangeRateAmount(rateStr, this.isEnableThousandsSeparator);
|
||||
const exchangeRateAmount = getConvertedAmount(this.baseAmount / 100, fromExchangeRate, toExchangeRate);
|
||||
return this.$locale.formatExchangeRateAmount(this.userStore, exchangeRateAmount);
|
||||
},
|
||||
setAsBaseline(currency, amount) {
|
||||
if (!isNumber(amount)) {
|
||||
amount = '';
|
||||
}
|
||||
|
||||
this.baseCurrency = currency;
|
||||
this.baseAmount = stringCurrencyToNumeric(amount.toString());
|
||||
this.baseAmount = this.$locale.parseAmount(this.userStore, amount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -293,10 +293,7 @@ export default {
|
||||
});
|
||||
},
|
||||
getDisplayCurrency(value, currencyCode) {
|
||||
return this.$locale.getDisplayCurrency(value, currencyCode, {
|
||||
currencyDisplayMode: this.settingsStore.appSettings.currencyDisplayMode,
|
||||
enableThousandsSeparator: this.settingsStore.appSettings.thousandsSeparator
|
||||
});
|
||||
return this.$locale.formatAmountWithCurrency(this.settingsStore, this.userStore, value, currencyCode);
|
||||
},
|
||||
getDisplayAmount(amount, incomplete) {
|
||||
if (!this.showAmountInHomePage) {
|
||||
|
||||
@@ -47,11 +47,6 @@
|
||||
<f7-toggle :checked="isAutoUpdateExchangeRatesData" @toggle:change="isAutoUpdateExchangeRatesData = $event"></f7-toggle>
|
||||
</f7-list-item>
|
||||
|
||||
<f7-list-item>
|
||||
<span>{{ $t('Enable Thousands Separator') }}</span>
|
||||
<f7-toggle :checked="isEnableThousandsSeparator" @toggle:change="isEnableThousandsSeparator = $event"></f7-toggle>
|
||||
</f7-list-item>
|
||||
|
||||
<f7-list-item
|
||||
:key="currentLocale + '_currency_display'"
|
||||
:title="$t('Currency Display Mode')"
|
||||
@@ -165,14 +160,6 @@ export default {
|
||||
isEnableApplicationLock() {
|
||||
return this.settingsStore.appSettings.applicationLock;
|
||||
},
|
||||
isEnableThousandsSeparator: {
|
||||
get: function () {
|
||||
return this.settingsStore.appSettings.thousandsSeparator;
|
||||
},
|
||||
set: function (value) {
|
||||
this.settingsStore.setEnableThousandsSeparator(value);
|
||||
}
|
||||
},
|
||||
currencyDisplayMode: {
|
||||
get: function () {
|
||||
return this.settingsStore.appSettings.currencyDisplayMode;
|
||||
|
||||
@@ -420,6 +420,7 @@
|
||||
<script>
|
||||
import { mapStores } from 'pinia';
|
||||
import { useSettingsStore } from '@/stores/setting.js';
|
||||
import { useUserStore } from '@/stores/user.js';
|
||||
import { useAccountsStore } from '@/stores/account.js';
|
||||
|
||||
import accountConstants from '@/consts/account.js';
|
||||
@@ -459,7 +460,7 @@ export default {
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapStores(useSettingsStore, useAccountsStore),
|
||||
...mapStores(useSettingsStore, useUserStore, useAccountsStore),
|
||||
title() {
|
||||
if (!this.editAccountId) {
|
||||
return 'Add Account';
|
||||
@@ -493,10 +494,10 @@ export default {
|
||||
return this.$locale.getAllCurrencies();
|
||||
},
|
||||
allowedMinAmount() {
|
||||
return transactionConstants.minAmount;
|
||||
return transactionConstants.minAmountNumber;
|
||||
},
|
||||
allowedMaxAmount() {
|
||||
return transactionConstants.maxAmount;
|
||||
return transactionConstants.maxAmountNumber;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@@ -647,10 +648,7 @@ export default {
|
||||
return this.getDisplayCurrency(account.balance, account.currency);
|
||||
},
|
||||
getDisplayCurrency(value, currencyCode) {
|
||||
return this.$locale.getDisplayCurrency(value, currencyCode, {
|
||||
currencyDisplayMode: this.settingsStore.appSettings.currencyDisplayMode,
|
||||
enableThousandsSeparator: this.settingsStore.appSettings.thousandsSeparator
|
||||
});
|
||||
return this.$locale.formatAmountWithCurrency(this.settingsStore, this.userStore, value, currencyCode);
|
||||
},
|
||||
chooseSuitableIcon(oldCategory, newCategory) {
|
||||
setAccountSuitableIcon(this.account, oldCategory, newCategory);
|
||||
|
||||
@@ -438,10 +438,7 @@ export default {
|
||||
});
|
||||
},
|
||||
getDisplayCurrency(value, currencyCode) {
|
||||
return this.$locale.getDisplayCurrency(value, currencyCode, {
|
||||
currencyDisplayMode: this.settingsStore.appSettings.currencyDisplayMode,
|
||||
enableThousandsSeparator: this.settingsStore.appSettings.thousandsSeparator
|
||||
});
|
||||
return this.$locale.formatAmountWithCurrency(this.settingsStore, this.userStore, value, currencyCode);
|
||||
},
|
||||
getAccountDomId(account) {
|
||||
return 'account_' + account.id;
|
||||
|
||||
@@ -164,10 +164,7 @@ export default {
|
||||
return '';
|
||||
},
|
||||
getDisplayAmount(value) {
|
||||
return this.$locale.getDisplayCurrency(value, this.userStore.currentUserDefaultCurrency, {
|
||||
currencyDisplayMode: this.settingsStore.appSettings.currencyDisplayMode,
|
||||
enableThousandsSeparator: this.settingsStore.appSettings.thousandsSeparator
|
||||
});
|
||||
return this.$locale.formatAmountWithCurrency(this.settingsStore, this.userStore, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -562,10 +562,7 @@ export default {
|
||||
return amount;
|
||||
},
|
||||
getDisplayCurrency(value, currencyCode) {
|
||||
return this.$locale.getDisplayCurrency(value, currencyCode, {
|
||||
currencyDisplayMode: this.settingsStore.appSettings.currencyDisplayMode,
|
||||
enableThousandsSeparator: this.settingsStore.appSettings.thousandsSeparator
|
||||
});
|
||||
return this.$locale.formatAmountWithCurrency(this.settingsStore, this.userStore, value, currencyCode);
|
||||
},
|
||||
getDisplayPercent(value, precision, lowPrecisionValue) {
|
||||
return formatPercent(value, precision, lowPrecisionValue);
|
||||
|
||||
@@ -367,9 +367,6 @@ import {
|
||||
getUtcOffsetByUtcOffsetMinutes,
|
||||
getActualUnixTimeForStore
|
||||
} from '@/lib/datetime.js';
|
||||
import {
|
||||
getAdaptiveDisplayAmountRate
|
||||
} from '@/lib/currency.js';
|
||||
import {
|
||||
getTransactionPrimaryCategoryName,
|
||||
getTransactionSecondaryCategoryName,
|
||||
@@ -458,7 +455,7 @@ export default {
|
||||
|
||||
const fromExchangeRate = this.exchangeRatesStore.latestExchangeRateMap[sourceAccount.currency];
|
||||
const toExchangeRate = this.exchangeRatesStore.latestExchangeRateMap[destinationAccount.currency];
|
||||
const amountRate = getAdaptiveDisplayAmountRate(this.transaction.sourceAmount, this.transaction.destinationAmount, fromExchangeRate, toExchangeRate, this.settingsStore.appSettings.thousandsSeparator);
|
||||
const amountRate = this.$locale.getAdaptiveAmountRate(this.userStore, this.transaction.sourceAmount, this.transaction.destinationAmount, fromExchangeRate, toExchangeRate);
|
||||
|
||||
if (!amountRate) {
|
||||
return this.$t('Transfer In Amount');
|
||||
@@ -494,10 +491,7 @@ export default {
|
||||
return this.accountsStore.allAccountsMap;
|
||||
},
|
||||
categorizedAccounts() {
|
||||
return this.$locale.getCategorizedAccountsWithDisplayBalance(this.exchangeRatesStore, this.allVisibleAccounts, this.showAccountBalance, this.defaultCurrency, {
|
||||
currencyDisplayMode: this.settingsStore.appSettings.currencyDisplayMode,
|
||||
enableThousandsSeparator: this.settingsStore.appSettings.thousandsSeparator
|
||||
});
|
||||
return this.$locale.getCategorizedAccountsWithDisplayBalance(this.allVisibleAccounts, this.showAccountBalance, this.defaultCurrency, this.settingsStore, this.userStore, this.exchangeRatesStore);
|
||||
},
|
||||
allCategories() {
|
||||
return this.transactionCategoriesStore.allTransactionCategories;
|
||||
@@ -593,10 +587,10 @@ export default {
|
||||
}
|
||||
},
|
||||
allowedMinAmount() {
|
||||
return transactionConstants.minAmount;
|
||||
return transactionConstants.minAmountNumber;
|
||||
},
|
||||
allowedMaxAmount() {
|
||||
return transactionConstants.maxAmount;
|
||||
return transactionConstants.maxAmountNumber;
|
||||
},
|
||||
showAccountBalance() {
|
||||
return this.settingsStore.appSettings.showAccountBalance;
|
||||
@@ -833,11 +827,8 @@ export default {
|
||||
|
||||
return this.getDisplayCurrency(amount);
|
||||
},
|
||||
getDisplayCurrency(value, currencyCode) {
|
||||
return this.$locale.getDisplayCurrency(value, currencyCode, {
|
||||
currencyDisplayMode: this.settingsStore.appSettings.currencyDisplayMode,
|
||||
enableThousandsSeparator: this.settingsStore.appSettings.thousandsSeparator
|
||||
});
|
||||
getDisplayCurrency(value) {
|
||||
return this.$locale.formatAmountWithCurrency(this.settingsStore, this.userStore, value, false);
|
||||
},
|
||||
getPrimaryCategoryName(categoryId, allCategories) {
|
||||
return getTransactionPrimaryCategoryName(categoryId, allCategories);
|
||||
|
||||
@@ -870,10 +870,7 @@ export default {
|
||||
return symbol + displayAmount + (incomplete ? '+' : '');
|
||||
},
|
||||
getDisplayCurrency(value, currencyCode) {
|
||||
return this.$locale.getDisplayCurrency(value, currencyCode, {
|
||||
currencyDisplayMode: this.settingsStore.appSettings.currencyDisplayMode,
|
||||
enableThousandsSeparator: this.settingsStore.appSettings.thousandsSeparator
|
||||
});
|
||||
return this.$locale.formatAmountWithCurrency(this.settingsStore, this.userStore, value, currencyCode);
|
||||
},
|
||||
getWeekdayShortName(transaction) {
|
||||
return this.$locale.getWeekdayShortName(transaction.dayOfWeek);
|
||||
|
||||
@@ -73,7 +73,6 @@ import { useRootStore } from '@/stores/index.js';
|
||||
import { useSettingsStore } from '@/stores/setting.js';
|
||||
import { useUserStore } from '@/stores/user.js';
|
||||
|
||||
import { appendThousandsSeparator } from '@/lib/numeral.js';
|
||||
import { isDataExportingEnabled } from '@/lib/server_settings.js';
|
||||
|
||||
export default {
|
||||
@@ -96,9 +95,6 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
...mapStores(useRootStore, useSettingsStore, useUserStore),
|
||||
isEnableThousandsSeparator() {
|
||||
return this.settingsStore.appSettings.thousandsSeparator;
|
||||
},
|
||||
displayDataStatistics() {
|
||||
const self = this;
|
||||
|
||||
@@ -107,10 +103,10 @@ export default {
|
||||
}
|
||||
|
||||
return {
|
||||
totalAccountCount: appendThousandsSeparator(self.dataStatistics.totalAccountCount, self.isEnableThousandsSeparator),
|
||||
totalTransactionCategoryCount: appendThousandsSeparator(self.dataStatistics.totalTransactionCategoryCount, self.isEnableThousandsSeparator),
|
||||
totalTransactionTagCount: appendThousandsSeparator(self.dataStatistics.totalTransactionTagCount, self.isEnableThousandsSeparator),
|
||||
totalTransactionCount: appendThousandsSeparator(self.dataStatistics.totalTransactionCount, self.isEnableThousandsSeparator)
|
||||
totalAccountCount: self.$locale.appendDigitGroupingSymbol(self.userStore, self.dataStatistics.totalAccountCount),
|
||||
totalTransactionCategoryCount: self.$locale.appendDigitGroupingSymbol(self.userStore, self.dataStatistics.totalTransactionCategoryCount),
|
||||
totalTransactionTagCount: self.$locale.appendDigitGroupingSymbol(self.userStore, self.dataStatistics.totalTransactionTagCount),
|
||||
totalTransactionCount: self.$locale.appendDigitGroupingSymbol(self.userStore, self.dataStatistics.totalTransactionCount)
|
||||
};
|
||||
},
|
||||
isDataExportingEnabled() {
|
||||
|
||||
@@ -206,6 +206,45 @@
|
||||
</select>
|
||||
</f7-list-item>
|
||||
|
||||
<f7-list-item
|
||||
class="list-item-with-header-and-title list-item-no-item-after"
|
||||
:header="$t('Decimal Separator')"
|
||||
:title="getNameByKeyValue(allDecimalSeparators, newProfile.decimalSeparator, 'type', 'displayName')"
|
||||
smart-select :smart-select-params="{ openIn: 'popup', popupPush: true, closeOnSelect: true, scrollToSelectedItem: true, searchbar: true, searchbarPlaceholder: $t('Decimal Separator'), searchbarDisableText: $t('Cancel'), appendSearchbarNotFound: $t('No results'), pageTitle: $t('Decimal Separator'), popupCloseLinkText: $t('Done') }"
|
||||
>
|
||||
<select v-model="newProfile.decimalSeparator">
|
||||
<option :value="format.type"
|
||||
:key="format.type"
|
||||
v-for="format in allDecimalSeparators">{{ format.displayName }}</option>
|
||||
</select>
|
||||
</f7-list-item>
|
||||
|
||||
<f7-list-item
|
||||
class="list-item-with-header-and-title list-item-no-item-after"
|
||||
:header="$t('Digit Grouping Symbol')"
|
||||
:title="getNameByKeyValue(allDigitGroupingSymbols, newProfile.digitGroupingSymbol, 'type', 'displayName')"
|
||||
smart-select :smart-select-params="{ openIn: 'popup', popupPush: true, closeOnSelect: true, scrollToSelectedItem: true, searchbar: true, searchbarPlaceholder: $t('Digit Grouping Symbol'), searchbarDisableText: $t('Cancel'), appendSearchbarNotFound: $t('No results'), pageTitle: $t('Digit Grouping Symbol'), popupCloseLinkText: $t('Done') }"
|
||||
>
|
||||
<select v-model="newProfile.digitGroupingSymbol">
|
||||
<option :value="format.type"
|
||||
:key="format.type"
|
||||
v-for="format in allDigitGroupingSymbols">{{ format.displayName }}</option>
|
||||
</select>
|
||||
</f7-list-item>
|
||||
|
||||
<f7-list-item
|
||||
class="list-item-with-header-and-title list-item-no-item-after"
|
||||
:header="$t('Digit Grouping')"
|
||||
:title="getNameByKeyValue(allDigitGroupingTypes, newProfile.digitGrouping, 'type', 'displayName')"
|
||||
smart-select :smart-select-params="{ openIn: 'popup', popupPush: true, closeOnSelect: true, scrollToSelectedItem: true, searchbar: true, searchbarPlaceholder: $t('Digit Grouping'), searchbarDisableText: $t('Cancel'), appendSearchbarNotFound: $t('No results'), pageTitle: $t('Digit Grouping'), popupCloseLinkText: $t('Done') }"
|
||||
>
|
||||
<select v-model="newProfile.digitGrouping">
|
||||
<option :value="format.type"
|
||||
:key="format.type"
|
||||
v-for="format in allDigitGroupingTypes">{{ format.displayName }}</option>
|
||||
</select>
|
||||
</f7-list-item>
|
||||
|
||||
<f7-list-item class="ebk-list-item-error-info" v-if="langAndRegionInputIsInvalid" :footer="$t(langAndRegionInputInvalidProblemMessage)"></f7-list-item>
|
||||
</f7-list>
|
||||
|
||||
@@ -261,7 +300,10 @@ export default {
|
||||
longDateFormat: 0,
|
||||
shortDateFormat: 0,
|
||||
longTimeFormat: 0,
|
||||
shortTimeFormat: 0
|
||||
shortTimeFormat: 0,
|
||||
decimalSeparator: 0,
|
||||
digitGroupingSymbol: 0,
|
||||
digitGrouping: 0
|
||||
},
|
||||
oldProfile: {
|
||||
email: '',
|
||||
@@ -274,7 +316,10 @@ export default {
|
||||
longDateFormat: 0,
|
||||
shortDateFormat: 0,
|
||||
longTimeFormat: 0,
|
||||
shortTimeFormat: 0
|
||||
shortTimeFormat: 0,
|
||||
decimalSeparator: 0,
|
||||
digitGroupingSymbol: 0,
|
||||
digitGrouping: 0
|
||||
},
|
||||
emailVerified: false,
|
||||
currentPassword: '',
|
||||
@@ -319,6 +364,15 @@ export default {
|
||||
allShortTimeFormats() {
|
||||
return this.$locale.getAllShortTimeFormats();
|
||||
},
|
||||
allDecimalSeparators() {
|
||||
return this.$locale.getAllDecimalSeparators();
|
||||
},
|
||||
allDigitGroupingSymbols() {
|
||||
return this.$locale.getAllDigitGroupingSymbols();
|
||||
},
|
||||
allDigitGroupingTypes() {
|
||||
return this.$locale.getAllDigitGroupingTypes();
|
||||
},
|
||||
allTransactionEditScopeTypes() {
|
||||
return this.$locale.getAllTransactionEditScopeTypes();
|
||||
},
|
||||
@@ -363,7 +417,10 @@ export default {
|
||||
this.newProfile.longDateFormat === this.oldProfile.longDateFormat &&
|
||||
this.newProfile.shortDateFormat === this.oldProfile.shortDateFormat &&
|
||||
this.newProfile.longTimeFormat === this.oldProfile.longTimeFormat &&
|
||||
this.newProfile.shortTimeFormat === this.oldProfile.shortTimeFormat) {
|
||||
this.newProfile.shortTimeFormat === this.oldProfile.shortTimeFormat &&
|
||||
this.newProfile.decimalSeparator === this.oldProfile.decimalSeparator &&
|
||||
this.newProfile.digitGroupingSymbol === this.oldProfile.digitGroupingSymbol &&
|
||||
this.newProfile.digitGrouping === this.oldProfile.digitGrouping) {
|
||||
return 'Nothing has been modified';
|
||||
} else if (!this.newProfile.password && this.newProfile.confirmPassword) {
|
||||
return 'Password cannot be blank';
|
||||
@@ -512,6 +569,9 @@ export default {
|
||||
this.oldProfile.shortDateFormat = profile.shortDateFormat;
|
||||
this.oldProfile.longTimeFormat = profile.longTimeFormat;
|
||||
this.oldProfile.shortTimeFormat = profile.shortTimeFormat;
|
||||
this.oldProfile.decimalSeparator = profile.decimalSeparator;
|
||||
this.oldProfile.digitGroupingSymbol = profile.digitGroupingSymbol;
|
||||
this.oldProfile.digitGrouping = profile.digitGrouping;
|
||||
|
||||
this.newProfile.email = this.oldProfile.email
|
||||
this.newProfile.nickname = this.oldProfile.nickname;
|
||||
@@ -524,6 +584,9 @@ export default {
|
||||
this.newProfile.shortDateFormat = this.oldProfile.shortDateFormat;
|
||||
this.newProfile.longTimeFormat = this.oldProfile.longTimeFormat;
|
||||
this.newProfile.shortTimeFormat = this.oldProfile.shortTimeFormat;
|
||||
this.newProfile.decimalSeparator = this.oldProfile.decimalSeparator;
|
||||
this.newProfile.digitGroupingSymbol = this.oldProfile.digitGroupingSymbol;
|
||||
this.newProfile.digitGrouping = this.oldProfile.digitGrouping;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user