4774-traducciones #853
|
@ -1,6 +1,6 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { computed, ref, useAttrs, watch } from 'vue';
|
import { computed, nextTick, ref, useAttrs, watch } from 'vue';
|
||||||
import { useRouter, onBeforeRouteLeave } from 'vue-router';
|
import { useRouter, onBeforeRouteLeave } from 'vue-router';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useQuasar } from 'quasar';
|
import { useQuasar } from 'quasar';
|
||||||
|
@ -98,6 +98,7 @@ defineExpose({
|
||||||
formData,
|
formData,
|
||||||
originalData,
|
originalData,
|
||||||
vnPaginateRef,
|
vnPaginateRef,
|
||||||
|
resetData,
|
||||||
});
|
});
|
||||||
|
|
||||||
onBeforeRouteLeave((to, from, next) => {
|
onBeforeRouteLeave((to, from, next) => {
|
||||||
|
|
|
@ -184,6 +184,12 @@ watch(
|
||||||
{ immediate: true },
|
{ immediate: true },
|
||||||
);
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => $props.create,
|
||||||
|
(value) => (createForm.value = value),
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
|
|
||||||
const isTableMode = computed(() => mode.value == TABLE_MODE);
|
const isTableMode = computed(() => mode.value == TABLE_MODE);
|
||||||
const showRightIcon = computed(() => $props.rightSearch || $props.rightSearchIcon);
|
const showRightIcon = computed(() => $props.rightSearch || $props.rightSearchIcon);
|
||||||
|
|
||||||
|
@ -474,6 +480,7 @@ function handleSelection({ evt, added, rows: selectedRows }, rows) {
|
||||||
<QBtn
|
<QBtn
|
||||||
v-for="(btn, index) of col.actions"
|
v-for="(btn, index) of col.actions"
|
||||||
v-show="btn.show ? btn.show(row) : true"
|
v-show="btn.show ? btn.show(row) : true"
|
||||||
|
v-bind="row.attrs"
|
||||||
:key="index"
|
:key="index"
|
||||||
:title="btn.title"
|
:title="btn.title"
|
||||||
:icon="btn.icon"
|
:icon="btn.icon"
|
||||||
|
@ -489,6 +496,7 @@ function handleSelection({ evt, added, rows: selectedRows }, rows) {
|
||||||
: 'hidden'
|
: 'hidden'
|
||||||
}`"
|
}`"
|
||||||
@click="btn.action(row)"
|
@click="btn.action(row)"
|
||||||
|
:disable="btn.disable ? btn.disable(row) : true"
|
||||||
/>
|
/>
|
||||||
</QTd>
|
</QTd>
|
||||||
</template>
|
</template>
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -329,6 +329,7 @@ globals:
|
||||||
medical: Mutual
|
medical: Mutual
|
||||||
pit: IRPF
|
pit: IRPF
|
||||||
wasteRecalc: Waste recaclulate
|
wasteRecalc: Waste recaclulate
|
||||||
|
translations: Translations
|
||||||
operator: Operator
|
operator: Operator
|
||||||
parking: Parking
|
parking: Parking
|
||||||
unsavedPopup:
|
unsavedPopup:
|
||||||
|
|
|
@ -329,6 +329,7 @@ globals:
|
||||||
medical: Mutua
|
medical: Mutua
|
||||||
pit: IRPF
|
pit: IRPF
|
||||||
wasteRecalc: Recalcular mermas
|
wasteRecalc: Recalcular mermas
|
||||||
|
translations: Traducciones
|
||||||
operator: Operario
|
operator: Operario
|
||||||
parking: Parking
|
parking: Parking
|
||||||
unsavedPopup:
|
unsavedPopup:
|
||||||
|
|
|
@ -108,6 +108,7 @@ function onBeforeSave(formData, originalData) {
|
||||||
:label="t('customer.extendedList.tableVisibleColumns.phone')"
|
:label="t('customer.extendedList.tableVisibleColumns.phone')"
|
||||||
:rules="validate('client.phone')"
|
:rules="validate('client.phone')"
|
||||||
clearable
|
clearable
|
||||||
|
type="number"
|
||||||
v-model="data.phone"
|
v-model="data.phone"
|
||||||
data-cy="customerPhone"
|
data-cy="customerPhone"
|
||||||
/>
|
/>
|
||||||
|
@ -115,6 +116,7 @@ function onBeforeSave(formData, originalData) {
|
||||||
:label="t('customer.summary.mobile')"
|
:label="t('customer.summary.mobile')"
|
||||||
:rules="validate('client.mobile')"
|
:rules="validate('client.mobile')"
|
||||||
clearable
|
clearable
|
||||||
|
type="number"
|
||||||
v-model="data.mobile"
|
v-model="data.mobile"
|
||||||
/>
|
/>
|
||||||
</VnRow>
|
</VnRow>
|
||||||
|
|
|
@ -149,7 +149,7 @@ function sendPdfInvoice({ address }) {
|
||||||
const createInvoiceInCorrection = async () => {
|
const createInvoiceInCorrection = async () => {
|
||||||
const { data: correctingId } = await axios.post(
|
const { data: correctingId } = await axios.post(
|
||||||
'InvoiceIns/corrective',
|
'InvoiceIns/corrective',
|
||||||
Object.assign(correctionFormData, { id: entityId.value })
|
Object.assign(correctionFormData, { id: entityId.value }),
|
||||||
);
|
);
|
||||||
push({ path: `/invoice-in/${correctingId}/summary` });
|
push({ path: `/invoice-in/${correctingId}/summary` });
|
||||||
};
|
};
|
||||||
|
@ -272,7 +272,6 @@ const createInvoiceInCorrection = async () => {
|
||||||
>
|
>
|
||||||
<template #option="{ itemProps, opt }">
|
<template #option="{ itemProps, opt }">
|
||||||
<QItem v-bind="itemProps">
|
<QItem v-bind="itemProps">
|
||||||
{{ console.log('opt: ', opt) }}
|
|
||||||
<QItemSection>
|
<QItemSection>
|
||||||
<QItemLabel
|
<QItemLabel
|
||||||
>{{ opt.id }} -
|
>{{ opt.id }} -
|
||||||
|
|
|
@ -0,0 +1,182 @@
|
||||||
|
<script setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { computed } from 'vue';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import VnTable from 'src/components/VnTable/VnTable.vue';
|
||||||
|
import VnSelect from 'src/components/common/VnSelect.vue';
|
||||||
|
import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
|
||||||
|
import FetchData from 'src/components/FetchData.vue';
|
||||||
|
import VnInput from 'src/components/common/VnInput.vue';
|
||||||
|
import { useArrayData } from 'src/composables/useArrayData';
|
||||||
|
import axios from 'axios';
|
||||||
|
useArrayData;
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
const columns = computed(() => [
|
||||||
|
{
|
||||||
|
align: 'left',
|
||||||
|
name: 'id',
|
||||||
|
label: t('id'),
|
||||||
|
visible: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
align: 'left',
|
||||||
|
name: primaryKey,
|
||||||
|
label: primaryKey,
|
||||||
|
create: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
align: 'left',
|
||||||
|
name: 'en',
|
||||||
|
label: t('defaultLang(en)'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
align: 'left',
|
||||||
|
name: lang,
|
||||||
|
label: lang,
|
||||||
|
component: 'input',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const tableRef = ref({});
|
||||||
|
const langs = ref([]);
|
||||||
|
const tables = ref([]);
|
||||||
|
const lang = ref('ca');
|
||||||
|
const table = ref();
|
||||||
|
const originalData = ref([]);
|
||||||
|
const selected = ref([]);
|
||||||
|
const PRIMARY_LANG = 'en';
|
||||||
|
|
||||||
|
const primaryKey = computed(() => table.value?.primaryKey);
|
||||||
|
const field = computed(() => table.value.field);
|
||||||
|
const url = computed(() => {
|
||||||
|
if (!table.value?.tableName) return;
|
||||||
|
const arrayData = useArrayData('translations');
|
||||||
|
if (arrayData) arrayData.reset(['skip', 'filter.skip', 'page']);
|
||||||
|
|
||||||
|
return table.value?.tableName + 's';
|
||||||
|
});
|
||||||
|
|
||||||
|
async function loadTable(data) {
|
||||||
|
if (data) originalData.value = data;
|
||||||
|
if (!lang.value) return;
|
||||||
|
const toFilter = JSON.parse(JSON.stringify(originalData.value));
|
||||||
|
if (!toFilter) return;
|
||||||
|
|
||||||
|
const filtered = [];
|
||||||
|
for (const row of toFilter) {
|
||||||
|
if (row.lang != PRIMARY_LANG) continue;
|
||||||
|
|
||||||
|
row.en = row[field.value];
|
||||||
|
const translation = originalData.value.find(
|
||||||
|
(o) => o.lang == lang.value && o[primaryKey.value] == row[primaryKey.value],
|
||||||
|
);
|
||||||
|
|
||||||
|
row[lang.value] = translation?.[field.value];
|
||||||
|
row.id = translation?.id;
|
||||||
|
filtered.push(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
tableRef.value.CrudModelRef.resetData(filtered);
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetOriginalData() {
|
||||||
|
originalData.value = null;
|
||||||
|
|||||||
|
}
|
||||||
|
|
||||||
|
async function save(data, changes) {
|
||||||
|
const { deletes } = data;
|
||||||
|
const { updates, creates } = changes();
|
||||||
|
|
||||||
|
for (const update of updates ?? []) {
|
||||||
|
update.data[field.value] = update.data[lang.value];
|
||||||
|
delete update.data[lang.value];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const create of creates ?? []) {
|
||||||
|
delete create['$index'];
|
||||||
|
delete create[PRIMARY_LANG];
|
||||||
|
create.lang = lang.value;
|
||||||
|
create[field.value] = create[lang.value];
|
||||||
|
delete create[lang.value];
|
||||||
|
}
|
||||||
|
|
||||||
|
await axios.post(url.value + '/crud', { updates, creates, deletes });
|
||||||
|
tableRef.value.reload();
|
||||||
|
tableRef.value.CrudModelRef.hasChanges = false;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<FetchData url="Languages" @on-fetch="(data) => (langs = data)" auto-load />
|
||||||
|
<FetchData
|
||||||
|
url="Applications/get-i18n-tables"
|
||||||
|
@on-fetch="(data) => (tables = data)"
|
||||||
|
auto-load
|
||||||
|
/>
|
||||||
|
<VnSubToolbar>
|
||||||
|
<template #st-data>
|
||||||
|
<VnSelect
|
||||||
|
:label="t('table')"
|
||||||
|
v-model="table"
|
||||||
|
:options="tables"
|
||||||
|
option-label="tableName"
|
||||||
|
option-value="tableName"
|
||||||
|
@update:model-value="resetOriginalData()"
|
||||||
|
:emit-value="false"
|
||||||
|
/>
|
||||||
|
<VnSelect
|
||||||
|
:label="t('lang')"
|
||||||
|
v-model="lang"
|
||||||
|
:options="langs"
|
||||||
|
option-label="code"
|
||||||
|
option-value="code"
|
||||||
|
@update:model-value="loadTable()"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</VnSubToolbar>
|
||||||
|
<VnTable
|
||||||
|
v-if="url"
|
||||||
|
ref="tableRef"
|
||||||
|
data-key="translations"
|
||||||
|
:url="url"
|
||||||
|
:limit="0"
|
||||||
|
:columns="columns"
|
||||||
|
:create="{
|
||||||
|
urlCreate: url,
|
||||||
|
title: 'Create translation',
|
||||||
|
onDataSaved: () => tableRef.reload(),
|
||||||
|
formInitialData: { lang: 'en' },
|
||||||
|
}"
|
||||||
|
:right-search="false"
|
||||||
|
@on-fetch="(data) => loadTable(data)"
|
||||||
|
:search-url="false"
|
||||||
|
:is-editable="true"
|
||||||
|
:table="{
|
||||||
|
'row-key': 'id',
|
||||||
|
selection: 'multiple',
|
||||||
|
}"
|
||||||
|
v-model:selected="selected"
|
||||||
|
:save-fn="save"
|
||||||
|
auto-load
|
||||||
|
>
|
||||||
|
<template #more-create-dialog="{ data }">
|
||||||
|
<VnInput v-model="data[field]" :label="field" />
|
||||||
|
</template>
|
||||||
|
</VnTable>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<i18n>
|
||||||
|
es:
|
||||||
|
primaryKey: Clave primaria
|
||||||
|
defaultLang(en): Idioma por defecto(Eng)
|
||||||
|
secondLang: Idioma secundario
|
||||||
|
table: Tabla
|
||||||
|
lang: Idioma
|
||||||
|
en:
|
||||||
|
primaryKey: Primary key
|
||||||
|
defaultLang(en): Default language(Eng)
|
||||||
|
secondLang: Second language
|
||||||
|
table: Table
|
||||||
|
lang: Language
|
||||||
|
</i18n>
|
|
@ -17,6 +17,7 @@ import Agency from './agency';
|
||||||
import Zone from './zone';
|
import Zone from './zone';
|
||||||
import Account from './account';
|
import Account from './account';
|
||||||
import Monitor from './monitor';
|
import Monitor from './monitor';
|
||||||
|
import TranslationsVn from './translationsVn.js';
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
Item,
|
Item,
|
||||||
|
@ -38,4 +39,5 @@ export default [
|
||||||
Zone,
|
Zone,
|
||||||
Account,
|
Account,
|
||||||
Monitor,
|
Monitor,
|
||||||
|
TranslationsVn,
|
||||||
];
|
];
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
import { RouterView } from 'vue-router';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
path: '/translations',
|
||||||
|
name: 'Translations',
|
||||||
|
meta: {
|
||||||
|
title: 'translations',
|
||||||
|
icon: 'history_edu',
|
||||||
|
moduleName: 'Translations',
|
||||||
|
},
|
||||||
|
component: RouterView,
|
||||||
|
menus: {
|
||||||
|
main: [],
|
||||||
|
card: [],
|
||||||
|
},
|
||||||
|
};
|
|
@ -6,7 +6,14 @@ const workerCard = {
|
||||||
component: () => import('src/pages/Worker/Card/WorkerCard.vue'),
|
component: () => import('src/pages/Worker/Card/WorkerCard.vue'),
|
||||||
redirect: { name: 'WorkerSummary' },
|
redirect: { name: 'WorkerSummary' },
|
||||||
meta: {
|
meta: {
|
||||||
menu: [
|
title: 'workers',
|
||||||
|
icon: 'vn:worker',
|
||||||
|
moduleName: 'Worker',
|
||||||
|
keyBinding: 'w',
|
||||||
|
},
|
||||||
|
menus: {
|
||||||
|
main: ['WorkerList', 'WorkerDepartment', 'TranslationsVn'],
|
||||||
|
card: [
|
||||||
'WorkerBasicData',
|
'WorkerBasicData',
|
||||||
'WorkerNotes',
|
'WorkerNotes',
|
||||||
'WorkerPda',
|
'WorkerPda',
|
||||||
|
@ -226,7 +233,7 @@ export default {
|
||||||
icon: 'vn:worker',
|
icon: 'vn:worker',
|
||||||
moduleName: 'Worker',
|
moduleName: 'Worker',
|
||||||
keyBinding: 'w',
|
keyBinding: 'w',
|
||||||
menu: ['WorkerList', 'WorkerDepartment'],
|
menu: ['WorkerList', 'WorkerDepartment', 'TranslationsVn'],
|
||||||
},
|
},
|
||||||
component: RouterView,
|
component: RouterView,
|
||||||
redirect: { name: 'WorkerMain' },
|
redirect: { name: 'WorkerMain' },
|
||||||
|
@ -268,6 +275,15 @@ export default {
|
||||||
departmentCard,
|
departmentCard,
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'translations',
|
||||||
|
name: 'TranslationsVn',
|
||||||
|
meta: {
|
||||||
|
title: 'translations',
|
||||||
|
icon: 'history_edu',
|
||||||
|
},
|
||||||
|
component: () => import('src/pages/Worker/TranslationsVn.vue'),
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
@ -15,7 +15,7 @@ import entry from 'src/router/modules/entry';
|
||||||
import roadmap from 'src/router/modules/roadmap';
|
import roadmap from 'src/router/modules/roadmap';
|
||||||
import agency from 'src/router/modules/agency';
|
import agency from 'src/router/modules/agency';
|
||||||
import zone from 'src/router/modules/zone';
|
import zone from 'src/router/modules/zone';
|
||||||
import account from './modules/account';
|
import account from 'src/router/modules/account';
|
||||||
import monitor from 'src/router/modules/monitor';
|
import monitor from 'src/router/modules/monitor';
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
describe('Translations', () => {
|
||||||
|
const tableType = 'itemTypeI18n';
|
||||||
|
const translationSelect = '[data-cy="Table_select"]';
|
||||||
|
const firstRow = '.q-virtual-scroll__content > :nth-child(1) > :nth-child(4)';
|
||||||
|
beforeEach(() => {
|
||||||
|
cy.viewport(1280, 720);
|
||||||
|
cy.login('buyer');
|
||||||
|
cy.visit(`/#/worker/translations`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should load translations and modify', () => {
|
||||||
|
cy.get('[data-cy="Table_select"]').click();
|
||||||
|
cy.selectOption(translationSelect, tableType);
|
||||||
|
cy.get(firstRow).type('test');
|
||||||
|
cy.saveCard();
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue
tableRef.crudModel.resetData