#6825 - VnTable V1 #396

Merged
alexm merged 73 commits from 6825-vnTable into dev 2024-06-20 13:08:55 +00:00
6 changed files with 280 additions and 72 deletions
Showing only changes of commit b76b2fd8a0 - Show all commits

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 />
<QBtn
icon="filter_alt"
title="asd"
class="bg-dark q-ml-md"
dense
@click="stateStore.toggleRightDrawer()"
/>
</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"
dense
:type="col.component == 'number' ? 'number' : 'text'"
class="q-px-md q-pb-xs"
<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,41 +189,51 @@ onMounted(() => {
</QChip>
</span>
</QCardSection>
<QCardSection class="row justify-between q-pa-sm">
<div>
<div v-for="col of colsMap" :key="col.field">
<div
v-if="
col.cardVisible &&
!col.isId &&
col.field != 'tableActions'
"
>
<VnLv :label="`${col.label}:`">
<template #value>
<VnTableColumn :column="col" :row />
</template>
</VnLv>
</div>
<!-- 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 &&
!col.isId &&
col.field != 'tableActions'
"
>
<VnLv :label="`${col.label}:`">
<template #value>
<VnTableColumn :column="col" :row />
</template>
</VnLv>
</div>
</div>
<div v-if="colsMap.tableActions" class="column">
<QBtn
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="{ 'bg-primary-light': btn.isPrimary }"
@click.stop="btn.action(row)"
/>
</div>
</QCardSection>
</QCard>
</TransitionGroup>
</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"
:key="index"
:title="btn.title"
:icon="btn.icon"
:outline="!btn.isPrimary"
size="sm"
class="q-pa-sm"
:class="{ 'bg-primary-light': btn.isPrimary }"
@click.stop="btn.action(row)"
/>
</QCardSection>
</QCard>
<!-- </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">
Review

Si la operacion ternaria es para el valor de la traducción, porque no ponerla dentro de la funcion t?

Otra cosa es, hacen falta las traducciones? Porque en globals tenemos yes y no

Si la operacion ternaria es para el valor de la traducción, porque no ponerla dentro de la funcion t? Otra cosa es, hacen falta las traducciones? Porque en globals tenemos yes y no
<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',