Merge branch 'dev' into 8623-FixInvoiceOutModule
gitea/salix-front/pipeline/pr-dev This commit looks good
Details
gitea/salix-front/pipeline/pr-dev This commit looks good
Details
This commit is contained in:
commit
807ee381fc
|
@ -30,22 +30,5 @@ export default {
|
|||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
form.addEventListener('keyup', function (evt) {
|
||||
if (evt.key === 'Enter' && !that.$attrs['prevent-submit']) {
|
||||
const input = evt.target;
|
||||
if (input.type == 'textarea' && evt.shiftKey) {
|
||||
evt.preventDefault();
|
||||
let { selectionStart, selectionEnd } = input;
|
||||
input.value =
|
||||
input.value.substring(0, selectionStart) +
|
||||
'\n' +
|
||||
input.value.substring(selectionEnd);
|
||||
selectionStart = selectionEnd = selectionStart + 1;
|
||||
return;
|
||||
}
|
||||
evt.preventDefault();
|
||||
that.onSubmit();
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script setup>
|
||||
import axios from 'axios';
|
||||
import { onMounted, onUnmounted, computed, ref, watch, nextTick } from 'vue';
|
||||
import { onMounted, onUnmounted, computed, ref, watch, nextTick, useAttrs } from 'vue';
|
||||
import { onBeforeRouteLeave, useRouter, useRoute } from 'vue-router';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useQuasar } from 'quasar';
|
||||
|
@ -22,6 +22,7 @@ const { validate } = useValidator();
|
|||
const { notify } = useNotify();
|
||||
const route = useRoute();
|
||||
const myForm = ref(null);
|
||||
const attrs = useAttrs();
|
||||
const $props = defineProps({
|
||||
url: {
|
||||
type: String,
|
||||
|
@ -113,7 +114,7 @@ const defaultButtons = computed(() => ({
|
|||
color: 'primary',
|
||||
icon: 'save',
|
||||
label: 'globals.save',
|
||||
click: () => myForm.value.onSubmit(false),
|
||||
click: async () => await save(),
|
||||
type: 'submit',
|
||||
},
|
||||
reset: {
|
||||
|
@ -208,8 +209,7 @@ async function fetch() {
|
|||
}
|
||||
}
|
||||
|
||||
async function save(prevent = false) {
|
||||
if (prevent) return;
|
||||
async function save() {
|
||||
if ($props.observeFormChanges && !hasChanges.value)
|
||||
return notify('globals.noChanges', 'negative');
|
||||
|
||||
|
@ -284,6 +284,22 @@ function trimData(data) {
|
|||
return data;
|
||||
}
|
||||
|
||||
async function onKeyup(evt) {
|
||||
if (evt.key === 'Enter' && !('prevent-submit' in attrs)) {
|
||||
const input = evt.target;
|
||||
if (input.type == 'textarea' && evt.shiftKey) {
|
||||
let { selectionStart, selectionEnd } = input;
|
||||
input.value =
|
||||
input.value.substring(0, selectionStart) +
|
||||
'\n' +
|
||||
input.value.substring(selectionEnd);
|
||||
selectionStart = selectionEnd = selectionStart + 1;
|
||||
return;
|
||||
}
|
||||
await save();
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
save,
|
||||
isLoading,
|
||||
|
@ -298,12 +314,12 @@ defineExpose({
|
|||
<QForm
|
||||
ref="myForm"
|
||||
v-if="formData"
|
||||
@submit="save(!!$event)"
|
||||
@submit.prevent
|
||||
@keyup.prevent="onKeyup"
|
||||
@reset="reset"
|
||||
class="q-pa-md"
|
||||
:style="maxWidth ? 'max-width: ' + maxWidth : ''"
|
||||
id="formModel"
|
||||
:prevent-submit="$attrs['prevent-submit']"
|
||||
>
|
||||
<QCard>
|
||||
<slot
|
||||
|
|
|
@ -27,10 +27,15 @@ const formModelRef = ref(null);
|
|||
const closeButton = ref(null);
|
||||
const isSaveAndContinue = ref(false);
|
||||
const onDataSaved = (formData, requestResponse) => {
|
||||
if (closeButton.value && isSaveAndContinue) closeButton.value.click();
|
||||
if (closeButton.value && !isSaveAndContinue.value) closeButton.value.click();
|
||||
emit('onDataSaved', formData, requestResponse);
|
||||
};
|
||||
|
||||
const onClick = async (saveAndContinue) => {
|
||||
isSaveAndContinue.value = saveAndContinue;
|
||||
await formModelRef.value.save();
|
||||
};
|
||||
|
||||
const isLoading = computed(() => formModelRef.value?.isLoading);
|
||||
const reset = computed(() => formModelRef.value?.reset);
|
||||
|
||||
|
@ -78,10 +83,7 @@ defineExpose({
|
|||
:flat="showSaveAndContinueBtn"
|
||||
:label="t('globals.save')"
|
||||
:title="t('globals.save')"
|
||||
@click="
|
||||
formModelRef.save();
|
||||
isSaveAndContinue = false;
|
||||
"
|
||||
@click="onClick(false)"
|
||||
color="primary"
|
||||
class="q-ml-sm"
|
||||
:disabled="isLoading"
|
||||
|
@ -99,10 +101,7 @@ defineExpose({
|
|||
:loading="isLoading"
|
||||
data-cy="FormModelPopup_isSaveAndContinue"
|
||||
z-max
|
||||
@click="
|
||||
isSaveAndContinue = true;
|
||||
formModelRef.save();
|
||||
"
|
||||
@click="onClick(true)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -335,3 +335,7 @@ input::-webkit-inner-spin-button {
|
|||
border: 1px solid;
|
||||
box-shadow: 0 4px 6px #00000000;
|
||||
}
|
||||
|
||||
.containerShrinked {
|
||||
width: 80%;
|
||||
}
|
||||
|
|
|
@ -114,7 +114,7 @@ function onBeforeSave(data) {
|
|||
if (isCash.value && shouldSendEmail.value && !data.email)
|
||||
return notify(t('There is no assigned email for this client'), 'negative');
|
||||
|
||||
data.bankFk = data.bankFk.id;
|
||||
data.bankFk = data.bankFk?.id;
|
||||
return data;
|
||||
}
|
||||
|
||||
|
@ -189,7 +189,7 @@ async function getAmountPaid() {
|
|||
:url-create="urlCreate"
|
||||
:mapper="onBeforeSave"
|
||||
@on-data-saved="onDataSaved"
|
||||
:prevent-submit="true"
|
||||
prevent-submit
|
||||
>
|
||||
<template #form="{ data, validate }">
|
||||
<span ref="closeButton" class="row justify-end close-icon" v-close-popup>
|
||||
|
|
|
@ -25,7 +25,7 @@ const setFilteredAddresses = (data) => {
|
|||
@on-fetch="(data) => (validAddresses = data)"
|
||||
/>
|
||||
<FetchData url="Addresses" auto-load @on-fetch="setFilteredAddresses" />
|
||||
<FormModel auto-load model="zone">
|
||||
<FormModel auto-load model="Zone">
|
||||
<template #form="{ data, validate }">
|
||||
<VnRow>
|
||||
<VnInput
|
||||
|
@ -33,6 +33,7 @@ const setFilteredAddresses = (data) => {
|
|||
:label="t('Name')"
|
||||
clearable
|
||||
v-model="data.name"
|
||||
:required="true"
|
||||
/>
|
||||
</VnRow>
|
||||
<VnRow>
|
||||
|
@ -83,7 +84,7 @@ const setFilteredAddresses = (data) => {
|
|||
type="number"
|
||||
min="0"
|
||||
/>
|
||||
<VnInputTime v-model="data.hour" :label="t('Closing')" />
|
||||
<VnInputTime v-model="data.hour" :label="t('Closing')" :required="true" />
|
||||
</VnRow>
|
||||
|
||||
<VnRow>
|
||||
|
@ -92,7 +93,7 @@ const setFilteredAddresses = (data) => {
|
|||
:label="t('Price')"
|
||||
type="number"
|
||||
min="0"
|
||||
required="true"
|
||||
:required="true"
|
||||
clearable
|
||||
/>
|
||||
<VnInput
|
||||
|
@ -100,7 +101,7 @@ const setFilteredAddresses = (data) => {
|
|||
:label="t('Price optimum')"
|
||||
type="number"
|
||||
min="0"
|
||||
required="true"
|
||||
:required="true"
|
||||
clearable
|
||||
/>
|
||||
</VnRow>
|
||||
|
|
|
@ -38,7 +38,12 @@ const agencies = ref([]);
|
|||
<template #body="{ params, searchFn }">
|
||||
<QItem>
|
||||
<QItemSection>
|
||||
<VnInput :label="t('list.name')" v-model="params.name" is-outlined />
|
||||
<VnInput
|
||||
:label="t('list.name')"
|
||||
v-model="params.name"
|
||||
is-outlined
|
||||
data-cy="zoneFilterPanelNameInput"
|
||||
/>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
<QItem>
|
||||
|
@ -53,6 +58,7 @@ const agencies = ref([]);
|
|||
dense
|
||||
outlined
|
||||
rounded
|
||||
data-cy="zoneFilterPanelAgencySelect"
|
||||
>
|
||||
</VnSelect>
|
||||
</QItemSection>
|
||||
|
|
|
@ -65,7 +65,6 @@ const tableFilter = {
|
|||
|
||||
const columns = computed(() => [
|
||||
{
|
||||
align: 'left',
|
||||
name: 'id',
|
||||
label: t('list.id'),
|
||||
chip: {
|
||||
|
@ -75,6 +74,8 @@ const columns = computed(() => [
|
|||
columnFilter: {
|
||||
inWhere: true,
|
||||
},
|
||||
columnClass: 'shrink-column',
|
||||
component: 'number',
|
||||
},
|
||||
{
|
||||
align: 'left',
|
||||
|
@ -106,7 +107,6 @@ const columns = computed(() => [
|
|||
format: (row, dashIfEmpty) => dashIfEmpty(row?.agencyMode?.name),
|
||||
},
|
||||
{
|
||||
align: 'left',
|
||||
name: 'price',
|
||||
label: t('list.price'),
|
||||
cardVisible: true,
|
||||
|
@ -114,9 +114,11 @@ const columns = computed(() => [
|
|||
columnFilter: {
|
||||
inWhere: true,
|
||||
},
|
||||
columnClass: 'shrink-column',
|
||||
component: 'number',
|
||||
},
|
||||
{
|
||||
align: 'left',
|
||||
align: 'center',
|
||||
name: 'hour',
|
||||
label: t('list.close'),
|
||||
cardVisible: true,
|
||||
|
@ -129,6 +131,7 @@ const columns = computed(() => [
|
|||
label: t('list.addressFk'),
|
||||
cardVisible: true,
|
||||
columnFilter: false,
|
||||
columnClass: 'expand',
|
||||
},
|
||||
{
|
||||
align: 'right',
|
||||
|
@ -177,67 +180,73 @@ function formatRow(row) {
|
|||
<ZoneFilterPanel data-key="ZonesList" />
|
||||
</template>
|
||||
</RightMenu>
|
||||
<VnTable
|
||||
ref="tableRef"
|
||||
data-key="ZonesList"
|
||||
url="Zones"
|
||||
:create="{
|
||||
urlCreate: 'Zones',
|
||||
title: t('list.createZone'),
|
||||
onDataSaved: ({ id }) => tableRef.redirect(`${id}/location`),
|
||||
formInitialData: {},
|
||||
}"
|
||||
:user-filter="tableFilter"
|
||||
:columns="columns"
|
||||
redirect="zone"
|
||||
:right-search="false"
|
||||
>
|
||||
<template #column-addressFk="{ row }">
|
||||
{{ dashIfEmpty(formatRow(row)) }}
|
||||
</template>
|
||||
<template #more-create-dialog="{ data }">
|
||||
<VnSelect
|
||||
url="AgencyModes"
|
||||
v-model="data.agencyModeFk"
|
||||
option-value="id"
|
||||
option-label="name"
|
||||
:label="t('list.agency')"
|
||||
/>
|
||||
<VnInput
|
||||
v-model="data.price"
|
||||
:label="t('list.price')"
|
||||
min="0"
|
||||
type="number"
|
||||
required="true"
|
||||
/>
|
||||
<VnInput
|
||||
v-model="data.bonus"
|
||||
:label="t('zone.bonus')"
|
||||
min="0"
|
||||
type="number"
|
||||
/>
|
||||
<VnInput
|
||||
v-model="data.travelingDays"
|
||||
:label="t('zone.travelingDays')"
|
||||
type="number"
|
||||
min="0"
|
||||
/>
|
||||
<VnInputTime v-model="data.hour" :label="t('list.close')" />
|
||||
<VnSelect
|
||||
url="Warehouses"
|
||||
v-model="data.warehouseFK"
|
||||
option-value="id"
|
||||
option-label="name"
|
||||
:label="t('list.warehouse')"
|
||||
:options="warehouseOptions"
|
||||
/>
|
||||
<QCheckbox
|
||||
v-model="data.isVolumetric"
|
||||
:label="t('list.isVolumetric')"
|
||||
:toggle-indeterminate="false"
|
||||
/>
|
||||
</template>
|
||||
</VnTable>
|
||||
<div class="table-container">
|
||||
<div class="column items-center">
|
||||
<VnTable
|
||||
ref="tableRef"
|
||||
data-key="ZonesList"
|
||||
url="Zones"
|
||||
:create="{
|
||||
urlCreate: 'Zones',
|
||||
title: t('list.createZone'),
|
||||
onDataSaved: ({ id }) => tableRef.redirect(`${id}/location`),
|
||||
formInitialData: {},
|
||||
}"
|
||||
:user-filter="tableFilter"
|
||||
:columns="columns"
|
||||
redirect="zone"
|
||||
:right-search="false"
|
||||
table-height="85vh"
|
||||
order="id ASC"
|
||||
>
|
||||
<template #column-addressFk="{ row }">
|
||||
{{ dashIfEmpty(formatRow(row)) }}
|
||||
</template>
|
||||
<template #more-create-dialog="{ data }">
|
||||
<VnSelect
|
||||
url="AgencyModes"
|
||||
v-model="data.agencyModeFk"
|
||||
option-value="id"
|
||||
option-label="name"
|
||||
:label="t('list.agency')"
|
||||
/>
|
||||
<VnInput
|
||||
v-model="data.price"
|
||||
:label="t('list.price')"
|
||||
min="0"
|
||||
type="number"
|
||||
required="true"
|
||||
/>
|
||||
<VnInput
|
||||
v-model="data.bonus"
|
||||
:label="t('zone.bonus')"
|
||||
min="0"
|
||||
type="number"
|
||||
/>
|
||||
<VnInput
|
||||
v-model="data.travelingDays"
|
||||
:label="t('zone.travelingDays')"
|
||||
type="number"
|
||||
min="0"
|
||||
/>
|
||||
<VnInputTime v-model="data.hour" :label="t('list.close')" />
|
||||
<VnSelect
|
||||
url="Warehouses"
|
||||
v-model="data.warehouseFK"
|
||||
option-value="id"
|
||||
option-label="name"
|
||||
:label="t('list.warehouse')"
|
||||
:options="warehouseOptions"
|
||||
/>
|
||||
<QCheckbox
|
||||
v-model="data.isVolumetric"
|
||||
:label="t('list.isVolumetric')"
|
||||
:toggle-indeterminate="false"
|
||||
/>
|
||||
</template>
|
||||
</VnTable>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<i18n>
|
||||
|
@ -245,3 +254,20 @@ es:
|
|||
Search zone: Buscar zona
|
||||
You can search zones by id or name: Puedes buscar zonas por id o nombre
|
||||
</i18n>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.table-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
.column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
min-width: 70%;
|
||||
}
|
||||
|
||||
:deep(.shrink-column) {
|
||||
width: 8%;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -56,7 +56,7 @@ onMounted(() => weekdayStore.initStore());
|
|||
<ZoneSearchbar />
|
||||
<VnSubToolbar />
|
||||
<QPage class="column items-center q-pa-md">
|
||||
<QCard class="full-width q-pa-md">
|
||||
<QCard class="containerShrinked q-pa-md">
|
||||
<div
|
||||
v-for="(detail, index) in details"
|
||||
:key="index"
|
||||
|
|
|
@ -44,6 +44,8 @@ summary:
|
|||
filterPanel:
|
||||
name: Name
|
||||
agencyModeFk: Agency
|
||||
id: ID
|
||||
price: Price
|
||||
deliveryPanel:
|
||||
pickup: Pick up
|
||||
delivery: Delivery
|
||||
|
|
|
@ -45,6 +45,8 @@ summary:
|
|||
filterPanel:
|
||||
name: Nombre
|
||||
agencyModeFk: Agencia
|
||||
id: ID
|
||||
price: Precio
|
||||
deliveryPanel:
|
||||
pickup: Recogida
|
||||
delivery: Entrega
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
describe('ZoneList', () => {
|
||||
const agency = 'inhouse pickup';
|
||||
beforeEach(() => {
|
||||
cy.viewport(1280, 720);
|
||||
cy.login('developer');
|
||||
|
@ -6,11 +7,15 @@ describe('ZoneList', () => {
|
|||
});
|
||||
|
||||
it('should filter by agency', () => {
|
||||
cy.get('input[aria-label="Agency"]').type('{downArrow}{enter}');
|
||||
cy.dataCy('zoneFilterPanelNameInput').type('{downArrow}{enter}');
|
||||
});
|
||||
|
||||
it('should open the zone summary', () => {
|
||||
cy.get('input[aria-label="Name"]').type('zone refund');
|
||||
cy.get('.q-scrollarea__content > .q-btn--standard > .q-btn__content').click();
|
||||
cy.dataCy('zoneFilterPanelAgencySelect').type(agency);
|
||||
cy.get('.q-menu .q-item').contains(agency).click();
|
||||
cy.get(':nth-child(1) > [data-col-field="agencyModeFk"]').should(
|
||||
'include.text',
|
||||
agency,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue