From 65e48f6194e42ba9332ed07f9e92c314ec8dee62 Mon Sep 17 00:00:00 2001 From: pablone <pablone@verdnatura.es> Date: Wed, 12 Feb 2025 19:43:45 +0100 Subject: [PATCH 1/2] feat: refs #6897 refactor VnColor and EntryList components; update FormModelPopup button visibility --- src/components/FormModelPopup.vue | 27 ++++++----- src/components/VnTable/VnTable.vue | 8 ++-- src/components/common/VnColor.vue | 4 +- src/i18n/locale/en.yml | 1 + src/i18n/locale/es.yml | 1 + src/pages/Entry/Card/EntryBuys.vue | 76 +++++++++++++++++++++--------- src/pages/Entry/EntryList.vue | 12 +---- 7 files changed, 79 insertions(+), 50 deletions(-) diff --git a/src/components/FormModelPopup.vue b/src/components/FormModelPopup.vue index 30aaa3513..3ae71a341 100644 --- a/src/components/FormModelPopup.vue +++ b/src/components/FormModelPopup.vue @@ -58,19 +58,6 @@ defineExpose({ <p>{{ subtitle }}</p> <slot name="form-inputs" :data="data" :validate="validate" /> <div class="q-mt-lg row justify-end"> - <QBtn - v-if="showSaveAndContinueBtn" - :label="t('globals.isSaveAndContinue')" - :title="t('globals.isSaveAndContinue')" - type="submit" - color="primary" - class="q-ml-sm" - :disabled="isLoading" - :loading="isLoading" - data-cy="FormModelPopup_isSaveAndContinue" - z-max - @click="() => (isSaveAndContinue = true)" - /> <QBtn :label="t('globals.cancel')" :title="t('globals.cancel')" @@ -90,6 +77,20 @@ defineExpose({ " /> <QBtn + v-if="showSaveAndContinueBtn" + :label="t('globals.isSaveAndContinue')" + :title="t('globals.isSaveAndContinue')" + type="submit" + color="primary" + class="q-ml-sm" + :disabled="isLoading" + :loading="isLoading" + data-cy="FormModelPopup_isSaveAndContinue" + z-max + @click="() => (isSaveAndContinue = true)" + /> + <QBtn + v-else :label="t('globals.save')" :title="t('globals.save')" type="submit" diff --git a/src/components/VnTable/VnTable.vue b/src/components/VnTable/VnTable.vue index 7e0757f6c..3e1923b4c 100644 --- a/src/components/VnTable/VnTable.vue +++ b/src/components/VnTable/VnTable.vue @@ -340,8 +340,9 @@ const clickHandler = async (event) => { const isDateElement = event.target.closest('.q-date'); const isTimeElement = event.target.closest('.q-time'); + const isQselectDropDown = event.target.closest('.q-select__dropdown-icon'); - if (isDateElement || isTimeElement) return; + if (isDateElement || isTimeElement || isQselectDropDown) return; if (clickedElement === null) { destroyInput(editingRow.value, editingField.value); @@ -411,7 +412,7 @@ async function renderInput(rowId, field, clickedElement) { focusOnMount: true, eventHandlers: { 'update:modelValue': async (value) => { - if (isSelect) { + if (isSelect && value) { row[column.name] = value[column.attrs?.optionValue ?? 'id']; row[column?.name + 'TextValue'] = value[column.attrs?.optionLabel ?? 'name']; @@ -593,6 +594,7 @@ const checkbox = ref(null); @row-click="(_, row) => rowClickFunction && rowClickFunction(row)" @update:selected="emit('update:selected', $event)" @selection="(details) => handleSelection(details, rows)" + :hide-selected-banner="true" > <template #top-left v-if="!$props.withoutHeader"> <slot name="top-left"> </slot> @@ -1042,7 +1044,7 @@ es: .grid-three { display: grid; - grid-template-columns: repeat(auto-fit, minmax(150px, max-content)); + grid-template-columns: repeat(auto-fit, minmax(300px, max-content)); max-width: 100%; grid-gap: 20px; margin: 0 auto; diff --git a/src/components/common/VnColor.vue b/src/components/common/VnColor.vue index 00e662bb8..8a5a787b0 100644 --- a/src/components/common/VnColor.vue +++ b/src/components/common/VnColor.vue @@ -2,7 +2,7 @@ const $props = defineProps({ colors: { type: String, - default: '{"value":[]}', + default: '{"value": []}', }, }); @@ -11,7 +11,7 @@ const maxHeight = 30; const colorHeight = maxHeight / colorArray?.length; </script> <template> - <div class="color-div" :style="{ height: `${maxHeight}px` }"> + <div v-if="colors" class="color-div" :style="{ height: `${maxHeight}px` }"> <div v-for="(color, index) in colorArray" :key="index" diff --git a/src/i18n/locale/en.yml b/src/i18n/locale/en.yml index 44759769a..e3b690042 100644 --- a/src/i18n/locale/en.yml +++ b/src/i18n/locale/en.yml @@ -156,6 +156,7 @@ globals: changeState: Change state raid: 'Raid {daysInForward} days' isVies: Vies + noData: No data available pageTitles: logIn: Login addressEdit: Update address diff --git a/src/i18n/locale/es.yml b/src/i18n/locale/es.yml index 2f8e6c1d1..1dbe25366 100644 --- a/src/i18n/locale/es.yml +++ b/src/i18n/locale/es.yml @@ -160,6 +160,7 @@ globals: changeState: Cambiar estado raid: 'Redada {daysInForward} días' isVies: Vies + noData: Datos no disponibles pageTitles: logIn: Inicio de sesión addressEdit: Modificar consignatario diff --git a/src/pages/Entry/Card/EntryBuys.vue b/src/pages/Entry/Card/EntryBuys.vue index 76e1bb860..e159c5356 100644 --- a/src/pages/Entry/Card/EntryBuys.vue +++ b/src/pages/Entry/Card/EntryBuys.vue @@ -156,10 +156,10 @@ const columns = [ { align: 'center', labelAbbreviation: t('Sti.'), - label: t('Printed Stickers/Stickers'), + label: t('Stickers'), toolTip: t('Printed Stickers/Stickers'), name: 'stickers', - component: 'number', + component: 'input', create: true, attrs: { positive: false, @@ -179,7 +179,7 @@ const columns = [ component: 'select', attrs: { url: 'packagings', - fields: ['id', 'volume'], + fields: ['id'], optionLabel: 'id', }, create: true, @@ -192,10 +192,10 @@ const columns = [ component: 'number', create: true, width: '35px', + format: (row, dashIfEmpty) => parseFloat(row['weight']).toFixed(1), }, { - align: 'center', - labelAbbreviation: 'Pack', + labelAbbreviation: 'P', label: 'Packing', toolTip: 'Packing', name: 'packing', @@ -209,14 +209,13 @@ const columns = [ row['amount'] = row['quantity'] * row['buyingValue']; }, }, - width: '35px', + width: '20px', style: (row) => { if (row.groupingMode === 'grouping') return { color: 'var(--vn-label-color)' }; }, }, { - align: 'center', labelAbbreviation: 'GM', label: t('Grouping selector'), toolTip: t('Grouping selector'), @@ -229,7 +228,7 @@ const columns = [ indeterminateValue: null, }, size: 'xs', - width: '30px', + width: '25px', create: true, rightFilter: false, getIcon: (value) => { @@ -245,12 +244,12 @@ const columns = [ }, { align: 'center', - labelAbbreviation: 'Group', + labelAbbreviation: 'G', label: 'Grouping', toolTip: 'Grouping', name: 'grouping', component: 'number', - width: '35px', + width: '20px', create: true, style: (row) => { if (row.groupingMode === 'packing') return { color: 'var(--vn-label-color)' }; @@ -290,6 +289,7 @@ const columns = [ }, }, width: '45px', + format: (row) => parseFloat(row['buyingValue']).toFixed(3), }, { align: 'center', @@ -301,6 +301,7 @@ const columns = [ positive: false, }, isEditable: false, + format: (row) => parseFloat(row['amount']).toFixed(2), style: getAmountStyle, }, { @@ -312,6 +313,7 @@ const columns = [ component: 'number', width: '35px', create: true, + format: (row) => parseFloat(row['price2']).toFixed(2), }, { align: 'center', @@ -325,6 +327,7 @@ const columns = [ }, width: '35px', create: true, + format: (row) => parseFloat(row['price3']).toFixed(2), }, { align: 'center', @@ -344,6 +347,7 @@ const columns = [ style: (row) => { if (!row?.hasMinPrice) return { color: 'var(--vn-label-color)' }; }, + format: (row) => parseFloat(row['minPrice']).toFixed(2), }, { align: 'center', @@ -518,7 +522,7 @@ onMounted(() => { <Teleport to="#st-data" v-if="stateStore?.isSubToolbarShown() && editableMode"> <QBtnGroup push style="column-gap: 1px"> <QBtnDropdown - icon="exposure_neg_1" + label="+/-" color="primary" flat :title="t('Invert quantity value')" @@ -533,7 +537,7 @@ onMounted(() => { @click="invertQuantitySign(selectedRows, -1)" data-cy="set-negative-quantity" > - <span style="font-size: medium">-1</span> + <span style="font-size: large">-</span> </QBtn> </QItemSection> </QItem> @@ -544,7 +548,7 @@ onMounted(() => { @click="invertQuantitySign(selectedRows, 1)" data-cy="set-positive-quantity" > - <span style="font-size: medium">1</span> + <span style="font-size: large">+</span> </QBtn> </QItemSection> </QItem> @@ -558,11 +562,11 @@ onMounted(() => { :disable="!selectedRows.length" data-cy="check-buy-amount" > - <QTooltip>{{}}</QTooltip> <QList> <QItem> <QItemSection> <QBtn + size="sm" icon="check" flat @click="setIsChecked(selectedRows, true)" @@ -573,6 +577,7 @@ onMounted(() => { <QItem> <QItemSection> <QBtn + size="sm" icon="close" flat @click="setIsChecked(selectedRows, false)" @@ -662,7 +667,7 @@ onMounted(() => { <FetchedTags :item="row" :columns="3" /> </template> <template #column-stickers="{ row }"> - <span class="editable-text"> + <span :class="editableMode ? 'editable-text' : ''"> <span style="color: var(--vn-label-color)"> {{ row.printedStickers }} </span> @@ -693,20 +698,36 @@ onMounted(() => { </template> <template #column-create-itemFk="{ data }"> <VnSelect - url="Items" + url="Items/search" v-model="data.itemFk" :label="t('Article')" - :fields="['id', 'name']" + :fields="['id', 'name', 'size', 'producerName']" + :filter-options="['id', 'name', 'size', 'producerName']" option-label="name" option-value="id" @update:modelValue=" async (value) => { - setBuyUltimate(value, data); + await setBuyUltimate(value, data); } " :required="true" data-cy="itemFk-create-popup" - /> + sort-by="nickname DESC" + > + <template #option="scope"> + <QItem v-bind="scope.itemProps"> + <QItemSection> + <QItemLabel> + {{ scope.opt.name }} + </QItemLabel> + <QItemLabel caption> + #{{ scope.opt.id }}, {{ scope.opt?.size }}, + {{ scope.opt?.producerName }} + </QItemLabel> + </QItemSection> + </QItem> + </template> + </VnSelect> </template> <template #column-create-groupingMode="{ data }"> <VnSelectEnum @@ -720,9 +741,14 @@ onMounted(() => { /> </template> <template #previous-create-dialog="{ data }"> - <div style="position: absolute"> + <div + style="position: absolute" + :class="{ 'centered-container': !data.itemFk }" + > <ItemDescriptor :id="data.itemFk" v-if="data.itemFk" /> - <SkeletonDescriptor v-if="!data.itemFk" :has-image="true" /> + <div v-else> + <span>{{ t('globals.noData') }}</span> + </div> </div> </template> </VnTable> @@ -744,6 +770,7 @@ es: Com.: Ref. Comment: Referencia Minimum price: Precio mínimo + Stickers: Etiquetas Printed Stickers/Stickers: Etiquetas impresas/Etiquetas Cost: Cost. Buying value: Coste @@ -761,7 +788,12 @@ es: Check buy amount: Marcar como correcta la cantidad de compra </i18n> <style lang="scss" scoped> -.test { +.centered-container { + display: flex; justify-content: center; + align-items: center; + position: absolute; + width: 40%; + height: 100%; } </style> diff --git a/src/pages/Entry/EntryList.vue b/src/pages/Entry/EntryList.vue index c2b9e8bba..845d65604 100644 --- a/src/pages/Entry/EntryList.vue +++ b/src/pages/Entry/EntryList.vue @@ -182,14 +182,6 @@ const columns = computed(() => [ name: 'entryTypeCode', cardVisible: true, }, - { - name: 'dated', - label: t('entry.list.tableVisibleColumns.dated'), - component: 'date', - cardVisible: false, - visible: false, - create: true, - }, { name: 'companyFk', label: t('entry.list.tableVisibleColumns.companyFk'), @@ -220,7 +212,8 @@ function getBadgeAttrs(row) { let timeDiff = today - timeTicket; - if (timeDiff > 0) return { color: 'warning', 'text-color': 'black' }; + if (timeDiff > 0) return { color: 'info', 'text-color': 'black' }; + if (timeDiff < 0) return { color: 'warning', 'text-color': 'black' }; switch (row.entryTypeCode) { case 'regularization': case 'life': @@ -245,7 +238,6 @@ function getBadgeAttrs(row) { default: break; } - if (timeDiff < 0) return { color: 'info', 'text-color': 'black' }; return { color: 'transparent' }; } -- 2.40.1 From 8539e933897551edf5af974e5263953ad301bb50 Mon Sep 17 00:00:00 2001 From: pablone <pablone@verdnatura.es> Date: Thu, 13 Feb 2025 08:42:13 +0100 Subject: [PATCH 2/2] feat: refs #6897 update FormModelPopup button logic and add entryList tests --- src/components/FormModelPopup.vue | 26 +++++++++---------- .../{entrylist.spec.js => entryList.spec.js} | 8 +++--- .../integration/route/routeList.spec.js | 26 +++++++++++-------- 3 files changed, 32 insertions(+), 28 deletions(-) rename test/cypress/integration/entry/{entrylist.spec.js => entryList.spec.js} (98%) diff --git a/src/components/FormModelPopup.vue b/src/components/FormModelPopup.vue index 3ae71a341..5cc7f06d2 100644 --- a/src/components/FormModelPopup.vue +++ b/src/components/FormModelPopup.vue @@ -76,6 +76,19 @@ defineExpose({ } " /> + <QBtn + :flat="showSaveAndContinueBtn" + :label="t('globals.save')" + :title="t('globals.save')" + type="submit" + color="primary" + class="q-ml-sm" + :disabled="isLoading" + :loading="isLoading" + data-cy="FormModelPopup_save" + z-max + @click="() => (isSaveAndContinue = false)" + /> <QBtn v-if="showSaveAndContinueBtn" :label="t('globals.isSaveAndContinue')" @@ -89,19 +102,6 @@ defineExpose({ z-max @click="() => (isSaveAndContinue = true)" /> - <QBtn - v-else - :label="t('globals.save')" - :title="t('globals.save')" - type="submit" - color="primary" - class="q-ml-sm" - :disabled="isLoading" - :loading="isLoading" - data-cy="FormModelPopup_save" - z-max - @click="() => (isSaveAndContinue = false)" - /> </div> </template> </FormModel> diff --git a/test/cypress/integration/entry/entrylist.spec.js b/test/cypress/integration/entry/entryList.spec.js similarity index 98% rename from test/cypress/integration/entry/entrylist.spec.js rename to test/cypress/integration/entry/entryList.spec.js index 2eb9a7013..5e2fa0c01 100644 --- a/test/cypress/integration/entry/entrylist.spec.js +++ b/test/cypress/integration/entry/entryList.spec.js @@ -124,12 +124,12 @@ describe('Entry', () => { clickAndType('stickers', '1'); checkText('quantity', '11'); - checkText('amount', '550'); + checkText('amount', '550.00'); clickAndType('packing', '2'); checkText('packing', '12close'); - checkText('weight', '12'); + checkText('weight', '12.0'); checkText('quantity', '132'); - checkText('amount', '6600'); + checkText('amount', '6600.00'); checkColor('packing', COLORS.enabled); selectCell('groupingMode').click().click().click(); @@ -137,7 +137,7 @@ describe('Entry', () => { checkColor('grouping', COLORS.enabled); selectCell('buyingValue').click().clear().type('{backspace}{backspace}1'); - checkText('amount', '132'); + checkText('amount', '132.00'); checkColor('minPrice', COLORS.disable); selectCell('hasMinPrice').click().click(); diff --git a/test/cypress/integration/route/routeList.spec.js b/test/cypress/integration/route/routeList.spec.js index 421bdbcc8..976ce7352 100644 --- a/test/cypress/integration/route/routeList.spec.js +++ b/test/cypress/integration/route/routeList.spec.js @@ -4,9 +4,6 @@ describe('Route', () => { cy.login('developer'); cy.visit(`/#/route/extended-list`); }); - const getVnSelect = - '> :nth-child(1) > .column > .q-field > .q-field__inner > .q-field__control > .q-field__control-container'; - const getRowColumn = (row, column) => `:nth-child(${row}) > :nth-child(${column})`; it('Route list create route', () => { cy.addBtnClick(); @@ -16,18 +13,25 @@ describe('Route', () => { }); it('Route list search and edit', () => { - cy.get('#searchbar input').type('{enter}'); /* - cy.get('td[data-col-field="description"]').click(); */ - cy.get('input[name="description"]').type('routeTestOne{enter}'); - /* cy.get('.q-table tr') + cy.get('#searchbar input').type('{enter}'); + cy.get('[data-col-field="description"][data-row-index="0"]') + .click() + .type('routeTestOne{enter}'); + cy.get('.q-table tr') .its('length') .then((rowCount) => { expect(rowCount).to.be.greaterThan(0); }); - cy.get(getRowColumn(1, 3) + getVnSelect).type('{downArrow}{enter}'); - cy.get(getRowColumn(1, 4) + getVnSelect).type('{downArrow}{enter}'); - cy.get(getRowColumn(1, 5) + getVnSelect).type('{downArrow}{enter}'); + cy.get('[data-col-field="workerFk"][data-row-index="0"]') + .click() + .type('{downArrow}{enter}'); + cy.get('[data-col-field="agencyModeFk"][data-row-index="0"]') + .click() + .type('{downArrow}{enter}'); + cy.get('[data-col-field="vehicleFk"][data-row-index="0"]') + .click() + .type('{downArrow}{enter}'); cy.get('button[title="Save"]').click(); - cy.get('.q-notification__message').should('have.text', 'Data saved'); */ + cy.get('.q-notification__message').should('have.text', 'Data saved'); }); }); -- 2.40.1