From 399413a270fce0df126dba23fbfb35a127b52885 Mon Sep 17 00:00:00 2001 From: MaysWind Date: Sat, 29 Jun 2024 17:12:22 +0800 Subject: [PATCH] support setting decimal separator and digit grouping symbol --- cmd/user_data.go | 3 + pkg/api/users.go | 52 +++ pkg/errs/user.go | 47 +-- pkg/locales/all_locales.go | 24 ++ pkg/locales/base.go | 8 + pkg/locales/en.go | 6 + pkg/locales/zh_hans.go | 6 + pkg/models/numeral.go | 95 +++++ pkg/models/user.go | 18 + pkg/services/users.go | 12 + src/components/desktop/AmountInput.vue | 176 +++++++-- src/components/desktop/PieChart.vue | 8 +- src/components/desktop/TrendsChart.vue | 5 +- src/components/mobile/NumberPadSheet.vue | 90 +++-- src/components/mobile/PieChart.vue | 8 +- src/consts/numeral.js | 108 ++++++ src/consts/transaction.js | 8 +- src/lib/common.js | 8 + src/lib/currency.js | 153 -------- src/lib/i18n.js | 344 +++++++++++++----- src/lib/numeral.js | 247 ++++++++++++- src/lib/services.js | 7 +- src/lib/settings.js | 9 - src/locales/en.js | 18 +- src/locales/zh_Hans.js | 18 +- src/stores/exchangeRates.js | 2 +- src/stores/index.js | 5 +- src/stores/setting.js | 5 - src/stores/transaction.js | 6 +- src/stores/user.js | 12 + src/views/desktop/ExchangeRatesPage.vue | 33 +- src/views/desktop/HomePage.vue | 5 +- src/views/desktop/accounts/ListPage.vue | 5 +- .../app/settings/tabs/AppBasicSettingTab.vue | 20 - .../cards/MonthlyIncomeAndExpenseCard.vue | 5 +- .../desktop/statistics/TransactionPage.vue | 5 +- src/views/desktop/transactions/ListPage.vue | 5 +- .../transactions/list/dialogs/EditDialog.vue | 10 +- .../settings/tabs/UserBasicSettingTab.vue | 71 +++- .../tabs/UserDataManagementSettingTab.vue | 12 +- src/views/mobile/ExchangeRatesPage.vue | 31 +- src/views/mobile/HomePage.vue | 5 +- src/views/mobile/SettingsPage.vue | 13 - src/views/mobile/accounts/EditPage.vue | 12 +- src/views/mobile/accounts/ListPage.vue | 5 +- .../mobile/settings/TextSizeSettingsPage.vue | 5 +- .../mobile/statistics/TransactionPage.vue | 5 +- src/views/mobile/transactions/EditPage.vue | 21 +- src/views/mobile/transactions/ListPage.vue | 5 +- src/views/mobile/users/DataManagementPage.vue | 12 +- src/views/mobile/users/UserProfilePage.vue | 69 +++- 51 files changed, 1280 insertions(+), 582 deletions(-) create mode 100644 pkg/models/numeral.go create mode 100644 src/consts/numeral.js delete mode 100644 src/lib/currency.js diff --git a/cmd/user_data.go b/cmd/user_data.go index bcb95861..b13b6d89 100644 --- a/cmd/user_data.go +++ b/cmd/user_data.go @@ -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) diff --git a/pkg/api/users.go b/pkg/api/users.go index 2285f311..28b9160a 100644 --- a/pkg/api/users.go +++ b/pkg/api/users.go @@ -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 } diff --git a/pkg/errs/user.go b/pkg/errs/user.go index 28c7fee2..4ae509fe 100644 --- a/pkg/errs/user.go +++ b/pkg/errs/user.go @@ -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") ) diff --git a/pkg/locales/all_locales.go b/pkg/locales/all_locales.go index 04ccc83c..b62220a8 100644 --- a/pkg/locales/all_locales.go +++ b/pkg/locales/all_locales.go @@ -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) +} diff --git a/pkg/locales/base.go b/pkg/locales/base.go index f982e7d0..3f511ced 100644 --- a/pkg/locales/base.go +++ b/pkg/locales/base.go @@ -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 diff --git a/pkg/locales/en.go b/pkg/locales/en.go index 733eba62..de34b69b 100644 --- a/pkg/locales/en.go +++ b/pkg/locales/en.go @@ -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,", diff --git a/pkg/locales/zh_hans.go b/pkg/locales/zh_hans.go index 050a4a40..2354dbb1 100644 --- a/pkg/locales/zh_hans.go +++ b/pkg/locales/zh_hans.go @@ -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 您好,", diff --git a/pkg/models/numeral.go b/pkg/models/numeral.go new file mode 100644 index 00000000..95a670fe --- /dev/null +++ b/pkg/models/numeral.go @@ -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)) + } +} diff --git a/pkg/models/user.go b/pkg/models/user.go index 6582c936..69b5fb85 100644 --- a/pkg/models/user.go +++ b/pkg/models/user.go @@ -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, } diff --git a/pkg/services/users.go b/pkg/services/users.go index 44105310..9b9541ca 100644 --- a/pkg/services/users.go +++ b/pkg/services/users.go @@ -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") diff --git a/src/components/desktop/AmountInput.vue b/src/components/desktop/AmountInput.vue index 342e4d32..969981d7 100644 --- a/src/components/desktop/AmountInput.vue +++ b/src/components/desktop/AmountInput.vue @@ -1,12 +1,12 @@