0
0
Fork 0

feat: refs #6825 VnTableFilter and VnPanelFilter init

This commit is contained in:
Alex Moreno 2024-05-03 15:03:54 +02:00
parent 0fe957db80
commit b76b2fd8a0
6 changed files with 280 additions and 72 deletions

View File

@ -1,11 +1,17 @@
<script setup>
import { ref, onMounted, computed } from 'vue';
import { useQuasar } from 'quasar';
import { useI18n } from 'vue-i18n';
import { useQuasar } from 'quasar';
import { useStateStore } from 'stores/useStateStore';
import VnPaginate from 'components/ui/VnPaginate.vue';
import VnFilterPanel from 'components/ui/VnFilterPanel.vue';
import VnLv from 'components/ui/VnLv.vue';
import VnBreadcrumbs from 'components/common/VnBreadcrumbs.vue';
import VnTableColumn from 'src/components/common/VnTableColumn.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import VnTableColumn from 'components/common/VnTableColumn.vue';
import VnTableFilter from 'components/common/VnTableFilter.vue';
const $props = defineProps({
columns: {
@ -35,8 +41,11 @@ const $props = defineProps({
});
const { t } = useI18n();
const $q = useQuasar();
const stateStore = useStateStore();
const mode = ref('list');
const selected = ref([]);
const filters = ref({});
const tableModes = computed(() => {
const modes = [
{
@ -60,25 +69,38 @@ const tableModes = computed(() => {
return modes;
});
// {
// isId: Boolean
// align: 'left',
// field: 'hasFile',
// label: t('globals.original'),
// name: 'hasFile',
// component: QCheckbox ?? span,
// cardVisible: Boolean
// props: (prop) => ({
// disable: true,
// 'model-value': Boolean(prop.value),
// }),
// },
// vnTableOpitons y hacer bucle
onMounted(() => {
mode.value = $props.defaultMode;
stateStore.rightDrawer = true;
});
function columnsCard(cols) {
return Object.values(cols).filter(
(col) => col.cardVisible && !col.isId && col.field != 'tableActions'
);
}
</script>
<template>
<QDrawer v-model="stateStore.rightDrawer" side="right" :width="256" show-if-above>
<QScrollArea class="fit text-grey-8">
<VnFilterPanel
:data-key="$attrs['data-key']"
:search-button="true"
:params="filters"
>
<template #body>
<VnTableFilter
:column="col"
:data-key="$attrs['data-key']"
v-for="col of columns"
:key="col.id"
v-model="filters[col.field]"
/>
</template>
</VnFilterPanel>
</QScrollArea>
</QDrawer>
<VnPaginate v-bind="$attrs" class="q-px-md">
<template #body="{ rows }">
<!-- :grid="($q.screen.lt.md && reponsive) || mode != 'table'" -->
@ -118,42 +140,45 @@ onMounted(() => {
dense
:options="tableModes"
/>
<QBtn icon="filter_alt" title="asd" class="bg-dark q-ml-md" dense />
</template>
<!-- VnTableColumn¿?-->
<template #header-cell="{ col }">
<QTh auto-width>
<div class="q-pa-sm" :class="`text-${col.align ?? 'left'}`">
{{ col.label }}
</div>
<hr class="q-ma-none divisor-line" />
<QInput
v-if="columnSearch"
<QBtn
icon="filter_alt"
title="asd"
class="bg-dark q-ml-md"
dense
:type="col.component == 'number' ? 'number' : 'text'"
class="q-px-md q-pb-xs"
@click="stateStore.toggleRightDrawer()"
/>
</template>
<template #header-cell="{ col }">
<QTh auto-width style="min-width: 100px">
<VnTableFilter
:column="col"
:show-title="true"
:data-key="$attrs['data-key']"
v-model="filters[col.field]"
/>
</QTh>
</template>
<template #body-cell="{ row, col }">
<template #body-cell="{ col, row }">
<!-- Columns -->
<QTd auto-width :class="`text-${col.align ?? 'left'}`">
<VnTableColumn :column="col" :row />
<VnTableColumn :column="col" :row="row" />
</QTd>
</template>
<template #item="{ row, colsMap }">
<TransitionGroup name="grid" tag="div" class="grid">
<QCard bordered flat>
<QCardSection horizontal>
<span v-for="(col, index) of colsMap" :key="col.field">
{{ index }}
<!-- <TransitionGroup name="grid" tag="div" class="grid"> -->
<QCard bordered flat class="row no-wrap justify-between">
<QCardSection vertical class="no-margin no-padding w-80">
<!-- Chips -->
<QCardSection horizontal class="w-80">
<span v-for="col of colsMap" :key="col.field">
<QChip
:class="
col.color
? col.color(row)
: col.isId == 1
? 'bg-primary-light'
: 'bg-secondary'
: 'bg-chip-secondary'
"
square
v-if="col.isId"
@ -164,9 +189,16 @@ onMounted(() => {
</QChip>
</span>
</QCardSection>
<QCardSection class="row justify-between q-pa-sm">
<div>
<div v-for="col of colsMap" :key="col.field">
<!-- Fields -->
<QCardSection
class="q-pa-sm w-80"
:class="
mode == 'list' || $q.screen.lt.md
? 'grid-three'
: 'grid-one'
"
>
<div v-for="col of columnsCard(colsMap)" :key="col.field">
<div
v-if="
col.cardVisible &&
@ -181,24 +213,27 @@ onMounted(() => {
</VnLv>
</div>
</div>
</div>
<div v-if="colsMap.tableActions" class="column">
</QCardSection>
</QCardSection>
<!-- Actions -->
<QCardSection
v-if="colsMap.tableActions"
class="column flex-center w-10 no-margin q-pa-xs q-gutter-y-xs"
>
<QBtn
v-for="(btn, index) of colsMap.tableActions
.actions"
v-for="(btn, index) of colsMap.tableActions.actions"
:key="index"
:title="btn.title"
:icon="btn.icon"
:outline="!btn.isPrimary"
size="sm"
class="q-pa-sm q-mb-sm"
class="q-pa-sm"
:class="{ 'bg-primary-light': btn.isPrimary }"
@click.stop="btn.action(row)"
/>
</div>
</QCardSection>
</QCard>
</TransitionGroup>
<!-- </TransitionGroup> -->
</template>
</QTable>
</template>
@ -213,7 +248,7 @@ onMounted(() => {
color: var(--vn-section-color);
}
.bg-secondary {
.bg-chip-secondary {
background-color: var(--vn-page-color);
color: var(--vn-text-colo);
}
@ -308,4 +343,12 @@ onMounted(() => {
display: flex;
flex-direction: row;
}
.w-80 {
width: 80%;
}
.w-20 {
width: 20%;
}
</style>

View File

@ -0,0 +1,108 @@
<template>
<div
v-if="showTitle && column"
class="q-pt-sm q-px-sm ellipsis"
:class="`text-${column.align ?? 'left'}`"
>
{{ column.label }}
</div>
<div
v-if="columnFilter !== false && column.field != 'tableActions'"
class="row no-wrap"
>
<hr class="q-ma-none divisor-line" v-if="showTitle" />
<component
v-if="columnFilter?.component"
:is="isBasicComponent?.component ?? columnFilter.component"
v-model="model"
v-bind="columnFilter.attrs"
v-on="isBasicComponent?.event ?? columnFilter.event"
dense
/>
<span v-else class="full-width">
<QInput
v-model="model"
dense
class="q-px-sm q-pb-xs q-pt-none"
:label="showTitle ? '' : column.label"
@keyup.enter="addFilter"
>
<template #append> </template>
</QInput>
</span>
</div>
<div v-else-if="showTitle" style="height: 45px"><!-- fixme! --></div>
</template>
<script setup>
import { markRaw, computed, defineModel } from 'vue';
import { QCheckbox } from 'quasar';
import { useArrayData } from 'composables/useArrayData';
/* basic input */
import VnSelect from 'components/common/VnSelect.vue';
import VnInput from 'components/common/VnInput.vue';
import VnInputDate from 'components/common/VnInputDate.vue';
const $props = defineProps({
column: {
type: Object,
required: true,
},
showTitle: {
type: Boolean,
default: false,
},
dataKey: {
type: String,
required: true,
},
addModel: {
type: Object,
default: () => {},
},
});
const model = defineModel();
const arrayData = useArrayData($props.dataKey);
const columnFilter = computed(() => $props.column?.columnFilter);
const isBasicComponent = computed(
() => components[$props.column?.columnFilter?.component]
);
const updateEvent = { 'update:modelValue': addFilter };
const enterEvent = { 'keyup.enter': addFilter };
const components = {
input: {
component: markRaw(VnInput),
event: enterEvent,
},
number: {
component: markRaw(VnInput),
event: enterEvent,
},
date: {
component: markRaw(VnInputDate),
event: updateEvent,
},
checkbox: {
component: markRaw(QCheckbox),
event: updateEvent,
},
select: {
component: markRaw(VnSelect),
event: updateEvent,
},
};
async function addFilter() {
const value = model.value == '' ? null : model.value;
const prefix = columnFilter.value?.inWhere?.prefix;
let field = columnFilter.value?.field ?? $props.column.field;
field = prefix ? prefix + '.' + field : field;
const toFilter = { [field]: value };
const filter = columnFilter.value?.inWhere
? { filter: { where: toFilter } }
: { params: toFilter };
await arrayData.addFilter(filter);
}
</script>

View File

@ -0,0 +1,13 @@
<template>
<QSelect dense icon="filter_alt" flat size="xs" :options="filterOptions"> </QSelect>
</template>
<script setup>
const model = defineModel();
const filterOptions = [{ label: '%' }, { label: '<' }, { label: '>' }];
async function encapsulate(field) {
// ejemplo
// si es % que te ponga {like: `%${field}%`}
}
</script>

View File

@ -0,0 +1,33 @@
// {
// isId: Boolean
// align: 'left',
// field: 'hasFile',
// label: t('globals.original'),
// name: 'hasFile',
// component: QCheckbox ?? span,
// cardVisible: Boolean
// isId: 1/2
// color: function
// props: (prop) => ({
// disable: true,
// 'model-value': Boolean(prop.value),
// }),
// tableActions: {
// field: 'tableActions',
// name: 'tableActions',
// actions: [
// {
// title: t('Client ticket list'),
// icon: 'vn:ticket',
// action: redirectToCreateView,
// isPrimary: true,
// },
// {
// title: t('Client ticket list'),
// icon: 'preview',
// action: (row) => viewSummary(row.id, CustomerSummary),
// },
// ],
// },
// },
// tableActions y hacer bucle

View File

@ -62,6 +62,8 @@ onMounted(() => {
if (Object.keys(store.userParams).length > 0) {
userParams.value = JSON.parse(JSON.stringify(store.userParams));
}
console.log('userParams.value: ', userParams.value);
emit('init', { params: userParams.value });
});
@ -165,7 +167,7 @@ function formatValue(value) {
</script>
<template>
<QForm @submit="search" id="filterPanelForm">
<div id="filterPanelForm">
<QList dense>
<QItem class="q-mt-xs">
<QItemSection top>
@ -255,7 +257,7 @@ function formatValue(value) {
</QItem>
<QSeparator />
</template>
</QForm>
</div>
<QInnerLoading
:label="t('globals.pleaseWait')"
:showing="isLoading"

View File

@ -265,6 +265,7 @@ const columns = computed(() => [
field: 'customerStatus',
label: 'customerStatus',
name: 'customerStatus',
columnFilter: false,
},
{
align: 'left',
@ -272,6 +273,9 @@ const columns = computed(() => [
label: t('customer.extendedList.tableVisibleColumns.id'),
name: 'id',
isId: 1,
columnFilter: {
field: 'search',
},
},
{
align: 'left',
@ -279,6 +283,11 @@ const columns = computed(() => [
label: t('customer.extendedList.tableVisibleColumns.name'),
name: 'name',
isId: 2,
columnFilter: {
inWhere: {
prefix: 'c',
},
},
},
{
align: 'left',