refactor: refs #8684 enhance editability checks in VnTable and improve item request handling
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
ab6dc5d2ca
commit
240b927a02
|
@ -373,16 +373,20 @@ function handleSelection({ evt, added, rows: selectedRows }, rows) {
|
|||
}
|
||||
}
|
||||
|
||||
function isEditableColumn(column) {
|
||||
const isEditableCol = column?.isEditable ?? true;
|
||||
function isEditableColumn(column, row) {
|
||||
const isEditableCol =
|
||||
typeof column?.isEditable == 'function'
|
||||
? column?.isEditable(row)
|
||||
: (column?.isEditable ?? true);
|
||||
|
||||
const isVisible = column?.visible ?? true;
|
||||
const hasComponent = column?.component;
|
||||
|
||||
return $props.isEditable && isVisible && hasComponent && isEditableCol;
|
||||
}
|
||||
|
||||
function hasEditableFormat(column) {
|
||||
if (isEditableColumn(column)) return 'editable-text';
|
||||
function hasEditableFormat(column, row) {
|
||||
if (isEditableColumn(column, row)) return 'editable-text';
|
||||
}
|
||||
|
||||
const clickHandler = async (event) => {
|
||||
|
@ -394,6 +398,7 @@ const clickHandler = async (event) => {
|
|||
if (isDateElement || isTimeElement || isQSelectDropDown) return;
|
||||
|
||||
if (clickedElement === null) {
|
||||
console.log('destroyInput 1');
|
||||
await destroyInput(editingRow.value, editingField.value);
|
||||
return;
|
||||
}
|
||||
|
@ -404,17 +409,25 @@ 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);
|
||||
}
|
||||
|
||||
if (isEditableColumn(column)) {
|
||||
if (
|
||||
isEditableColumn(
|
||||
column,
|
||||
CrudModelRef.value.formData[rowIndex ?? editingRow.value],
|
||||
)
|
||||
) {
|
||||
await renderInput(Number(rowIndex), colField, clickedElement);
|
||||
}
|
||||
};
|
||||
|
||||
async function handleTabKey(event, rowIndex, colField) {
|
||||
if (editingRow.value == rowIndex && editingField.value == colField)
|
||||
if (editingRow.value == rowIndex && editingField.value == colField) {
|
||||
console.log('destroyInput 3');
|
||||
await destroyInput(editingRow.value, editingField.value);
|
||||
}
|
||||
|
||||
const direction = event.shiftKey ? -1 : 1;
|
||||
const { nextRowIndex, nextColumnName } = await handleTabNavigation(
|
||||
|
@ -426,6 +439,7 @@ 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);
|
||||
}
|
||||
|
||||
|
@ -467,16 +481,21 @@ async function renderInput(rowId, field, clickedElement) {
|
|||
await column?.cellEvent?.['update:modelValue']?.(value, oldValue, row);
|
||||
},
|
||||
keyup: async (event) => {
|
||||
if (event.key === 'Enter')
|
||||
if (event.key === 'Enter') {
|
||||
console.log('destroyInput 4');
|
||||
await destroyInput(rowId, field, clickedElement);
|
||||
}
|
||||
},
|
||||
keydown: async (event) => {
|
||||
switch (event.key) {
|
||||
case 'Tab':
|
||||
console.log('field: ', field);
|
||||
console.log('target: ', event.target);
|
||||
await handleTabKey(event, rowId, field);
|
||||
event.stopPropagation();
|
||||
break;
|
||||
case 'Escape':
|
||||
console.log('destroyInput 5');
|
||||
await destroyInput(rowId, field, clickedElement);
|
||||
break;
|
||||
default:
|
||||
|
@ -511,6 +530,10 @@ async function updateSelectValue(value, column, row, oldValue) {
|
|||
}
|
||||
|
||||
async function destroyInput(rowIndex, field, clickedElement) {
|
||||
const column = $props.columns.find((col) => col.name === field);
|
||||
if (typeof column?.beforeDestroy === 'function')
|
||||
await column.beforeDestroy(CrudModelRef.value.formData[rowIndex]);
|
||||
|
||||
if (!clickedElement)
|
||||
clickedElement = document.querySelector(
|
||||
`[data-row-index="${rowIndex}"][data-col-field="${field}"]`,
|
||||
|
@ -523,6 +546,7 @@ async function destroyInput(rowIndex, field, clickedElement) {
|
|||
child.style.position = '';
|
||||
});
|
||||
}
|
||||
|
||||
if (editingRow.value !== rowIndex || editingField.value !== field) return;
|
||||
editingRow.value = null;
|
||||
editingField.value = null;
|
||||
|
@ -540,7 +564,13 @@ async function handleTabNavigation(rowIndex, colName, direction) {
|
|||
iterations++;
|
||||
newColumnIndex = (newColumnIndex + direction + totalColumns) % totalColumns;
|
||||
|
||||
if (isEditableColumn(columns[newColumnIndex])) break;
|
||||
if (
|
||||
isEditableColumn(
|
||||
columns[newColumnIndex],
|
||||
CrudModelRef.value.formData[rowIndex],
|
||||
)
|
||||
)
|
||||
break;
|
||||
} while (iterations < totalColumns);
|
||||
|
||||
if (iterations >= totalColumns + 1) return;
|
||||
|
@ -840,19 +870,19 @@ const handleHeaderSelection = (evt, data) => {
|
|||
: getToggleIcon(row[col?.name])
|
||||
"
|
||||
style="color: var(--vn-text-color)"
|
||||
:class="hasEditableFormat(col)"
|
||||
:class="hasEditableFormat(col, row)"
|
||||
size="14px"
|
||||
/>
|
||||
<QIcon
|
||||
v-else-if="col?.component === 'checkbox'"
|
||||
:name="getCheckboxIcon(row[col?.name])"
|
||||
style="color: var(--vn-text-color)"
|
||||
:class="hasEditableFormat(col)"
|
||||
:class="hasEditableFormat(col, row)"
|
||||
size="14px"
|
||||
/>
|
||||
<span
|
||||
v-else
|
||||
:class="hasEditableFormat(col)"
|
||||
:class="hasEditableFormat(col, row)"
|
||||
:style="
|
||||
typeof col?.style == 'function'
|
||||
? col.style(row)
|
||||
|
|
|
@ -13,7 +13,6 @@ import DepartmentDescriptorProxy from 'src/pages/Worker/Department/Card/Departme
|
|||
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
|
||||
import ItemRequestFilter from './ItemRequestFilter.vue';
|
||||
import RightMenu from 'src/components/common/RightMenu.vue';
|
||||
import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
|
||||
import FormModelPopup from 'src/components/FormModelPopup.vue';
|
||||
import ItemDescriptorProxy from './Card/ItemDescriptorProxy.vue';
|
||||
import { dashIfEmpty } from 'src/filters';
|
||||
|
@ -23,8 +22,6 @@ const { notify } = useNotify();
|
|||
const stateStore = useStateStore();
|
||||
const denyFormRef = ref(null);
|
||||
const denyRequestId = ref(null);
|
||||
const denyRequestIndex = ref(null);
|
||||
const itemRequestsOptions = ref([]);
|
||||
const userParams = {
|
||||
state: 'pending',
|
||||
daysOnward: 7,
|
||||
|
@ -146,7 +143,24 @@ const columns = computed(() => [
|
|||
align: 'left',
|
||||
component: 'input',
|
||||
columnClass: 'shrink',
|
||||
cellEvent: {},
|
||||
isEditable: (row) => row?.itemFk,
|
||||
beforeDestroy: async ({ id, itemFk, saleQuantity, state }) => {
|
||||
if (!saleQuantity) {
|
||||
await tableRef.value.reload();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await axios.post(`TicketRequests/${id}/confirm`, {
|
||||
id,
|
||||
itemFk: parseInt(itemFk),
|
||||
quantity: parseInt(saleQuantity),
|
||||
});
|
||||
await tableRef.value.reload();
|
||||
} catch (error) {
|
||||
notify(error.response.data.error.message, 'negative');
|
||||
console.log('error: ', error);
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
label: t('item.buyRequest.concept'),
|
||||
|
|
|
@ -6,8 +6,7 @@ describe('Item summary', () => {
|
|||
});
|
||||
|
||||
it('should clone the item', () => {
|
||||
cy.dataCy('descriptor-more-opts').click();
|
||||
cy.get('.q-menu > .q-list > :nth-child(2) > .q-item__section').click();
|
||||
cy.selectDescriptorOption(2);
|
||||
cy.dataCy('VnConfirm_confirm').click();
|
||||
cy.waitForElement('[data-cy="itemTags"]');
|
||||
cy.dataCy('itemTags').should('be.visible');
|
|
@ -1,15 +1,14 @@
|
|||
describe('Item list', () => {
|
||||
beforeEach(() => {
|
||||
cy.login('developer');
|
||||
cy.login('buyer');
|
||||
cy.visit(`/#/item/list`);
|
||||
});
|
||||
|
||||
it('should filter the items and redirect to the summary', () => {
|
||||
cy.dataCy('Category_select').type('Plant');
|
||||
cy.get('.q-menu .q-item').contains('Plant').click();
|
||||
cy.dataCy('Type_select').type('Anthurium');
|
||||
cy.get('.q-menu .q-item').contains('Anthurium').click();
|
||||
cy.selectOption('[data-cy="Category_select"]', 'Plant');
|
||||
cy.selectOption('[data-cy="Type_select"]', 'Anthurium');
|
||||
cy.get('.q-virtual-scroll__content > :nth-child(4) > :nth-child(4)').click();
|
||||
cy.url().should('include', '/summary');
|
||||
});
|
||||
|
||||
it('should create an item', () => {
|
||||
|
@ -24,8 +23,6 @@ describe('Item list', () => {
|
|||
cy.fillInForm(data);
|
||||
cy.dataCy('FormModelPopup_save').click();
|
||||
cy.checkNotification('Data created');
|
||||
cy.get(
|
||||
':nth-child(2) > .q-drawer > .q-drawer__content > .q-scrollarea > .q-scrollarea__container > .q-scrollarea__content',
|
||||
).should('be.visible');
|
||||
cy.url().should('include', '/basic-data');
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue