4774-traducciones #853

Open
carlossa wants to merge 34 commits from 4774-traducciones into dev
14 changed files with 2649 additions and 10 deletions

View File

@ -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) => {

View File

@ -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>

1196
src/i18n/en/index.js Normal file

File diff suppressed because it is too large Load Diff

1198
src/i18n/es/index.js Normal file

File diff suppressed because it is too large Load Diff

View File

@ -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:

View File

@ -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:

View File

@ -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>

View File

@ -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 }} -

View File

@ -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;
Outdated
Review

tableRef.crudModel.resetData

tableRef.crudModel.resetData
}
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>

View File

@ -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,
]; ];

View File

@ -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: [],
},
};

View File

@ -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'),
},
], ],
}, },
], ],

View File

@ -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 = [

View File

@ -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();
});
});