From 533c68ee09ff3b6a9e3fd426cfb0ffce3c56b946 Mon Sep 17 00:00:00 2001 From: Alf Sebastian Houge Date: Sun, 26 Feb 2023 13:44:58 +0100 Subject: [PATCH 1/4] Add db migration for supporting per user language setting --- server/db/migrations.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/server/db/migrations.go b/server/db/migrations.go index 598dd29..b9824f8 100644 --- a/server/db/migrations.go +++ b/server/db/migrations.go @@ -27,6 +27,10 @@ var migrations = []localMigration{ Name: "2022_03_08_13_16_AddVIN", Query: "ALTER TABLE vehicles ADD COLUMN vin text", }, + { + Name: "2023_02_26_13_42_AddLanguage", + Query: "ALTER TABLE users ADD COLUMN language text default 'English'", + }, } func RunMigrations() { From efa6aed8eb60ee2066adf9457e73b907ce9fbe61 Mon Sep 17 00:00:00 2001 From: Alf Sebastian Houge Date: Sun, 26 Feb 2023 13:45:17 +0100 Subject: [PATCH 2/4] Add language masters --- server/controllers/masters.go | 1 + server/models/language.go | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 server/models/language.go diff --git a/server/controllers/masters.go b/server/controllers/masters.go index 1813175..8c1f2e2 100644 --- a/server/controllers/masters.go +++ b/server/controllers/masters.go @@ -19,6 +19,7 @@ func RegisterAnonMasterConroller(router *gin.RouterGroup) { "distanceUnits": db.DistanceUnitDetails, "roles": db.RoleDetails, "currencies": models.GetCurrencyMasterList(), + "languages": models.GetLanguageMastersList(), }) }) } diff --git a/server/models/language.go b/server/models/language.go new file mode 100644 index 0000000..b373d01 --- /dev/null +++ b/server/models/language.go @@ -0,0 +1,21 @@ +package models + +type LanguageModel struct { + Emoji string `json:"emoji"` + Name string `json:"name"` + NameNative string `json:"nameNative"` +} + +func GetLanguageMastersList() []LanguageModel { + return []LanguageModel{ + { + Emoji: "🇬🇧", + Name: "English", + NameNative: "English", + }, { + Emoji: "🇩🇪", + Name: "German", + NameNative: "Deutsch", + }, + } +} \ No newline at end of file From 14968013dd5329fad1270da1ef23faf137842920 Mon Sep 17 00:00:00 2001 From: Alf Sebastian Houge Date: Sun, 26 Feb 2023 13:54:55 +0100 Subject: [PATCH 3/4] Write and read language setting from backend --- server/db/dbModels.go | 1 + server/db/migrations.go | 2 +- ui/src/router/views/settings.vue | 29 +++++++++++++++--- ui/src/state/modules/masters.js | 52 ++++++++++++++++++++++++++++++++ ui/src/state/modules/vehicles.js | 33 -------------------- 5 files changed, 79 insertions(+), 38 deletions(-) create mode 100644 ui/src/state/modules/masters.js diff --git a/server/db/dbModels.go b/server/db/dbModels.go index 71682bb..aec7665 100644 --- a/server/db/dbModels.go +++ b/server/db/dbModels.go @@ -19,6 +19,7 @@ type User struct { Name string `json:"name"` Vehicles []Vehicle `gorm:"many2many:user_vehicles;" json:"vehicles"` IsDisabled bool `json:"isDisabled"` + Language string `json:"language"` } func (b *User) MarshalJSON() ([]byte, error) { diff --git a/server/db/migrations.go b/server/db/migrations.go index b9824f8..b2f4112 100644 --- a/server/db/migrations.go +++ b/server/db/migrations.go @@ -29,7 +29,7 @@ var migrations = []localMigration{ }, { Name: "2023_02_26_13_42_AddLanguage", - Query: "ALTER TABLE users ADD COLUMN language text default 'English'", + Query: "ALTER TABLE users ADD COLUMN language text default 'English 🇬🇧'", }, } diff --git a/ui/src/router/views/settings.vue b/ui/src/router/views/settings.vue index ca4b326..768bace 100644 --- a/ui/src/router/views/settings.vue +++ b/ui/src/router/views/settings.vue @@ -22,6 +22,7 @@ export default { data: function() { return { settingsModel: { + language: this.me.language, currency: this.me.currency, distanceUnit: this.me.distanceUnit, dateFormat: this.me.dateFormat, @@ -36,7 +37,7 @@ export default { } }, computed: { - ...mapState('vehicles', ['currencyMasters', 'distanceUnitMasters']), + ...mapState('masters', ['currencyMasters', 'languageMasters', 'distanceUnitMasters']), passwordValid() { if (this.changePassModel.new === '' || this.changePassModel.renew === '') { return true @@ -58,6 +59,15 @@ export default { ) }) }, + filteredLanguageMasters() { + return this.languageMasters.filter((option) => { + return ( + option.nameNative + .toString() + .toLowerCase() + .indexOf(this.settingsModel.language.toLowerCase()) >= 0) + }) + }, }, methods: { changePassword() { @@ -126,6 +136,9 @@ export default { formatCurrency(option) { return `${option.namePlural} (${option.code})` }, + formatLanguage(option) { + return `${option.nameNative} ${option.emoji}` + }, }, } @@ -136,9 +149,17 @@ export default {
-

- {{ $t('settingdesc') }} -

+ + + { + commit('CACHE_LANGUAGE_MASTERS', response.data.languages) + commit('CACHE_FUEL_UNIT_MASTERS', response.data.fuelUnits) + commit('CACHE_FUEL_TYPE_MASTERS', response.data.fuelTypes) + commit('CACHE_CURRENCY_MASTERS', response.data.currencies) + commit('CACHE_DISTANCE_UNIT_MASTERS', response.data.distanceUnits) + commit('CACHE_ROLE_MASTERS', response.data.roles) + return response.data + }) + }, +} \ No newline at end of file diff --git a/ui/src/state/modules/vehicles.js b/ui/src/state/modules/vehicles.js index ba5fef8..173c00f 100644 --- a/ui/src/state/modules/vehicles.js +++ b/ui/src/state/modules/vehicles.js @@ -4,11 +4,6 @@ import { filter } from 'lodash' import parseISO from 'date-fns/parseISO' export const state = { vehicles: [], - roleMasters: [], - fuelUnitMasters: [], - distanceUnitMasters: [], - currencyMasters: [], - fuelTypeMasters: [], quickEntries: [], vehicleStats: new Map(), } @@ -29,24 +24,9 @@ export const mutations = { CACHE_VEHICLE_STATS(state, stats) { state.vehicleStats.set(stats.vehicleId, stats) }, - CACHE_FUEL_UNIT_MASTERS(state, masters) { - state.fuelUnitMasters = masters - }, - CACHE_DISTANCE_UNIT_MASTERS(state, masters) { - state.distanceUnitMasters = masters - }, - CACHE_FUEL_TYPE_MASTERS(state, masters) { - state.fuelTypeMasters = masters - }, - CACHE_CURRENCY_MASTERS(state, masters) { - state.currencyMasters = masters - }, CACHE_QUICK_ENTRIES(state, entries) { state.quickEntries = entries }, - CACHE_ROLE_MASTERS(state, roles) { - state.roleMasters = roles - }, } export const actions = { @@ -54,22 +34,9 @@ export const actions = { const { currentUser } = rootState.auth if (currentUser) { dispatch('fetchVehicles') - dispatch('fetchMasters') dispatch('fetchQuickEntries', { force: true }) } }, - fetchMasters({ commit, state, rootState }) { - return axios.get('/api/masters').then((response) => { - const fuelUnitMasters = response.data.fuelUnits - const fuelTypeMasters = response.data.fuelTypes - commit('CACHE_FUEL_UNIT_MASTERS', fuelUnitMasters) - commit('CACHE_FUEL_TYPE_MASTERS', fuelTypeMasters) - commit('CACHE_CURRENCY_MASTERS', response.data.currencies) - commit('CACHE_DISTANCE_UNIT_MASTERS', response.data.distanceUnits) - commit('CACHE_ROLE_MASTERS', response.data.roles) - return response.data - }) - }, fetchVehicles({ commit, state, rootState }) { return axios.get('/api/me/vehicles').then((response) => { const data = response.data From 302bdd2222391c1a077e925f13ddf8b67a95d261 Mon Sep 17 00:00:00 2001 From: Alf Sebastian Houge Date: Tue, 18 Jul 2023 22:48:36 +0200 Subject: [PATCH 4/4] Implement switching language (but doesn't persist) --- server/controllers/masters.go | 4 ++-- server/db/migrations.go | 2 +- server/models/language.go | 3 +++ server/models/misc.go | 1 + server/service/miscService.go | 19 ++++++++++++++++++- ui/src/router/views/settings.vue | 21 +++++++++------------ 6 files changed, 34 insertions(+), 16 deletions(-) diff --git a/server/controllers/masters.go b/server/controllers/masters.go index 8c1f2e2..835d85b 100644 --- a/server/controllers/masters.go +++ b/server/controllers/masters.go @@ -19,7 +19,7 @@ func RegisterAnonMasterConroller(router *gin.RouterGroup) { "distanceUnits": db.DistanceUnitDetails, "roles": db.RoleDetails, "currencies": models.GetCurrencyMasterList(), - "languages": models.GetLanguageMastersList(), + "languages": models.GetLanguageMastersList(), }) }) } @@ -53,7 +53,7 @@ func udpateSettings(c *gin.Context) { func udpateMySettings(c *gin.Context) { var model models.UpdateSettingModel if err := c.ShouldBind(&model); err == nil { - err := service.UpdateUserSettings(c.MustGet("userId").(string), model.Currency, *model.DistanceUnit, model.DateFormat) + err := service.UpdateUserSettings(c.MustGet("userId").(string), model.Currency, *model.DistanceUnit, model.DateFormat, model.Language) if err != nil { c.JSON(http.StatusUnprocessableEntity, common.NewError("udpateMySettings", err)) return diff --git a/server/db/migrations.go b/server/db/migrations.go index b2f4112..347648d 100644 --- a/server/db/migrations.go +++ b/server/db/migrations.go @@ -29,7 +29,7 @@ var migrations = []localMigration{ }, { Name: "2023_02_26_13_42_AddLanguage", - Query: "ALTER TABLE users ADD COLUMN language text default 'English 🇬🇧'", + Query: "ALTER TABLE users ADD COLUMN language text default 'en'", }, } diff --git a/server/models/language.go b/server/models/language.go index b373d01..c8e655f 100644 --- a/server/models/language.go +++ b/server/models/language.go @@ -4,6 +4,7 @@ type LanguageModel struct { Emoji string `json:"emoji"` Name string `json:"name"` NameNative string `json:"nameNative"` + Shorthand string `json:"shorthand"` } func GetLanguageMastersList() []LanguageModel { @@ -12,10 +13,12 @@ func GetLanguageMastersList() []LanguageModel { Emoji: "🇬🇧", Name: "English", NameNative: "English", + Shorthand: "en", }, { Emoji: "🇩🇪", Name: "German", NameNative: "Deutsch", + Shorthand: "de", }, } } \ No newline at end of file diff --git a/server/models/misc.go b/server/models/misc.go index 3171db2..5356617 100644 --- a/server/models/misc.go +++ b/server/models/misc.go @@ -6,6 +6,7 @@ type UpdateSettingModel struct { Currency string `json:"currency" form:"currency" query:"currency"` DateFormat string `json:"dateFormat" form:"dateFormat" query:"dateFormat"` DistanceUnit *db.DistanceUnit `json:"distanceUnit" form:"distanceUnit" query:"distanceUnit" ` + Language string `json:"language" form:"language" query:"language"` } type ClarksonMigrationModel struct { diff --git a/server/service/miscService.go b/server/service/miscService.go index ef344a3..3705878 100644 --- a/server/service/miscService.go +++ b/server/service/miscService.go @@ -1,7 +1,9 @@ package service import ( + "errors" "hammond/db" + "hammond/models" ) func CanInitializeSystem() (bool, error) { @@ -14,15 +16,30 @@ func UpdateSettings(currency string, distanceUnit db.DistanceUnit) error { setting.DistanceUnit = distanceUnit return db.UpdateSettings(setting) } -func UpdateUserSettings(userId, currency string, distanceUnit db.DistanceUnit, dateFormat string) error { +func UpdateUserSettings(userId, currency string, distanceUnit db.DistanceUnit, dateFormat string, language string) error { user, err := db.GetUserById(userId) if err != nil { return err } + // TODO: Pull into function + languageExists := false + languages := models.GetLanguageMastersList(); + for _, lang := range languages { + if (language == lang.Shorthand){ + languageExists = true + } + } + + if (!languageExists) { + return errors.New("Language not in masters list") + } + + user.Currency = currency user.DistanceUnit = distanceUnit user.DateFormat = dateFormat + user.Language = language return db.UpdateUser(user) } diff --git a/ui/src/router/views/settings.vue b/ui/src/router/views/settings.vue index 768bace..1c5c822 100644 --- a/ui/src/router/views/settings.vue +++ b/ui/src/router/views/settings.vue @@ -28,6 +28,7 @@ export default { dateFormat: this.me.dateFormat, }, tryingToSave: false, + selectedLanguage: "", changePassModel: { old: '', new: '', @@ -59,15 +60,9 @@ export default { ) }) }, - filteredLanguageMasters() { - return this.languageMasters.filter((option) => { - return ( - option.nameNative - .toString() - .toLowerCase() - .indexOf(this.settingsModel.language.toLowerCase()) >= 0) - }) - }, + }, + mounted() { + this.selectedLanguage = this.formatLanguage(this.languageMasters.filter(x => x.shorthand === this.me.language)[0]) }, methods: { changePassword() { @@ -120,6 +115,7 @@ export default { type: 'is-success', duration: 3000, }) + this.$i18n.locale = this.settingsModel.language }) .catch((ex) => { this.$buefy.toast.open({ @@ -151,13 +147,14 @@ export default {