diff --git a/.eslintrc.js b/.eslintrc.cjs similarity index 100% rename from .eslintrc.js rename to .eslintrc.cjs diff --git a/package.json b/package.json index cdb185ba1..71d80d401 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "salix-front", - "version": "24.26.2", + "version": "24.30.1", "description": "Salix frontend", "productName": "Salix", "author": "Verdnatura", diff --git a/public/no-image-dark.png b/public/no-image-dark.png new file mode 100644 index 000000000..2a20d7eb4 Binary files /dev/null and b/public/no-image-dark.png differ diff --git a/public/no-image.png b/public/no-image.png new file mode 100644 index 000000000..11d5317a9 Binary files /dev/null and b/public/no-image.png differ diff --git a/public/no-user.png b/public/no-user.png new file mode 100644 index 000000000..e090bc2eb Binary files /dev/null and b/public/no-user.png differ diff --git a/src/boot/axios.js b/src/boot/axios.js index e3e7289af..fa8a08003 100644 --- a/src/boot/axios.js +++ b/src/boot/axios.js @@ -1,11 +1,10 @@ import axios from 'axios'; -import { Notify } from 'quasar'; import { useSession } from 'src/composables/useSession'; import { Router } from 'src/router'; -import { i18n } from './i18n'; +import useNotify from 'src/composables/useNotify.js'; const session = useSession(); -const { t } = i18n.global; +const { notify } = useNotify(); axios.defaults.baseURL = '/api/'; @@ -27,10 +26,7 @@ const onResponse = (response) => { const isSaveRequest = method === 'patch'; if (isSaveRequest) { - Notify.create({ - message: t('globals.dataSaved'), - type: 'positive', - }); + notify('globals.dataSaved', 'positive'); } return response; @@ -59,18 +55,15 @@ const onResponseError = (error) => { } if (session.isLoggedIn() && response?.status === 401) { - session.destroy(); + session.destroy(false); const hash = window.location.hash; const url = hash.slice(1); - Router.push({ path: url }); + Router.push(`/login?redirect=${url}`); } else if (!session.isLoggedIn()) { return Promise.reject(error); } - Notify.create({ - message: t(message), - type: 'negative', - }); + notify(message, 'negative'); return Promise.reject(error); }; diff --git a/src/boot/qformMixin.js b/src/boot/qformMixin.js index a809140b0..0bf1f9795 100644 --- a/src/boot/qformMixin.js +++ b/src/boot/qformMixin.js @@ -27,7 +27,6 @@ export default { this.$el.addEventListener('keyup', function (evt) { if (evt.key === 'Enter') { const input = evt.target; - console.log('input', input); if (input.type == 'textarea' && evt.shiftKey) { evt.preventDefault(); let { selectionStart, selectionEnd } = input; diff --git a/src/components/CrudModel.vue b/src/components/CrudModel.vue index fe15d2db1..a55bde6f2 100644 --- a/src/components/CrudModel.vue +++ b/src/components/CrudModel.vue @@ -67,6 +67,10 @@ const $props = defineProps({ default: '', description: 'It is used for redirect on click "save and continue"', }, + hasSubToolbar: { + type: Boolean, + default: true, + }, }); const isLoading = ref(false); @@ -75,6 +79,7 @@ const originalData = ref(); const vnPaginateRef = ref(); const formData = ref(); const saveButtonRef = ref(null); +const watchChanges = ref(); const formUrl = computed(() => $props.url); const emit = defineEmits(['onFetch', 'update:selected', 'saveChanges']); @@ -89,6 +94,7 @@ defineExpose({ saveChanges, getChanges, formData, + vnPaginateRef, }); async function fetch(data) { @@ -97,19 +103,26 @@ async function fetch(data) { data.map((d) => (d.$index = $index++)); } - originalData.value = data && JSON.parse(JSON.stringify(data)); - formData.value = data && JSON.parse(JSON.stringify(data)); - watch(formData, () => (hasChanges.value = true), { deep: true }); + resetData(data); emit('onFetch', data); return data; } +function resetData(data) { + if (!data) return; + originalData.value = JSON.parse(JSON.stringify(data)); + formData.value = JSON.parse(JSON.stringify(data)); + + if (watchChanges.value) watchChanges.value(); //destoy watcher + watchChanges.value = watch(formData, () => (hasChanges.value = true), { deep: true }); +} + async function reset() { await fetch(originalData.value); hasChanges.value = false; } -// eslint-disable-next-line vue/no-dupe-keys + function filter(value, update, filterOptions) { update( () => { @@ -135,7 +148,7 @@ async function onSubmit() { await saveChanges($props.saveFn ? formData.value : null); } -async function onSumbitAndGo() { +async function onSubmitAndGo() { await onSubmit(); push({ path: $props.goTo }); } @@ -271,8 +284,9 @@ function isEmpty(obj) { if (obj.length > 0) return false; } -async function reload() { - vnPaginateRef.value.fetch(); +async function reload(params) { + const data = await vnPaginateRef.value.fetch(params); + fetch(data); } watch(formUrl, async () => { @@ -284,10 +298,11 @@ watch(formUrl, async () => { - - + + { /> $props.model ?? `formModel_${route?.meta?.title ?? route.name}` -); + () => $props.model ?? `formModel_${route?.meta?.title ?? route.name}`, +).value; const componentIsRendered = ref(false); const arrayData = useArrayData(modelValue); const isLoading = ref(false); @@ -119,9 +123,10 @@ onMounted(async () => { // Podemos enviarle al form la estructura de data inicial sin necesidad de fetchearla state.set(modelValue, $props.formInitialData); - if ($props.autoLoad && !$props.formInitialData && $props.url) await fetch(); - else if (arrayData.store.data) updateAndEmit('onFetch', arrayData.store.data); - + if (!$props.formInitialData) { + if ($props.autoLoad && $props.url) await fetch(); + else if (arrayData.store.data) updateAndEmit('onFetch', arrayData.store.data); + } if ($props.observeFormChanges) { watch( () => formData.value, @@ -132,7 +137,7 @@ onMounted(async () => { JSON.stringify(newVal) !== JSON.stringify(originalData.value); isResetting.value = false; }, - { deep: true } + { deep: true }, ); } }); @@ -140,7 +145,7 @@ onMounted(async () => { if (!$props.url) watch( () => arrayData.store.data, - (val) => updateAndEmit('onFetch', val) + (val) => updateAndEmit('onFetch', val), ); watch(formUrl, async () => { @@ -200,11 +205,12 @@ async function save() { if ($props.urlCreate) notify('globals.dataCreated', 'positive'); updateAndEmit('onDataSaved', formData.value, response?.data); + if ($props.reload) await arrayData.fetch({}); + hasChanges.value = false; } catch (err) { console.error(err); notify('errors.writeRequest', 'negative'); } finally { - hasChanges.value = false; isLoading.value = false; } } @@ -233,7 +239,7 @@ function filter(value, update, filterOptions) { (ref) => { ref.setOptionIndex(-1); ref.moveOptionSelection(1, true); - } + }, ); } @@ -245,12 +251,18 @@ function updateAndEmit(evt, val, res) { emit(evt, state.get(modelValue), res); } -defineExpose({ save, isLoading, hasChanges }); +defineExpose({ + save, + isLoading, + hasChanges, + reset, + fetch, +});