feat: refs #8406 "add" button on a bottom bar in CrudModel
gitea/salix-front/pipeline/pr-dev This commit looks good Details

This commit is contained in:
Pau Rovira 2025-04-16 14:58:18 +02:00
parent 36d306e827
commit d838d9b55a
12 changed files with 52 additions and 10 deletions

View File

@ -50,7 +50,7 @@ const $props = defineProps({
}, },
insertOnLoad: { insertOnLoad: {
type: Boolean, type: Boolean,
default: true, default: false,
}, },
defaultSave: { defaultSave: {
type: Boolean, type: Boolean,
@ -64,6 +64,10 @@ const $props = defineProps({
type: Boolean, type: Boolean,
default: true, default: true,
}, },
defaultAdd: {
type: Boolean,
default: false,
},
selected: { selected: {
type: Object, type: Object,
default: null, default: null,
@ -96,7 +100,6 @@ const saveButtonRef = ref(null);
const watchChanges = ref(); const watchChanges = ref();
let isNotEqual = ref(false); let isNotEqual = ref(false);
let isLastRowEmpty = ref(false); let isLastRowEmpty = ref(false);
const isFirstFetch = ref(true);
const formUrl = computed(() => $props.url); const formUrl = computed(() => $props.url);
const rowsContainer = ref(null); const rowsContainer = ref(null);
@ -134,10 +137,9 @@ async function fetch(data) {
const rows = keyData ? data[keyData] : data; const rows = keyData ? data[keyData] : data;
resetData(rows); resetData(rows);
emit('onFetch', rows); emit('onFetch', rows);
if (isFirstFetch.value && $props.insertOnLoad) { if ($props.insertOnLoad) {
await insert(); await insert();
} }
isFirstFetch.value = false;
return rows; return rows;
} }
@ -338,9 +340,16 @@ function removeIndexField(data) {
} }
async function handleTab(event) { async function handleTab(event) {
const focusableElements = rowsContainer.value?.querySelectorAll( if (event.target.classList.contains('q-checkbox__input') ||
'input, select, textarea, [tabindex]:not([tabindex="-1"]), .q-field__native, .q-checkbox__input' event.target.type === 'checkbox' ||
event.target.closest('.q-checkbox')) {
return;
}
const focusableElements = rowsContainer.value?.querySelectorAll(
'input:not([type="checkbox"]), select, textarea, [tabindex]:not([tabindex="-1"]):not(.q-checkbox__input), .q-field__native'
); );
if (!focusableElements || focusableElements.length === 0) return; if (!focusableElements || focusableElements.length === 0) return;
const lastElement = focusableElements[focusableElements.length - 1]; const lastElement = focusableElements[focusableElements.length - 1];
@ -348,7 +357,7 @@ async function handleTab(event) {
event.preventDefault(); event.preventDefault();
await insert(); await insert();
await nextTick(); await nextTick();
const newElements = rowsContainer.value.querySelectorAll('input, select, textarea, [tabindex]:not([tabindex="-1"])'); const newElements = rowsContainer.value.querySelectorAll('input:not([type="checkbox"]), select, textarea, [tabindex]:not([tabindex="-1"]):not(.q-checkbox__input)');
if (newElements.length > focusableElements.length) { if (newElements.length > focusableElements.length) {
newElements[newElements.length - 1].focus(); newElements[newElements.length - 1].focus();
} }
@ -376,7 +385,7 @@ watch(formUrl, async () => {
v-bind="$attrs" v-bind="$attrs"
> >
<template #body v-if="formData"> <template #body v-if="formData">
<div ref="rowsContainer" @keydown.tab.prevent="handleTab"> <div ref="rowsContainer" @keydown.tab="handleTab">
<slot <slot
name="body" name="body"
:rows="formData" :rows="formData"
@ -467,4 +476,16 @@ watch(formUrl, async () => {
:label="t && t('globals.pleaseWait')" :label="t && t('globals.pleaseWait')"
color="primary" color="primary"
/> />
<div class=" bottomButton" v-if="defaultAdd">
<QBtn
@click="insert()"
class="cursor-pointer fill-icon"
color="primary"
icon="add_circle"
size="md"
round
flat
v-shortcut="'+'"
/>
</div>
</template> </template>

View File

@ -138,6 +138,8 @@ const columns = computed(() => [
:filter="developmentsFilter" :filter="developmentsFilter"
ref="claimDevelopmentForm" ref="claimDevelopmentForm"
:data-required="{ claimFk: route.params.id }" :data-required="{ claimFk: route.params.id }"
:defaultAdd="true"
:insert-on-load="true"
v-model:selected="selected" v-model:selected="selected"
@save-changes="$router.push(`/claim/${route.params.id}/action`)" @save-changes="$router.push(`/claim/${route.params.id}/action`)"
:default-save="false" :default-save="false"

View File

@ -89,7 +89,8 @@ onBeforeMount(async () => await setTaxableBase());
data-key="InvoiceInDueDays" data-key="InvoiceInDueDays"
url="InvoiceInDueDays" url="InvoiceInDueDays"
:filter="filter" :filter="filter"
:insert-on-load="false" :insert-on-load="true"
:default-add="true"
auto-load auto-load
:data-required="{ invoiceInFk: invoiceId }" :data-required="{ invoiceInFk: invoiceId }"
v-model:selected="rowsSelected" v-model:selected="rowsSelected"

View File

@ -89,7 +89,9 @@ const columns = computed(() => [
url="InvoiceInIntrastats" url="InvoiceInIntrastats"
auto-load auto-load
:data-required="{ invoiceInFk: invoiceInId }" :data-required="{ invoiceInFk: invoiceInId }"
:default-add="true"
:filter="filter" :filter="filter"
:insert-on-load="true"
v-model:selected="rowsSelected" v-model:selected="rowsSelected"
@on-fetch="(data) => (invoceInIntrastat = data)" @on-fetch="(data) => (invoceInIntrastat = data)"
> >

View File

@ -187,6 +187,8 @@ function setCursor(ref) {
url="InvoiceInTaxes" url="InvoiceInTaxes"
:filter="filter" :filter="filter"
:data-required="{ invoiceInFk: $route.params.id }" :data-required="{ invoiceInFk: $route.params.id }"
:default-add="true"
:insert-on-load="true"
auto-load auto-load
v-model:selected="rowsSelected" v-model:selected="rowsSelected"
:go-to="`/invoice-in/${$route.params.id}/due-day`" :go-to="`/invoice-in/${$route.params.id}/due-day`"

View File

@ -51,6 +51,7 @@ const submit = async (rows) => {
<CrudModel <CrudModel
:data-required="{ itemFk: route.params.id }" :data-required="{ itemFk: route.params.id }"
:default-remove="false" :default-remove="false"
:insert-on-load="true"
:filter="{ :filter="{
fields: ['id', 'itemFk', 'code'], fields: ['id', 'itemFk', 'code'],
where: { itemFk: route.params.id }, where: { itemFk: route.params.id },

View File

@ -58,7 +58,6 @@ const submitTaxes = async (data) => {
:save-fn="submitTaxes" :save-fn="submitTaxes"
:filter="taxesFilter" :filter="taxesFilter"
:default-remove="false" :default-remove="false"
:insert-on-load="false"
data-key="ItemTax" data-key="ItemTax"
model="ItemTax" model="ItemTax"
ref="ItemTaxRef" ref="ItemTaxRef"

View File

@ -181,6 +181,7 @@ function beforeSave(data) {
model="TicketService" model="TicketService"
:filter="crudModelFilter" :filter="crudModelFilter"
:data-required="crudModelRequiredData" :data-required="crudModelRequiredData"
:default-add="true"
auto-load auto-load
v-model:selected="selected" v-model:selected="selected"
:order="['description ASC']" :order="['description ASC']"

View File

@ -99,6 +99,10 @@ const columns = computed(() => [
workerFk: entityId, workerFk: entityId,
}, },
}" }"
:crud-model="{
insertOnLoad: false,
}"
order="paymentDate DESC" order="paymentDate DESC"
:columns="columns" :columns="columns"
auto-load auto-load

View File

@ -128,6 +128,9 @@ const columns = computed(() => [
workerFk: entityId, workerFk: entityId,
}, },
}" }"
:crud-model="{
insertOnLoad: false,
}"
order="id DESC" order="id DESC"
:columns="columns" :columns="columns"
auto-load auto-load

View File

@ -109,6 +109,9 @@ const columns = [
workerFk: entityId, workerFk: entityId,
}, },
}" }"
:crud-model="{
insertOnLoad: false,
}"
order="date DESC" order="date DESC"
:columns="columns" :columns="columns"
auto-load auto-load

View File

@ -170,6 +170,9 @@ function isSigned(row) {
'row-key': 'deviceProductionFk', 'row-key': 'deviceProductionFk',
selection: 'multiple', selection: 'multiple',
}" }"
:crud-model="{
insertOnLoad: false,
}"
:table-filter="{ hiddenTags: ['userFk'] }" :table-filter="{ hiddenTags: ['userFk'] }"
> >
<template #moreBeforeActions> <template #moreBeforeActions>