Merge branch '8045-FixIconDescriptorRedirect' of https://gitea.verdnatura.es/verdnatura/salix-front into 8045-FixIconDescriptorRedirect
gitea/salix-front/pipeline/pr-dev There was a failure building this commit Details

This commit is contained in:
Jon Elias 2025-03-03 08:26:04 +01:00
commit d9a05b5682
22 changed files with 306 additions and 56 deletions

1
Jenkinsfile vendored
View File

@ -113,6 +113,7 @@ pipeline {
} }
steps { steps {
script { script {
sh 'rm junit/e2e-*.xml || true'
env.COMPOSE_TAG = PROTECTED_BRANCH.contains(env.CHANGE_TARGET) ? env.CHANGE_TARGET : 'dev' env.COMPOSE_TAG = PROTECTED_BRANCH.contains(env.CHANGE_TARGET) ? env.CHANGE_TARGET : 'dev'
def image = docker.build('lilium-dev', '-f docs/Dockerfile.dev docs') def image = docker.build('lilium-dev', '-f docs/Dockerfile.dev docs')
sh "docker-compose ${env.COMPOSE_PARAMS} up -d" sh "docker-compose ${env.COMPOSE_PARAMS} up -d"

View File

@ -96,6 +96,10 @@ const $props = defineProps({
type: [String, Boolean], type: [String, Boolean],
default: '800px', default: '800px',
}, },
onDataSaved: {
type: Function,
default: () => {},
},
}); });
const emit = defineEmits(['onFetch', 'onDataSaved']); const emit = defineEmits(['onFetch', 'onDataSaved']);
const modelValue = computed( const modelValue = computed(

View File

@ -134,6 +134,10 @@ const $props = defineProps({
createComplement: { createComplement: {
type: Object, type: Object,
}, },
dataCy: {
type: String,
default: 'vn-table',
},
}); });
const { t } = useI18n(); const { t } = useI18n();
@ -249,7 +253,9 @@ function splitColumns(columns) {
col.columnFilter = { inWhere: true, ...col.columnFilter }; col.columnFilter = { inWhere: true, ...col.columnFilter };
splittedColumns.value.columns.push(col); splittedColumns.value.columns.push(col);
} }
// Status column
splittedColumns.value.create = createOrderSort(splittedColumns.value.create);
if (splittedColumns.value.chips.length) { if (splittedColumns.value.chips.length) {
splittedColumns.value.columnChips = splittedColumns.value.chips.filter( splittedColumns.value.columnChips = splittedColumns.value.chips.filter(
(c) => !c.isId, (c) => !c.isId,
@ -265,6 +271,24 @@ function splitColumns(columns) {
} }
} }
function createOrderSort(columns) {
const orderedColumn = columns
.map((column, index) =>
column.createOrder !== undefined ? { ...column, originalIndex: index } : null,
)
.filter((item) => item !== null);
orderedColumn.sort((a, b) => a.createOrder - b.createOrder);
const filteredColumns = columns.filter((col) => col.createOrder === undefined);
orderedColumn.forEach((col) => {
filteredColumns.splice(col.createOrder, 0, col);
});
return filteredColumns;
}
const rowClickFunction = computed(() => { const rowClickFunction = computed(() => {
if ($props.rowClick != undefined) return $props.rowClick; if ($props.rowClick != undefined) return $props.rowClick;
if ($props.redirect) return ({ id }) => redirectFn(id); if ($props.redirect) return ({ id }) => redirectFn(id);
@ -340,12 +364,11 @@ function hasEditableFormat(column) {
const clickHandler = async (event) => { const clickHandler = async (event) => {
const clickedElement = event.target.closest('td'); const clickedElement = event.target.closest('td');
const isDateElement = event.target.closest('.q-date'); const isDateElement = event.target.closest('.q-date');
const isTimeElement = event.target.closest('.q-time'); const isTimeElement = event.target.closest('.q-time');
const isQselectDropDown = event.target.closest('.q-select__dropdown-icon'); const isQSelectDropDown = event.target.closest('.q-select__dropdown-icon');
if (isDateElement || isTimeElement || isQselectDropDown) return; if (isDateElement || isTimeElement || isQSelectDropDown) return;
if (clickedElement === null) { if (clickedElement === null) {
await destroyInput(editingRow.value, editingField.value); await destroyInput(editingRow.value, editingField.value);
@ -584,9 +607,24 @@ function removeTextValue(data, getChanges) {
return data; return data;
} }
function handleRowClick(event, row) {
if (event.ctrlKey) return rowCtrlClickFunction.value(event, row);
if (rowClickFunction.value) rowClickFunction.value(row);
}
const rowCtrlClickFunction = computed(() => {
if ($props.rowCtrlClick != undefined) return $props.rowCtrlClick;
if ($props.redirect)
return (evt, { id }) => {
stopEventPropagation(evt);
window.open(`/#/${$props.redirect}/${id}`, '_blank');
};
return () => {};
});
</script> </script>
<template> <template>
<RightMenu v-if="$props.rightSearch"> <RightMenu v-if="$props.rightSearch" :overlay="overlay">
<template #right-panel> <template #right-panel>
<VnTableFilter <VnTableFilter
:data-key="$attrs['data-key']" :data-key="$attrs['data-key']"
@ -639,7 +677,7 @@ function removeTextValue(data, getChanges) {
:style="isTableMode && `max-height: ${tableHeight}`" :style="isTableMode && `max-height: ${tableHeight}`"
:virtual-scroll="isTableMode" :virtual-scroll="isTableMode"
@virtual-scroll="handleScroll" @virtual-scroll="handleScroll"
@row-click="(_, row) => rowClickFunction && rowClickFunction(row)" @row-click="(event, row) => handleRowClick(event, row)"
@update:selected="emit('update:selected', $event)" @update:selected="emit('update:selected', $event)"
@selection="(details) => handleSelection(details, rows)" @selection="(details) => handleSelection(details, rows)"
:hide-selected-banner="true" :hide-selected-banner="true"
@ -986,7 +1024,10 @@ function removeTextValue(data, getChanges) {
> >
<template #form-inputs="{ data }"> <template #form-inputs="{ data }">
<div :style="createComplement?.containerStyle"> <div :style="createComplement?.containerStyle">
<div> <div
:style="createComplement?.previousStyle"
v-if="!quasar.screen.xs"
>
<slot name="previous-create-dialog" :data="data" /> <slot name="previous-create-dialog" :data="data" />
</div> </div>
<div class="grid-create" :style="createComplement?.columnGridStyle"> <div class="grid-create" :style="createComplement?.columnGridStyle">
@ -999,7 +1040,10 @@ function removeTextValue(data, getChanges) {
:label="column.label" :label="column.label"
> >
<VnColumn <VnColumn
:column="column" :column="{
...column,
...{ disable: column?.createDisable ?? false },
}"
:row="{}" :row="{}"
default="input" default="input"
v-model="data[column.name]" v-model="data[column.name]"

View File

@ -11,6 +11,13 @@ const stateStore = useStateStore();
const slots = useSlots(); const slots = useSlots();
const hasContent = useHasContent('#right-panel'); const hasContent = useHasContent('#right-panel');
defineProps({
overlay: {
type: Boolean,
default: false,
},
});
onMounted(() => { onMounted(() => {
if ((!slots['right-panel'] && !hasContent.value) || quasar.platform.is.mobile) if ((!slots['right-panel'] && !hasContent.value) || quasar.platform.is.mobile)
stateStore.rightDrawer = false; stateStore.rightDrawer = false;
@ -34,7 +41,12 @@ onMounted(() => {
</QBtn> </QBtn>
</div> </div>
</Teleport> </Teleport>
<QDrawer v-model="stateStore.rightDrawer" side="right" :width="256"> <QDrawer
v-model="stateStore.rightDrawer"
side="right"
:width="256"
:overlay="overlay"
>
<QScrollArea class="fit"> <QScrollArea class="fit">
<div id="right-panel"></div> <div id="right-panel"></div>
<slot v-if="!hasContent" name="right-panel" /> <slot v-if="!hasContent" name="right-panel" />

View File

@ -27,7 +27,7 @@ const checkboxModel = computed({
</script> </script>
<template> <template>
<div> <div>
<QCheckbox v-bind="$attrs" v-on="$attrs" v-model="checkboxModel" /> <QCheckbox v-bind="$attrs" v-model="checkboxModel" />
<QIcon <QIcon
v-if="info" v-if="info"
v-bind="$attrs" v-bind="$attrs"

View File

@ -302,8 +302,6 @@ defineExpose({ opts: myOptions, vnSelectRef });
function handleKeyDown(event) { function handleKeyDown(event) {
if (event.key === 'Tab' && !event.shiftKey) { if (event.key === 'Tab' && !event.shiftKey) {
event.preventDefault();
const inputValue = vnSelectRef.value?.inputValue; const inputValue = vnSelectRef.value?.inputValue;
if (inputValue) { if (inputValue) {

View File

@ -29,7 +29,6 @@ export async function checkEntryLock(entryFk, userFk) {
.dialog({ .dialog({
component: VnConfirm, component: VnConfirm,
componentProps: { componentProps: {
'data-cy': 'entry-lock-confirm',
title: t('entry.lock.title'), title: t('entry.lock.title'),
message: t('entry.lock.message', { message: t('entry.lock.message', {
userName: data?.user?.nickname, userName: data?.user?.nickname,

View File

@ -694,8 +694,10 @@ worker:
machine: Machine machine: Machine
business: business:
tableVisibleColumns: tableVisibleColumns:
id: ID
started: Start Date started: Start Date
ended: End Date ended: End Date
hourlyLabor: Time sheet
company: Company company: Company
reasonEnd: Reason for Termination reasonEnd: Reason for Termination
department: Department department: Department
@ -703,6 +705,7 @@ worker:
calendarType: Work Calendar calendarType: Work Calendar
workCenter: Work Center workCenter: Work Center
payrollCategories: Contract Category payrollCategories: Contract Category
workerBusinessAgreementName: Agreement
occupationCode: Contribution Code occupationCode: Contribution Code
rate: Rate rate: Rate
businessType: Contract Type businessType: Contract Type

View File

@ -770,8 +770,10 @@ worker:
concept: Concepto concept: Concepto
business: business:
tableVisibleColumns: tableVisibleColumns:
id: Id
started: Fecha inicio started: Fecha inicio
ended: Fecha fin ended: Fecha fin
hourlyLabor: Ficha
company: Empresa company: Empresa
reasonEnd: Motivo finalización reasonEnd: Motivo finalización
department: Departamento department: Departamento
@ -782,6 +784,7 @@ worker:
occupationCode: Cotización occupationCode: Cotización
rate: Tarifa rate: Tarifa
businessType: Contrato businessType: Contrato
workerBusinessAgreementName: Convenio
amount: Salario amount: Salario
basicSalary: Salario transportistas basicSalary: Salario transportistas
notes: Notas notes: Notas

View File

@ -54,6 +54,7 @@ const columns = [
toggleIndeterminate: false, toggleIndeterminate: false,
}, },
create: true, create: true,
createOrder: 12,
width: '25px', width: '25px',
}, },
{ {
@ -87,15 +88,6 @@ const columns = [
isEditable: false, isEditable: false,
columnFilter: false, columnFilter: false,
}, },
{
name: 'entryFk',
isId: true,
visible: false,
isEditable: false,
disable: true,
create: true,
columnFilter: false,
},
{ {
align: 'center', align: 'center',
label: 'Id', label: 'Id',
@ -137,6 +129,7 @@ const columns = [
name: 'itemFk', name: 'itemFk',
visible: false, visible: false,
create: true, create: true,
createOrder: 0,
columnFilter: false, columnFilter: false,
}, },
{ {
@ -160,6 +153,8 @@ const columns = [
name: 'stickers', name: 'stickers',
component: 'input', component: 'input',
create: true, create: true,
createOrder: 1,
attrs: { attrs: {
positive: false, positive: false,
}, },
@ -271,6 +266,7 @@ const columns = [
}, },
width: '45px', width: '45px',
create: true, create: true,
createOrder: 3,
style: getQuantityStyle, style: getQuantityStyle,
}, },
{ {
@ -280,6 +276,7 @@ const columns = [
toolTip: t('Buying value'), toolTip: t('Buying value'),
name: 'buyingValue', name: 'buyingValue',
create: true, create: true,
createOrder: 2,
component: 'number', component: 'number',
attrs: { attrs: {
positive: false, positive: false,
@ -312,6 +309,7 @@ const columns = [
toolTip: t('Package'), toolTip: t('Package'),
name: 'price2', name: 'price2',
component: 'number', component: 'number',
createDisable: true,
width: '35px', width: '35px',
create: true, create: true,
format: (row) => parseFloat(row['price2']).toFixed(2), format: (row) => parseFloat(row['price2']).toFixed(2),
@ -321,6 +319,7 @@ const columns = [
label: t('Box'), label: t('Box'),
name: 'price3', name: 'price3',
component: 'number', component: 'number',
createDisable: true,
cellEvent: { cellEvent: {
'update:modelValue': async (value, oldValue, row) => { 'update:modelValue': async (value, oldValue, row) => {
row['price2'] = row['price2'] * (value / oldValue); row['price2'] = row['price2'] * (value / oldValue);
@ -508,13 +507,14 @@ async function setBuyUltimate(itemFk, data) {
}, },
}); });
const buyUltimateData = buyUltimate.data[0]; const buyUltimateData = buyUltimate.data[0];
if (!buyUltimateData) return;
const allowedKeys = columns const allowedKeys = columns
.filter((col) => col.create === true) .filter((col) => col.create === true)
.map((col) => col.name); .map((col) => col.name);
allowedKeys.forEach((key) => { allowedKeys.forEach((key) => {
if (buyUltimateData.hasOwnProperty(key) && key !== 'entryFk') { if (buyUltimateData?.hasOwnProperty(key) && key !== 'entryFk') {
if (!['stickers', 'quantity'].includes(key)) data[key] = buyUltimateData[key]; if (!['stickers', 'quantity'].includes(key)) data[key] = buyUltimateData[key];
} }
}); });
@ -607,6 +607,7 @@ onMounted(() => {
ref="entryBuysRef" ref="entryBuysRef"
data-key="EntryBuys" data-key="EntryBuys"
:url="`Entries/${entityId}/getBuyList`" :url="`Entries/${entityId}/getBuyList`"
search-url="EntryBuys"
save-url="Buys/crud" save-url="Buys/crud"
:disable-option="{ card: true }" :disable-option="{ card: true }"
v-model:selected="selectedRows" v-model:selected="selectedRows"
@ -636,16 +637,19 @@ onMounted(() => {
isFullWidth: true, isFullWidth: true,
containerStyle: { containerStyle: {
display: 'flex', display: 'flex',
'flex-wrap': 'wrap',
gap: '16px', gap: '16px',
position: 'relative', position: 'relative',
height: '500px',
}, },
columnGridStyle: { columnGridStyle: {
'max-width': '50%', 'max-width': '50%',
flex: 1,
'margin-right': '30px', 'margin-right': '30px',
flex: 1,
}, },
previousStyle: {
'max-width': '30%',
height: '500px',
},
displayPrevious: true,
}" }"
:is-editable="editableMode" :is-editable="editableMode"
:without-header="!editableMode" :without-header="!editableMode"
@ -660,6 +664,7 @@ onMounted(() => {
auto-load auto-load
footer footer
data-cy="entry-buys" data-cy="entry-buys"
overlay
> >
<template #column-hex="{ row }"> <template #column-hex="{ row }">
<VnColor :colors="row?.hexJson" style="height: 100%; min-width: 2000px" /> <VnColor :colors="row?.hexJson" style="height: 100%; min-width: 2000px" />

View File

@ -11,6 +11,8 @@ import VnTable from 'components/VnTable/VnTable.vue';
import SupplierDescriptorProxy from 'src/pages/Supplier/Card/SupplierDescriptorProxy.vue'; import SupplierDescriptorProxy from 'src/pages/Supplier/Card/SupplierDescriptorProxy.vue';
import VnSelectTravelExtended from 'src/components/common/VnSelectTravelExtended.vue'; import VnSelectTravelExtended from 'src/components/common/VnSelectTravelExtended.vue';
import { toDate } from 'src/filters'; import { toDate } from 'src/filters';
import { useSummaryDialog } from 'src/composables/useSummaryDialog';
import EntrySummary from './Card/EntrySummary.vue';
const { t } = useI18n(); const { t } = useI18n();
const tableRef = ref(); const tableRef = ref();
@ -18,6 +20,7 @@ const defaultEntry = ref({});
const state = useState(); const state = useState();
const user = state.getUser(); const user = state.getUser();
const dataKey = 'EntryList'; const dataKey = 'EntryList';
const { viewSummary } = useSummaryDialog();
const entryQueryFilter = { const entryQueryFilter = {
include: [ include: [
@ -222,6 +225,19 @@ const columns = computed(() => [
visible: false, visible: false,
create: true, create: true,
}, },
{
align: 'right',
label: '',
name: 'tableActions',
actions: [
{
title: t('components.smartCard.viewSummary'),
icon: 'preview',
isPrimary: true,
action: (row) => viewSummary(row.id, EntrySummary, 'xlg-width'),
},
],
},
]); ]);
function getBadgeAttrs(row) { function getBadgeAttrs(row) {
const date = row.landed; const date = row.landed;
@ -267,16 +283,7 @@ onBeforeMount(async () => {
</script> </script>
<template> <template>
<VnSection <VnSection :data-key="dataKey" prefix="entry">
:data-key="dataKey"
prefix="entry"
url="Entries/filter"
:array-data-props="{
url: 'Entries/filter',
order: 'landed DESC',
userFilter: entryQueryFilter,
}"
>
<template #advanced-menu> <template #advanced-menu>
<EntryFilter :data-key="dataKey" /> <EntryFilter :data-key="dataKey" />
</template> </template>
@ -285,6 +292,7 @@ onBeforeMount(async () => {
v-if="defaultEntry.defaultSupplierFk" v-if="defaultEntry.defaultSupplierFk"
ref="tableRef" ref="tableRef"
:data-key="dataKey" :data-key="dataKey"
search-url="EntryList"
url="Entries/filter" url="Entries/filter"
:filter="entryQueryFilter" :filter="entryQueryFilter"
order="landed DESC" order="landed DESC"

View File

@ -95,7 +95,7 @@ const columns = computed(() => [
}, },
}, },
], ],
'data-cy': 'table-actions', dataCy: 'table-actions',
}, },
]); ]);

View File

@ -185,6 +185,7 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
data-key="InvoiceInSummary" data-key="InvoiceInSummary"
:url="`InvoiceIns/${entityId}/summary`" :url="`InvoiceIns/${entityId}/summary`"
@on-fetch="(data) => init(data)" @on-fetch="(data) => init(data)"
module-name="InvoiceIn"
> >
<template #header="{ entity }"> <template #header="{ entity }">
<div>{{ entity.id }} - {{ entity.supplier?.name }}</div> <div>{{ entity.id }} - {{ entity.supplier?.name }}</div>

View File

@ -202,7 +202,7 @@ function setCursor(ref) {
:option-label="col.optionLabel" :option-label="col.optionLabel"
:filter-options="['id', 'name']" :filter-options="['id', 'name']"
:tooltip="t('Create a new expense')" :tooltip="t('Create a new expense')"
@keydown.tab=" @keydown.tab.prevent="
autocompleteExpense( autocompleteExpense(
$event, $event,
row, row,

View File

@ -180,6 +180,7 @@ const onDmsSaved = async (dms, response) => {
rows: dmsDialog.value.rowsToCreateInvoiceIn, rows: dmsDialog.value.rowsToCreateInvoiceIn,
dms: response.data, dms: response.data,
}); });
notify(t('Data saved'), 'positive');
} }
dmsDialog.value.show = false; dmsDialog.value.show = false;
dmsDialog.value.initialForm = null; dmsDialog.value.initialForm = null;
@ -243,7 +244,7 @@ onUnmounted(() => (stateStore.rightDrawer = false));
</template> </template>
<template #column-invoiceInFk="{ row }"> <template #column-invoiceInFk="{ row }">
<span class="link" @click.stop> <span class="link" @click.stop>
{{ row.invoiceInFk }} {{ row.supplierRef }}
<InvoiceInDescriptorProxy v-if="row.invoiceInFk" :id="row.invoiceInFk" /> <InvoiceInDescriptorProxy v-if="row.invoiceInFk" :id="row.invoiceInFk" />
</span> </span>
</template> </template>

View File

@ -1,5 +1,5 @@
<script setup> <script setup>
import { computed, ref } from 'vue'; import { computed, ref, markRaw } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useSummaryDialog } from 'src/composables/useSummaryDialog'; import { useSummaryDialog } from 'src/composables/useSummaryDialog';
import { toHour } from 'src/filters'; import { toHour } from 'src/filters';
@ -8,6 +8,7 @@ import RouteFilter from 'pages/Route/Card/RouteFilter.vue';
import VnTable from 'components/VnTable/VnTable.vue'; import VnTable from 'components/VnTable/VnTable.vue';
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue'; import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
import VnSection from 'src/components/common/VnSection.vue'; import VnSection from 'src/components/common/VnSection.vue';
import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
const { t } = useI18n(); const { t } = useI18n();
const { viewSummary } = useSummaryDialog(); const { viewSummary } = useSummaryDialog();
@ -38,17 +39,7 @@ const columns = computed(() => [
align: 'left', align: 'left',
name: 'workerFk', name: 'workerFk',
label: t('route.Worker'), label: t('route.Worker'),
component: 'select', component: markRaw(VnSelectWorker),
attrs: {
url: 'Workers/activeWithInheritedRole',
fields: ['id', 'name'],
useLike: false,
optionFilter: 'firstName',
find: {
value: 'workerFk',
label: 'workerUserName',
},
},
create: true, create: true,
cardVisible: true, cardVisible: true,
format: (row, dashIfEmpty) => dashIfEmpty(row.travelRef), format: (row, dashIfEmpty) => dashIfEmpty(row.travelRef),
@ -59,6 +50,10 @@ const columns = computed(() => [
name: 'agencyName', name: 'agencyName',
label: t('route.Agency'), label: t('route.Agency'),
cardVisible: true, cardVisible: true,
},
{
label: t('route.Agency'),
name: 'agencyModeFk',
component: 'select', component: 'select',
attrs: { attrs: {
url: 'agencyModes', url: 'agencyModes',
@ -69,14 +64,19 @@ const columns = computed(() => [
}, },
}, },
create: true, create: true,
columnClass: 'expand',
columnFilter: false, columnFilter: false,
visible: false,
}, },
{ {
align: 'left', align: 'left',
name: 'vehiclePlateNumber', name: 'vehiclePlateNumber',
label: t('route.Vehicle'), label: t('route.Vehicle'),
cardVisible: true, cardVisible: true,
},
{
name: 'vehicleFk',
label: t('route.Vehicle'),
cardVisible: true,
component: 'select', component: 'select',
attrs: { attrs: {
url: 'vehicles', url: 'vehicles',
@ -90,6 +90,7 @@ const columns = computed(() => [
}, },
create: true, create: true,
columnFilter: false, columnFilter: false,
visible: false,
}, },
{ {
align: 'left', align: 'left',
@ -156,6 +157,7 @@ const columns = computed(() => [
<VnTable <VnTable
:data-key :data-key
:columns="columns" :columns="columns"
ref="tableRef"
:right-search="false" :right-search="false"
redirect="route" redirect="route"
:create="{ :create="{

View File

@ -6,7 +6,10 @@ import VnSection from 'src/components/common/VnSection.vue';
import VnInput from 'src/components/common/VnInput.vue'; import VnInput from 'src/components/common/VnInput.vue';
import VnSelect from 'src/components/common/VnSelect.vue'; import VnSelect from 'src/components/common/VnSelect.vue';
import FetchData from 'src/components/FetchData.vue'; import FetchData from 'src/components/FetchData.vue';
import { useSummaryDialog } from 'src/composables/useSummaryDialog';
import SupplierSummary from './Card/SupplierSummary.vue';
const { viewSummary } = useSummaryDialog();
const { t } = useI18n(); const { t } = useI18n();
const tableRef = ref(); const tableRef = ref();
const dataKey = 'SupplierList'; const dataKey = 'SupplierList';
@ -103,6 +106,19 @@ const columns = computed(() => [
}, },
}, },
}, },
{
align: 'right',
label: '',
name: 'tableActions',
actions: [
{
title: t('components.smartCard.viewSummary'),
icon: 'preview',
isPrimary: true,
action: (row) => viewSummary(row.id, SupplierSummary, 'md-width'),
},
],
},
]); ]);
</script> </script>
<template> <template>

View File

@ -214,6 +214,7 @@ const columns = computed(() => [
{ {
title: t('components.smartCard.viewSummary'), title: t('components.smartCard.viewSummary'),
icon: 'preview', icon: 'preview',
isPrimary: true,
action: (row, evt) => { action: (row, evt) => {
if (evt && evt.ctrlKey) { if (evt && evt.ctrlKey) {
const url = router.resolve({ const url = router.resolve({

View File

@ -35,6 +35,22 @@ async function reactivateWorker() {
} }
} }
const columns = computed(() => [ const columns = computed(() => [
{
name: 'id',
label: t('Id'),
align: 'left',
isId: true,
cardVisible: true,
width: '40px',
},
{
name: 'isHourlyLabor',
label: t('worker.business.tableVisibleColumns.hourlyLabor'),
align: 'left',
component: 'checkbox',
cardVisible: true,
width: '60px',
},
{ {
name: 'started', name: 'started',
label: t('worker.business.tableVisibleColumns.started'), label: t('worker.business.tableVisibleColumns.started'),
@ -194,6 +210,20 @@ const columns = computed(() => [
format: ({ workerBusinessTypeName }, dashIfEmpty) => format: ({ workerBusinessTypeName }, dashIfEmpty) =>
dashIfEmpty(workerBusinessTypeName), dashIfEmpty(workerBusinessTypeName),
}, },
{
align: 'left',
name: 'workerBusinessAgreementFk',
label: t('worker.business.tableVisibleColumns.workerBusinessAgreementName'),
component: 'select',
attrs: {
url: 'WorkerBusinessAgreements',
fields: ['id', 'name'],
},
cardVisible: true,
create: true,
format: ({ workerBusinessAgreementName }, dashIfEmpty) =>
dashIfEmpty(workerBusinessAgreementName),
},
{ {
align: 'left', align: 'left',
label: t('worker.business.tableVisibleColumns.amount'), label: t('worker.business.tableVisibleColumns.amount'),
@ -230,7 +260,7 @@ const columns = computed(() => [
save-url="/Businesses/crud" save-url="/Businesses/crud"
:create="{ :create="{
urlCreate: `Workers/${entityId}/Business`, urlCreate: `Workers/${entityId}/Business`,
title: 'Create business', title: t('Create business'),
onDataSaved: () => tableRef.reload(), onDataSaved: () => tableRef.reload(),
formInitialData: {}, formInitialData: {},
}" }"
@ -248,4 +278,5 @@ const columns = computed(() => [
<i18n> <i18n>
es: es:
Do you want to reactivate the user?: desea reactivar el usuario? Do you want to reactivate the user?: desea reactivar el usuario?
Create business: Crear contrato
</i18n> </i18n>

View File

@ -1,4 +1,4 @@
describe('Entry', () => { describe.skip('Entry', () => {
beforeEach(() => { beforeEach(() => {
cy.viewport(1920, 1080); cy.viewport(1920, 1080);
cy.login('buyer'); cy.login('buyer');
@ -67,7 +67,7 @@ describe('Entry', () => {
it('Should notify when entry is lock by another user', () => { it('Should notify when entry is lock by another user', () => {
const checkLockMessage = () => { const checkLockMessage = () => {
cy.get('[data-cy="entry-lock-confirm"]').should('be.visible'); cy.get('[role="dialog"]').should('be.visible');
cy.get('[data-cy="VnConfirm_message"] > span').should( cy.get('[data-cy="VnConfirm_message"] > span').should(
'contain.text', 'contain.text',
'This entry has been locked by buyerNick', 'This entry has been locked by buyerNick',

View File

@ -0,0 +1,121 @@
describe('RouteAutonomous', () => {
const getLinkSelector = (colField) =>
`tr:first-child > [data-col-field="${colField}"] > .no-padding > .link`;
const selectors = {
reference: 'Reference_input',
date: 'tr:first-child > [data-col-field="dated"]',
total: '.value > .text-h6',
received: getLinkSelector('invoiceInFk'),
autonomous: getLinkSelector('supplierName'),
firstRowCheckbox: '.q-virtual-scroll__content tr:first-child .q-checkbox__bg',
secondRowCheckbox: '.q-virtual-scroll__content tr:nth-child(2) .q-checkbox__bg',
createInvoiceBtn: '.q-card > .q-btn',
saveFormBtn: 'FormModelPopup_save',
summaryIcon: 'tableAction-0',
summaryPopupBtn: '.header > :nth-child(2) > .q-btn__content > .q-icon',
summaryHeader: '.summaryHeader > :nth-child(2)',
descriptorHeader: '.summaryHeader > div',
descriptorTitle: '.q-item__label--header > .title > span',
summaryGoToSummaryBtn: '.header > .q-icon',
descriptorGoToSummaryBtn: '.descriptor > .header > a[href] > .q-btn',
};
const data = {
reference: 'Test invoice',
total: '€206.40',
supplier: 'PLANTS SL',
route: 'first route',
};
const summaryUrl = '/summary';
const dataSaved = 'Data saved';
beforeEach(() => {
cy.viewport(1920, 1080);
cy.login('developer');
cy.visit(`/#/route/agency-term`);
cy.typeSearchbar('{enter}');
});
it('Should list autonomous routes', () => {
cy.get('.q-table')
.children()
.should('be.visible')
.should('have.length.greaterThan', 0);
});
it('Should create invoice in to selected route', () => {
cy.get(selectors.firstRowCheckbox).click();
cy.get(selectors.createInvoiceBtn).click();
cy.dataCy(selectors.reference).type(data.reference);
cy.get('.q-file').selectFile('test/cypress/fixtures/image.jpg', {
force: true,
});
cy.dataCy(selectors.saveFormBtn).click();
cy.checkNotification(dataSaved);
cy.typeSearchbar('{enter}');
});
it('Should display the total price of the selected rows', () => {
cy.get(selectors.firstRowCheckbox).click();
cy.get(selectors.secondRowCheckbox).click();
cy.validateContent(selectors.total, data.total);
});
it('Should redirect to the summary when clicking a route', () => {
cy.get(selectors.date).click();
cy.get(selectors.summaryHeader).should('contain', data.route);
cy.url().should('include', summaryUrl);
});
describe('Received pop-ups', () => {
it('Should redirect to invoice in summary from the received descriptor pop-up', () => {
cy.get(selectors.received).click();
cy.validateContent(selectors.descriptorTitle, data.reference);
cy.get(selectors.descriptorGoToSummaryBtn).click();
cy.get(selectors.descriptorHeader).should('contain', data.supplier);
cy.url().should('include', summaryUrl);
});
it('Should redirect to the invoiceIn summary from summary pop-up from the received descriptor pop-up', () => {
cy.get(selectors.received).click();
cy.validateContent(selectors.descriptorTitle, data.reference);
cy.get(selectors.summaryPopupBtn).click();
cy.get(selectors.descriptorHeader).should('contain', data.supplier);
cy.get(selectors.summaryGoToSummaryBtn).click();
cy.get(selectors.descriptorHeader).should('contain', data.supplier);
cy.url().should('include', summaryUrl);
});
});
describe('Autonomous pop-ups', () => {
it('Should redirect to the supplier summary from the received descriptor pop-up', () => {
cy.get(selectors.autonomous).click();
cy.validateContent(selectors.descriptorTitle, data.supplier);
cy.get(selectors.descriptorGoToSummaryBtn).click();
cy.get(selectors.summaryHeader).should('contain', data.supplier);
cy.url().should('include', summaryUrl);
});
it('Should redirect to the supplier summary from summary pop-up from the autonomous descriptor pop-up', () => {
cy.get(selectors.autonomous).click();
cy.get(selectors.descriptorTitle).should('contain', data.supplier);
cy.get(selectors.summaryPopupBtn).click();
cy.get(selectors.summaryHeader).should('contain', data.supplier);
cy.get(selectors.summaryGoToSummaryBtn).click();
cy.get(selectors.summaryHeader).should('contain', data.supplier);
cy.url().should('include', summaryUrl);
});
});
describe('Route pop-ups', () => {
it('Should redirect to the summary from the route summary pop-up', () => {
cy.dataCy(selectors.summaryIcon).first().click();
cy.get(selectors.summaryHeader).should('contain', data.route);
cy.get(selectors.summaryGoToSummaryBtn).click();
cy.get(selectors.summaryHeader).should('contain', data.route);
cy.url().should('include', summaryUrl);
});
});
});

View File

@ -1,5 +1,5 @@
/// <reference types="cypress" /> /// <reference types="cypress" />
describe('TicketList', () => { describe.skip('TicketList', () => {
const firstRow = 'tbody > :nth-child(1)'; const firstRow = 'tbody > :nth-child(1)';
beforeEach(() => { beforeEach(() => {