feat: refs #8406 added new insertion with tabulation
gitea/salix-front/pipeline/pr-dev There was a failure building this commit
Details
gitea/salix-front/pipeline/pr-dev There was a failure building this commit
Details
This commit is contained in:
parent
5b42e97d83
commit
87c1c16d26
|
@ -1,6 +1,6 @@
|
|||
<script setup>
|
||||
import axios from 'axios';
|
||||
import { computed, ref, useAttrs, watch } from 'vue';
|
||||
import { computed, ref, useAttrs, watch, nextTick } from 'vue';
|
||||
import { useRouter, onBeforeRouteLeave } from 'vue-router';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useQuasar } from 'quasar';
|
||||
|
@ -98,6 +98,7 @@ let isNotEqual = ref(false);
|
|||
let isLastRowEmpty = ref(false);
|
||||
const isFirstFetch = ref(true);
|
||||
const formUrl = computed(() => $props.url);
|
||||
const rowsContainer = ref(null);
|
||||
|
||||
const emit = defineEmits(['onFetch', 'update:selected', 'saveChanges']);
|
||||
|
||||
|
@ -148,25 +149,17 @@ function resetData(data) {
|
|||
data.map((d) => (d.$index = $index++));
|
||||
}
|
||||
originalData.value = JSON.parse(JSON.stringify(data));
|
||||
|
||||
formData.value = JSON.parse(JSON.stringify(data));
|
||||
|
||||
if (watchChanges.value) watchChanges.value(); //destroy watcher
|
||||
watchChanges.value = watch(formData, (nVal) => {
|
||||
hasChanges.value = false;
|
||||
for(let index = 0; index < nVal.length; index++) {
|
||||
const curRow = nVal[index];
|
||||
const originalRow = originalData.value[index];
|
||||
if(originalRow && JSON.stringify(removeIndexField(curRow)) == JSON.stringify(removeIndexField(originalRow))) continue;
|
||||
for(const key in curRow) {
|
||||
if(key == '$index') continue;
|
||||
if(Object.hasOwn($props.dataRequired || {}, key)) continue;
|
||||
if(curRow[key]) {
|
||||
hasChanges.value = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
const filteredNewData = nVal.filter(row => !isRowEmpty(row) || row[$props.primaryKey]);
|
||||
const filteredOriginal = originalData.value.filter(row => row[$props.primaryKey]);
|
||||
|
||||
const changes = getDifferences(filteredOriginal, filteredNewData);
|
||||
hasChanges.value = !isEmpty(changes);
|
||||
|
||||
}, { deep: true });
|
||||
}
|
||||
async function reset() {
|
||||
|
@ -237,21 +230,23 @@ async function saveChanges(data) {
|
|||
}
|
||||
|
||||
async function insert(pushData = { ...$props.dataRequired, ...$props.dataDefault }) {
|
||||
const lastRow = formData.value.at(-1);
|
||||
const $index = lastRow?.$index >= 0 ? lastRow.$index + 1 : 0;
|
||||
isNotEqual = JSON.stringify(removeIndexField(formData.value)) !== JSON.stringify(removeIndexField(originalData.value));
|
||||
isLastRowEmpty = checkLastRow(lastRow);
|
||||
if (isNotEqual && isLastRowEmpty) return;
|
||||
formData.value = formData.value.filter(row => !isRowEmpty(row));
|
||||
|
||||
const lastRow = formData.value.at(-1);
|
||||
const isLastRowEmpty = lastRow ? isRowEmpty(lastRow) : false;
|
||||
|
||||
if (formData.value.length > 0 && isLastRowEmpty) return;
|
||||
const $index = formData.value.length ? formData.value.at(-1).$index + 1 : 0;
|
||||
|
||||
const nRow = Object.assign({ $index }, pushData);
|
||||
formData.value.push(nRow);
|
||||
for (const key in nRow) {
|
||||
if (isChange(nRow, key)) continue;
|
||||
else {
|
||||
hasChanges.value = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const hasChange = Object.keys(nRow).some(key => !isChange(nRow, key));
|
||||
if (hasChange) hasChanges.value = true;
|
||||
}
|
||||
|
||||
function isRowEmpty(row) {
|
||||
return Object.keys(row).every(key => isChange(row, key));
|
||||
}
|
||||
|
||||
|
||||
|
@ -259,13 +254,7 @@ function isChange(row,key){
|
|||
return !row[key] || key == '$index' || Object.hasOwn($props.dataRequired || {}, key);
|
||||
}
|
||||
|
||||
function checkLastRow(lastRow) {
|
||||
for (const key in lastRow) {
|
||||
if (isChange(lastRow, key)) continue;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
async function remove(data) {
|
||||
if (!data.length)
|
||||
return quasar.notify({
|
||||
|
@ -275,17 +264,15 @@ async function remove(data) {
|
|||
|
||||
const pk = $props.primaryKey;
|
||||
let ids = data.map((d) => d[pk]).filter(Boolean);
|
||||
let preRemove = data.map((d) => (d[pk] ? null : d.$index)).filter(index => index !== null && index !== undefined);
|
||||
let preRemove = data.map((d) => (d[pk] ? null : d.$index)).filter(Boolean);
|
||||
let newData = formData.value;
|
||||
|
||||
if (preRemove.length) {
|
||||
newData = newData.filter(
|
||||
(form) => !preRemove.some((index) => index == form.$index),
|
||||
);
|
||||
const changes = getChanges();
|
||||
if (!changes.creates?.length && !changes.updates?.length)
|
||||
hasChanges.value = false;
|
||||
fetch(newData);
|
||||
formData.value = newData;
|
||||
hasChanges.value = JSON.stringify(removeIndexField(formData.value)) !== JSON.stringify(removeIndexField(originalData.value));
|
||||
}
|
||||
if (ids.length) {
|
||||
quasar
|
||||
|
@ -303,23 +290,7 @@ async function remove(data) {
|
|||
newData = newData.filter((form) => !ids.some((id) => id == form[pk]));
|
||||
fetch(newData);
|
||||
});
|
||||
} else {
|
||||
await fetch(formData.value);
|
||||
hasChanges.value = false;
|
||||
|
||||
const lastRow = formData.value.at(-1);
|
||||
|
||||
const limitedFormData = formData.value.slice(0, originalData.value.length);
|
||||
isNotEqual = JSON.stringify(removeIndexField(limitedFormData)) !== JSON.stringify(removeIndexField(originalData.value));
|
||||
|
||||
const additionalRows = formData.value.slice(originalData.value.length);
|
||||
const hasNonEmptyAdditionalRows = additionalRows.some(row => !checkLastRow(row));
|
||||
|
||||
|
||||
if (isNotEqual || hasNonEmptyAdditionalRows) {
|
||||
hasChanges.value = true;
|
||||
}
|
||||
}
|
||||
|
||||
emit('update:selected', []);
|
||||
}
|
||||
|
@ -366,6 +337,23 @@ function removeIndexField(data) {
|
|||
}
|
||||
}
|
||||
|
||||
async function handleTab(event) {
|
||||
const focusableElements = rowsContainer.value?.querySelectorAll(
|
||||
'input, select, textarea, [tabindex]:not([tabindex="-1"]), .q-field__native, .q-checkbox__input'
|
||||
);
|
||||
if (!focusableElements || focusableElements.length === 0) return;
|
||||
|
||||
const lastElement = focusableElements[focusableElements.length - 1];
|
||||
if (event.target === lastElement) {
|
||||
event.preventDefault();
|
||||
await insert();
|
||||
await nextTick();
|
||||
const newElements = rowsContainer.value.querySelectorAll('input, select, textarea, [tabindex]:not([tabindex="-1"])');
|
||||
if (newElements.length > focusableElements.length) {
|
||||
newElements[newElements.length - 1].focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function reload(params) {
|
||||
const data = await vnPaginateRef.value.fetch(params);
|
||||
|
@ -388,12 +376,14 @@ watch(formUrl, async () => {
|
|||
v-bind="$attrs"
|
||||
>
|
||||
<template #body v-if="formData">
|
||||
<slot
|
||||
name="body"
|
||||
:rows="formData"
|
||||
:validate="validate"
|
||||
:filter="filter"
|
||||
></slot>
|
||||
<div ref="rowsContainer" @keydown.tab.prevent="handleTab">
|
||||
<slot
|
||||
name="body"
|
||||
:rows="formData"
|
||||
:validate="validate"
|
||||
:filter="filter"
|
||||
></slot>
|
||||
</div>
|
||||
</template>
|
||||
</VnPaginate>
|
||||
<SkeletonTable
|
||||
|
|
|
@ -174,6 +174,7 @@ const setUserParams = (params) => {
|
|||
:create="false"
|
||||
:crud-model="{
|
||||
disableInfiniteScroll: true,
|
||||
insertOnLoad: false,
|
||||
}"
|
||||
:table="{
|
||||
'row-key': 'itemFk',
|
||||
|
|
Loading…
Reference in New Issue