Compare commits
4 Commits
master
...
feat/langu
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
302bdd2222 | ||
|
|
14968013dd | ||
|
|
efa6aed8eb | ||
|
|
533c68ee09 |
@@ -19,6 +19,7 @@ func RegisterAnonMasterConroller(router *gin.RouterGroup) {
|
|||||||
"distanceUnits": db.DistanceUnitDetails,
|
"distanceUnits": db.DistanceUnitDetails,
|
||||||
"roles": db.RoleDetails,
|
"roles": db.RoleDetails,
|
||||||
"currencies": models.GetCurrencyMasterList(),
|
"currencies": models.GetCurrencyMasterList(),
|
||||||
|
"languages": models.GetLanguageMastersList(),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -52,7 +53,7 @@ func udpateSettings(c *gin.Context) {
|
|||||||
func udpateMySettings(c *gin.Context) {
|
func udpateMySettings(c *gin.Context) {
|
||||||
var model models.UpdateSettingModel
|
var model models.UpdateSettingModel
|
||||||
if err := c.ShouldBind(&model); err == nil {
|
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 {
|
if err != nil {
|
||||||
c.JSON(http.StatusUnprocessableEntity, common.NewError("udpateMySettings", err))
|
c.JSON(http.StatusUnprocessableEntity, common.NewError("udpateMySettings", err))
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ type User struct {
|
|||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Vehicles []Vehicle `gorm:"many2many:user_vehicles;" json:"vehicles"`
|
Vehicles []Vehicle `gorm:"many2many:user_vehicles;" json:"vehicles"`
|
||||||
IsDisabled bool `json:"isDisabled"`
|
IsDisabled bool `json:"isDisabled"`
|
||||||
|
Language string `json:"language"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *User) MarshalJSON() ([]byte, error) {
|
func (b *User) MarshalJSON() ([]byte, error) {
|
||||||
|
|||||||
@@ -27,6 +27,10 @@ var migrations = []localMigration{
|
|||||||
Name: "2022_03_08_13_16_AddVIN",
|
Name: "2022_03_08_13_16_AddVIN",
|
||||||
Query: "ALTER TABLE vehicles ADD COLUMN vin text",
|
Query: "ALTER TABLE vehicles ADD COLUMN vin text",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "2023_02_26_13_42_AddLanguage",
|
||||||
|
Query: "ALTER TABLE users ADD COLUMN language text default 'en'",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func RunMigrations() {
|
func RunMigrations() {
|
||||||
|
|||||||
24
server/models/language.go
Normal file
24
server/models/language.go
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
type LanguageModel struct {
|
||||||
|
Emoji string `json:"emoji"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
NameNative string `json:"nameNative"`
|
||||||
|
Shorthand string `json:"shorthand"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetLanguageMastersList() []LanguageModel {
|
||||||
|
return []LanguageModel{
|
||||||
|
{
|
||||||
|
Emoji: "🇬🇧",
|
||||||
|
Name: "English",
|
||||||
|
NameNative: "English",
|
||||||
|
Shorthand: "en",
|
||||||
|
}, {
|
||||||
|
Emoji: "🇩🇪",
|
||||||
|
Name: "German",
|
||||||
|
NameNative: "Deutsch",
|
||||||
|
Shorthand: "de",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ type UpdateSettingModel struct {
|
|||||||
Currency string `json:"currency" form:"currency" query:"currency"`
|
Currency string `json:"currency" form:"currency" query:"currency"`
|
||||||
DateFormat string `json:"dateFormat" form:"dateFormat" query:"dateFormat"`
|
DateFormat string `json:"dateFormat" form:"dateFormat" query:"dateFormat"`
|
||||||
DistanceUnit *db.DistanceUnit `json:"distanceUnit" form:"distanceUnit" query:"distanceUnit" `
|
DistanceUnit *db.DistanceUnit `json:"distanceUnit" form:"distanceUnit" query:"distanceUnit" `
|
||||||
|
Language string `json:"language" form:"language" query:"language"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ClarksonMigrationModel struct {
|
type ClarksonMigrationModel struct {
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
package service
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"hammond/db"
|
"hammond/db"
|
||||||
|
"hammond/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
func CanInitializeSystem() (bool, error) {
|
func CanInitializeSystem() (bool, error) {
|
||||||
@@ -14,15 +16,30 @@ func UpdateSettings(currency string, distanceUnit db.DistanceUnit) error {
|
|||||||
setting.DistanceUnit = distanceUnit
|
setting.DistanceUnit = distanceUnit
|
||||||
return db.UpdateSettings(setting)
|
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)
|
user, err := db.GetUserById(userId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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.Currency = currency
|
||||||
user.DistanceUnit = distanceUnit
|
user.DistanceUnit = distanceUnit
|
||||||
user.DateFormat = dateFormat
|
user.DateFormat = dateFormat
|
||||||
|
user.Language = language
|
||||||
return db.UpdateUser(user)
|
return db.UpdateUser(user)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,11 +22,13 @@ export default {
|
|||||||
data: function() {
|
data: function() {
|
||||||
return {
|
return {
|
||||||
settingsModel: {
|
settingsModel: {
|
||||||
|
language: this.me.language,
|
||||||
currency: this.me.currency,
|
currency: this.me.currency,
|
||||||
distanceUnit: this.me.distanceUnit,
|
distanceUnit: this.me.distanceUnit,
|
||||||
dateFormat: this.me.dateFormat,
|
dateFormat: this.me.dateFormat,
|
||||||
},
|
},
|
||||||
tryingToSave: false,
|
tryingToSave: false,
|
||||||
|
selectedLanguage: "",
|
||||||
changePassModel: {
|
changePassModel: {
|
||||||
old: '',
|
old: '',
|
||||||
new: '',
|
new: '',
|
||||||
@@ -36,7 +38,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState('vehicles', ['currencyMasters', 'distanceUnitMasters']),
|
...mapState('masters', ['currencyMasters', 'languageMasters', 'distanceUnitMasters']),
|
||||||
passwordValid() {
|
passwordValid() {
|
||||||
if (this.changePassModel.new === '' || this.changePassModel.renew === '') {
|
if (this.changePassModel.new === '' || this.changePassModel.renew === '') {
|
||||||
return true
|
return true
|
||||||
@@ -59,6 +61,9 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
mounted() {
|
||||||
|
this.selectedLanguage = this.formatLanguage(this.languageMasters.filter(x => x.shorthand === this.me.language)[0])
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
changePassword() {
|
changePassword() {
|
||||||
if (!this.passwordValid) {
|
if (!this.passwordValid) {
|
||||||
@@ -110,6 +115,7 @@ export default {
|
|||||||
type: 'is-success',
|
type: 'is-success',
|
||||||
duration: 3000,
|
duration: 3000,
|
||||||
})
|
})
|
||||||
|
this.$i18n.locale = this.settingsModel.language
|
||||||
})
|
})
|
||||||
.catch((ex) => {
|
.catch((ex) => {
|
||||||
this.$buefy.toast.open({
|
this.$buefy.toast.open({
|
||||||
@@ -126,6 +132,9 @@ export default {
|
|||||||
formatCurrency(option) {
|
formatCurrency(option) {
|
||||||
return `${option.namePlural} (${option.code})`
|
return `${option.namePlural} (${option.code})`
|
||||||
},
|
},
|
||||||
|
formatLanguage(option) {
|
||||||
|
return `${option.nameNative} ${option.emoji}`
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -136,9 +145,18 @@ export default {
|
|||||||
<div class="columns"
|
<div class="columns"
|
||||||
><div class="column">
|
><div class="column">
|
||||||
<form class="box " @submit.prevent="saveSettings">
|
<form class="box " @submit.prevent="saveSettings">
|
||||||
<h1 class="subtitle">
|
<b-field :label="$t('language')">
|
||||||
{{ $t('settingdesc') }}
|
<b-autocomplete
|
||||||
</h1>
|
v-model="selectedLanguage"
|
||||||
|
:placeholder="$t('language')"
|
||||||
|
:keep-first="true"
|
||||||
|
:custom-formatter="formatLanguage"
|
||||||
|
:data="languageMasters"
|
||||||
|
:open-on-focus="true"
|
||||||
|
required
|
||||||
|
@select="(option) => (settingsModel.language = option.shorthand)"
|
||||||
|
/>
|
||||||
|
</b-field>
|
||||||
<b-field :label="$t('currency')">
|
<b-field :label="$t('currency')">
|
||||||
<b-autocomplete
|
<b-autocomplete
|
||||||
v-model="settingsModel.currency"
|
v-model="settingsModel.currency"
|
||||||
|
|||||||
52
ui/src/state/modules/masters.js
Normal file
52
ui/src/state/modules/masters.js
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
import axios from 'axios'
|
||||||
|
|
||||||
|
export const state = {
|
||||||
|
languageMasters: [],
|
||||||
|
fuelUnitMasters: [],
|
||||||
|
distanceUnitMasters: [],
|
||||||
|
currencyMasters: [],
|
||||||
|
fuelTypeMasters: [],
|
||||||
|
roleMasters: [],
|
||||||
|
}
|
||||||
|
export const mutations = {
|
||||||
|
CACHE_LANGUAGE_MASTERS(state, masters) {
|
||||||
|
state.languageMasters = masters
|
||||||
|
},
|
||||||
|
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_ROLE_MASTERS(state, roles) {
|
||||||
|
state.roleMasters = roles
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getters = {}
|
||||||
|
|
||||||
|
export const actions = {
|
||||||
|
init({ dispatch, rootState }) {
|
||||||
|
const { currentUser } = rootState.auth
|
||||||
|
if (currentUser) {
|
||||||
|
dispatch('fetchMasters')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fetchMasters({ commit, state, rootState }) {
|
||||||
|
return axios.get('/api/masters').then((response) => {
|
||||||
|
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
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
@@ -4,11 +4,6 @@ import { filter } from 'lodash'
|
|||||||
import parseISO from 'date-fns/parseISO'
|
import parseISO from 'date-fns/parseISO'
|
||||||
export const state = {
|
export const state = {
|
||||||
vehicles: [],
|
vehicles: [],
|
||||||
roleMasters: [],
|
|
||||||
fuelUnitMasters: [],
|
|
||||||
distanceUnitMasters: [],
|
|
||||||
currencyMasters: [],
|
|
||||||
fuelTypeMasters: [],
|
|
||||||
quickEntries: [],
|
quickEntries: [],
|
||||||
vehicleStats: new Map(),
|
vehicleStats: new Map(),
|
||||||
}
|
}
|
||||||
@@ -29,24 +24,9 @@ export const mutations = {
|
|||||||
CACHE_VEHICLE_STATS(state, stats) {
|
CACHE_VEHICLE_STATS(state, stats) {
|
||||||
state.vehicleStats.set(stats.vehicleId, 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) {
|
CACHE_QUICK_ENTRIES(state, entries) {
|
||||||
state.quickEntries = entries
|
state.quickEntries = entries
|
||||||
},
|
},
|
||||||
CACHE_ROLE_MASTERS(state, roles) {
|
|
||||||
state.roleMasters = roles
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const actions = {
|
export const actions = {
|
||||||
@@ -54,22 +34,9 @@ export const actions = {
|
|||||||
const { currentUser } = rootState.auth
|
const { currentUser } = rootState.auth
|
||||||
if (currentUser) {
|
if (currentUser) {
|
||||||
dispatch('fetchVehicles')
|
dispatch('fetchVehicles')
|
||||||
dispatch('fetchMasters')
|
|
||||||
dispatch('fetchQuickEntries', { force: true })
|
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 }) {
|
fetchVehicles({ commit, state, rootState }) {
|
||||||
return axios.get('/api/me/vehicles').then((response) => {
|
return axios.get('/api/me/vehicles').then((response) => {
|
||||||
const data = response.data
|
const data = response.data
|
||||||
|
|||||||
Reference in New Issue
Block a user