refactor: refs #8684 improve input handling and rendering in VnTable enhance item request logic in ItemRequest
gitea/salix-front/pipeline/pr-dev This commit is unstable
Details
gitea/salix-front/pipeline/pr-dev This commit is unstable
Details
This commit is contained in:
parent
cb1fa3c7f5
commit
d64788732e
|
@ -110,7 +110,6 @@ const components = {
|
|||
component: markRaw(VnCheckbox),
|
||||
event: updateEvent,
|
||||
attrs: {
|
||||
class: $props.showTitle ? 'q-py-sm' : 'q-px-md q-py-xs fit',
|
||||
'toggle-indeterminate': true,
|
||||
size: 'sm',
|
||||
},
|
||||
|
|
|
@ -398,8 +398,7 @@ const clickHandler = async (event) => {
|
|||
if (isDateElement || isTimeElement || isQSelectDropDown) return;
|
||||
|
||||
if (clickedElement === null) {
|
||||
console.log('destroyInput 1');
|
||||
await destroyInput(editingRow.value, editingField.value);
|
||||
destroyInput(editingRow.value, editingField.value);
|
||||
return;
|
||||
}
|
||||
const rowIndex = clickedElement.getAttribute('data-row-index');
|
||||
|
@ -409,8 +408,7 @@ const clickHandler = async (event) => {
|
|||
if (editingRow.value !== null && editingField.value !== null) {
|
||||
if (editingRow.value == rowIndex && editingField.value == colField) return;
|
||||
|
||||
console.log('destroyInput 2');
|
||||
await destroyInput(editingRow.value, editingField.value);
|
||||
destroyInput(editingRow.value, editingField.value);
|
||||
}
|
||||
|
||||
if (
|
||||
|
@ -419,18 +417,16 @@ const clickHandler = async (event) => {
|
|||
CrudModelRef.value.formData[rowIndex ?? editingRow.value],
|
||||
)
|
||||
) {
|
||||
await renderInput(Number(rowIndex), colField, clickedElement);
|
||||
renderInput(Number(rowIndex), colField, clickedElement);
|
||||
}
|
||||
};
|
||||
|
||||
async function handleTabKey(event, rowIndex, colField) {
|
||||
if (editingRow.value == rowIndex && editingField.value == colField) {
|
||||
console.log('destroyInput 3');
|
||||
await destroyInput(editingRow.value, editingField.value);
|
||||
}
|
||||
function handleTabKey(event, rowIndex, colField) {
|
||||
if (editingRow.value == rowIndex && editingField.value == colField)
|
||||
destroyInput(editingRow.value, editingField.value);
|
||||
|
||||
const direction = event.shiftKey ? -1 : 1;
|
||||
const { nextRowIndex, nextColumnName } = await handleTabNavigation(
|
||||
const { nextRowIndex, nextColumnName } = handleTabNavigation(
|
||||
rowIndex,
|
||||
colField,
|
||||
direction,
|
||||
|
@ -439,11 +435,10 @@ async function handleTabKey(event, rowIndex, colField) {
|
|||
if (nextRowIndex < 0 || nextRowIndex >= arrayData.store.data.length) return;
|
||||
|
||||
event.preventDefault();
|
||||
console.log('nextColumnName: ', nextColumnName);
|
||||
await renderInput(nextRowIndex, nextColumnName, null);
|
||||
renderInput(nextRowIndex, nextColumnName, null);
|
||||
}
|
||||
|
||||
async function renderInput(rowId, field, clickedElement) {
|
||||
function renderInput(rowId, field, clickedElement) {
|
||||
editingField.value = field;
|
||||
editingRow.value = rowId;
|
||||
|
||||
|
@ -480,28 +475,20 @@ async function renderInput(rowId, field, clickedElement) {
|
|||
} else row[column.name] = value;
|
||||
await column?.cellEvent?.['update:modelValue']?.(value, oldValue, row);
|
||||
},
|
||||
keyup: async (event) => {
|
||||
keyup: (event) => {
|
||||
if (event.key === 'Enter') {
|
||||
console.log('destroyInput 4');
|
||||
await destroyInput(rowId, field, clickedElement);
|
||||
destroyInput(rowId, field, clickedElement);
|
||||
}
|
||||
},
|
||||
keydown: async (event) => {
|
||||
keydown: (event) => {
|
||||
switch (event.key) {
|
||||
case 'Tab':
|
||||
console.log('field: ', field);
|
||||
console.log('target: ', event.target);
|
||||
await handleTabKey(event, rowId, field);
|
||||
handleTabKey(event, rowId, field);
|
||||
event.stopPropagation();
|
||||
const column = $props.columns.find((col) => col.name === field);
|
||||
if (typeof column?.beforeDestroy === 'function')
|
||||
await column.beforeDestroy(
|
||||
CrudModelRef.value.formData[editingRow.value],
|
||||
);
|
||||
|
||||
break;
|
||||
case 'Escape':
|
||||
console.log('destroyInput 5');
|
||||
await destroyInput(rowId, field, clickedElement);
|
||||
destroyInput(rowId, field, clickedElement);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -534,17 +521,23 @@ async function updateSelectValue(value, column, row, oldValue) {
|
|||
await column?.cellEvent?.['update:modelValue']?.(value, oldValue, row);
|
||||
}
|
||||
|
||||
async function destroyInput(rowIndex, field, clickedElement) {
|
||||
function destroyInput(rowIndex, field, clickedElement) {
|
||||
if (!clickedElement)
|
||||
clickedElement = document.querySelector(
|
||||
`[data-row-index="${rowIndex}"][data-col-field="${field}"]`,
|
||||
);
|
||||
|
||||
if (clickedElement) {
|
||||
await nextTick();
|
||||
render(null, clickedElement);
|
||||
Array.from(clickedElement.childNodes).forEach((child) => {
|
||||
child.style.visibility = 'visible';
|
||||
child.style.position = '';
|
||||
const column = $props.columns.find((col) => col.name === field);
|
||||
if (typeof column?.beforeDestroy === 'function')
|
||||
column.beforeDestroy(CrudModelRef.value.formData[rowIndex]);
|
||||
|
||||
nextTick().then(() => {
|
||||
render(null, clickedElement);
|
||||
Array.from(clickedElement.childNodes).forEach((child) => {
|
||||
child.style.visibility = 'visible';
|
||||
child.style.position = '';
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -553,7 +546,7 @@ async function destroyInput(rowIndex, field, clickedElement) {
|
|||
editingField.value = null;
|
||||
}
|
||||
|
||||
async function handleTabNavigation(rowIndex, colName, direction) {
|
||||
function handleTabNavigation(rowIndex, colName, direction) {
|
||||
const columns = $props.columns;
|
||||
const totalColumns = columns.length;
|
||||
let currentColumnIndex = columns.findIndex((col) => col.name === colName);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script setup>
|
||||
import { ref, computed, onMounted } from 'vue';
|
||||
import { ref, computed, onMounted, nextTick } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useStateStore } from 'stores/useStateStore';
|
||||
import { toCurrency } from 'filters/index';
|
||||
|
@ -23,7 +23,6 @@ const stateStore = useStateStore();
|
|||
const denyFormRef = ref(null);
|
||||
const denyRequestId = ref(null);
|
||||
const userParams = {
|
||||
state: 'pending',
|
||||
daysOnward: 7,
|
||||
};
|
||||
const tableRef = ref();
|
||||
|
@ -136,6 +135,7 @@ const columns = computed(() => [
|
|||
align: 'left',
|
||||
component: 'input',
|
||||
columnClass: 'expand',
|
||||
isEditable: ({ isOk }) => isOk === null,
|
||||
},
|
||||
{
|
||||
label: t('item.buyRequest.achieved'),
|
||||
|
@ -143,22 +143,35 @@ const columns = computed(() => [
|
|||
align: 'left',
|
||||
component: 'input',
|
||||
columnClass: 'shrink',
|
||||
isEditable: (row) => row?.itemFk,
|
||||
beforeDestroy: async ({ id, itemFk, saleQuantity, state }) => {
|
||||
if (!saleQuantity) {
|
||||
await tableRef.value.reload();
|
||||
return;
|
||||
isEditable: ({ itemFk, isOk }) => {
|
||||
if (itemFk && isOk === null) return true;
|
||||
},
|
||||
beforeDestroy: (row) => {
|
||||
console.log('row: ', row);
|
||||
if (!row.saleQuantity) {
|
||||
return tableRef.value.reload();
|
||||
}
|
||||
try {
|
||||
await axios.post(`TicketRequests/${id}/confirm`, {
|
||||
id,
|
||||
itemFk: parseInt(itemFk),
|
||||
quantity: parseInt(saleQuantity),
|
||||
});
|
||||
await tableRef.value.reload();
|
||||
axios
|
||||
.post(`TicketRequests/${row.id}/confirm`, {
|
||||
id: row.id,
|
||||
itemFk: parseInt(row.itemFk),
|
||||
quantity: parseInt(row.saleQuantity),
|
||||
})
|
||||
.then(() => {
|
||||
axios
|
||||
.get(`Items/findOne`, { where: { id: row.itemFk } })
|
||||
.then((response) => {
|
||||
console.log('response: ', response);
|
||||
row.itemDescription = response.data.name;
|
||||
row.state = 1;
|
||||
});
|
||||
notify(t('globals.dataSaved'), 'positive');
|
||||
return tableRef.value.reload();
|
||||
});
|
||||
} catch (error) {
|
||||
notify(error.response.data.error.message, 'negative');
|
||||
await tableRef.value.reload();
|
||||
return tableRef.value.reload();
|
||||
}
|
||||
},
|
||||
},
|
||||
|
@ -174,7 +187,7 @@ const columns = computed(() => [
|
|||
{
|
||||
label: t('globals.state'),
|
||||
name: 'state',
|
||||
format: (row) => getState(row.isOk),
|
||||
format: ({ isOk }) => getState(isOk),
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
|
@ -202,6 +215,7 @@ const columns = computed(() => [
|
|||
icon: 'thumb_down',
|
||||
fill: true,
|
||||
isPrimary: true,
|
||||
show: ({ isOk }) => isOk === null,
|
||||
action: (row) => showDenyRequestForm(row.id),
|
||||
},
|
||||
],
|
||||
|
@ -309,7 +323,8 @@ const showDenyRequestForm = (requestId) => {
|
|||
v-model="data.observation"
|
||||
fill-input
|
||||
:required="true"
|
||||
autogrow
|
||||
auto-grow
|
||||
data-cy="discardTextArea"
|
||||
/>
|
||||
</template>
|
||||
</FormModelPopup>
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
describe('Item Request', () => {
|
||||
beforeEach(() => {
|
||||
cy.login('buyer');
|
||||
cy.visit(`/#/item/request`);
|
||||
});
|
||||
|
||||
it('should fill the id and quantity then check the concept was updated', async () => {
|
||||
cy.get('td[data-row-index="0"][data-col-field="itemFk"]')
|
||||
.should('exist')
|
||||
.type('4');
|
||||
cy.get('td[data-row-index="0"][data-col-field="saleQuantity"]')
|
||||
.should('exist')
|
||||
.type('10{esc}');
|
||||
cy.checkNotification('Data saved');
|
||||
});
|
||||
it('should now click on the second declain request icon then type the reason', async () => {
|
||||
cy.selectOption('[data-cy="State_select"]', 'Pending');
|
||||
cy.get('button[title="Discard"]').eq(0).click();
|
||||
cy.dataCy('discardTextArea').should('exist').type('test(enter)');
|
||||
cy.checkNotification('Data saved');
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue