diff --git a/package.json b/package.json index 39d49519b..b5e62af11 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "salix-front", - "version": "24.52.0", + "version": "25.02.0", "description": "Salix frontend", "productName": "Salix", "author": "Verdnatura", diff --git a/src/boot/axios.js b/src/boot/axios.js index aee38e887..3f9fadee5 100644 --- a/src/boot/axios.js +++ b/src/boot/axios.js @@ -3,12 +3,12 @@ import { useSession } from 'src/composables/useSession'; import { Router } from 'src/router'; import useNotify from 'src/composables/useNotify.js'; import { useStateQueryStore } from 'src/stores/useStateQueryStore'; +import { i18n } from 'src/boot/i18n'; const session = useSession(); const { notify } = useNotify(); const stateQuery = useStateQueryStore(); const baseUrl = '/api/'; - axios.defaults.baseURL = baseUrl; const axiosNoError = axios.create({ baseURL: baseUrl }); @@ -16,6 +16,7 @@ const onRequest = (config) => { const token = session.getToken(); if (token.length && !config.headers.Authorization) { config.headers.Authorization = token; + config.headers['Accept-Language'] = i18n.global.locale.value; } stateQuery.add(config); return config; diff --git a/src/boot/i18n.js b/src/boot/i18n.js index b23b6d5fd..85d0772a3 100644 --- a/src/boot/i18n.js +++ b/src/boot/i18n.js @@ -1,9 +1,11 @@ import { boot } from 'quasar/wrappers'; import { createI18n } from 'vue-i18n'; import messages from 'src/i18n'; +import { useState } from 'src/composables/useState'; +const user = useState().getUser(); const i18n = createI18n({ - locale: navigator.language || navigator.userLanguage, + locale: user.value.lang || navigator.language || navigator.userLanguage, fallbackLocale: 'en', globalInjection: true, messages, diff --git a/src/components/UserPanel.vue b/src/components/UserPanel.vue index 810f63044..a0ef73a1f 100644 --- a/src/components/UserPanel.vue +++ b/src/components/UserPanel.vue @@ -87,10 +87,10 @@ async function saveDarkMode(value) { async function saveLanguage(value) { const query = `/VnUsers/${user.value.id}`; try { - await axios.patch(query, { - lang: value, - }); + await axios.patch(query, { lang: value }); + user.value.lang = value; + useState().setUser(user.value); onDataSaved(); } catch (error) { onDataError(); diff --git a/src/components/common/VnInputNumber.vue b/src/components/common/VnInputNumber.vue index 1cad6c245..165cfae3d 100644 --- a/src/components/common/VnInputNumber.vue +++ b/src/components/common/VnInputNumber.vue @@ -1,13 +1,28 @@ - diff --git a/src/components/common/VnSelect.vue b/src/components/common/VnSelect.vue index e5ac05231..758fb9228 100644 --- a/src/components/common/VnSelect.vue +++ b/src/components/common/VnSelect.vue @@ -4,6 +4,7 @@ import { useI18n } from 'vue-i18n'; import { useArrayData } from 'src/composables/useArrayData'; import { useRequired } from 'src/composables/useRequired'; import dataByOrder from 'src/utils/dataByOrder'; +import { QItemLabel } from 'quasar'; const emit = defineEmits(['update:modelValue', 'update:options', 'remove']); const $attrs = useAttrs(); @@ -33,6 +34,10 @@ const $props = defineProps({ type: String, default: 'id', }, + optionCaption: { + type: String, + default: null, + }, optionFilter: { type: String, default: null, @@ -101,6 +106,10 @@ const $props = defineProps({ type: String, default: null, }, + isOutlined: { + type: Boolean, + default: false, + }, }); const mixinRules = [requiredFieldRule, ...($attrs.rules ?? [])]; @@ -115,6 +124,15 @@ const noOneOpt = ref({ [optionValue.value]: false, [optionLabel.value]: noOneText, }); +const styleAttrs = computed(() => { + return $props.isOutlined + ? { + dense: true, + outlined: true, + rounded: true, + } + : {}; +}); const isLoading = ref(false); const useURL = computed(() => $props.url); const value = computed({ @@ -288,7 +306,7 @@ function handleKeyDown(event) { } const focusableElements = document.querySelectorAll( - 'a, button, input, textarea, select, details, [tabindex]:not([tabindex="-1"])' + 'a:not([disabled]), button:not([disabled]), input:not([disabled]), textarea:not([disabled]), select:not([disabled]), details:not([disabled]), [tabindex]:not([tabindex="-1"]):not([disabled])' ); const currentIndex = Array.prototype.indexOf.call( focusableElements, @@ -307,9 +325,8 @@ function handleKeyDown(event) { :options="myOptions" :option-label="optionLabel" :option-value="optionValue" - v-bind="$attrs" + v-bind="{ ...$attrs, ...styleAttrs }" @filter="filterHandler" - @keydown="handleKeyDown" :emit-value="nullishToTrue($attrs['emit-value'])" :map-options="nullishToTrue($attrs['map-options'])" :use-input="nullishToTrue($attrs['use-input'])" @@ -324,13 +341,15 @@ function handleKeyDown(event) { :input-debounce="useURL ? '300' : '0'" :loading="isLoading" @virtual-scroll="onScroll" + @keydown="handleKeyDown" :data-cy="$attrs.dataCy ?? $attrs.label + '_select'" + :data-url="url" > + diff --git a/src/components/ui/VnConfirm.vue b/src/components/ui/VnConfirm.vue index 0b1913383..a02b56bdb 100644 --- a/src/components/ui/VnConfirm.vue +++ b/src/components/ui/VnConfirm.vue @@ -98,6 +98,7 @@ function cancel() { /> { + const param = label.split('.').at(-1); + const globalLocale = `globals.params.${param}`; + if (te(globalLocale)) return t(globalLocale); + else if (te(t(`params.${param}`))); + else return t(`${route.meta.moduleName}.params.${param}`); +};