0
0
Fork 0

feat: refs #8224 wip

This commit is contained in:
William Buezas 2024-11-26 20:59:46 -03:00
parent 9086b7d48d
commit df8cd3dd55
6 changed files with 382 additions and 7 deletions

View File

@ -15,6 +15,7 @@ import VnTableChip from 'components/VnTable/VnChip.vue';
import VnVisibleColumn from 'src/components/VnTable/VnVisibleColumn.vue';
import VnLv from 'components/ui/VnLv.vue';
import VnTableOrder from 'src/components/VnTable/VnOrder.vue';
import ContextMenu from 'src/components/common/ContextMenu.vue';
const $props = defineProps({
columns: {
@ -113,6 +114,10 @@ const $props = defineProps({
type: Boolean,
default: false,
},
contextMenuItems: {
type: Array,
default: () => [],
},
});
const { t } = useI18n();
const stateStore = useStateStore();
@ -544,6 +549,14 @@ function handleSelection({ evt, added, rows: selectedRows }, rows) {
component-prop="columnField"
/>
</slot>
<ContextMenu
v-if="contextMenuItems && contextMenuItems.length > 0"
:data-key="$attrs['data-key']"
:table-row="row"
:table-col="col"
:expr-builder="$attrs['expr-builder']"
:context-menu-items="$props.contextMenuItems"
/>
</QTd>
</template>
<template #body-cell-tableActions="{ col, row }">
@ -774,6 +787,7 @@ function handleSelection({ evt, added, rows: selectedRows }, rows) {
</FormModelPopup>
</QDialog>
</template>
<i18n>
en:
status: Status

View File

@ -0,0 +1,192 @@
<script setup>
import { computed } from 'vue';
import { useArrayData } from 'composables/useArrayData';
import { buildFilter } from 'filters/filterPanel';
const $props = defineProps({
contextMenuItems: {
type: Array,
default: () => [],
},
tableRow: {
type: Object,
default: () => ({}),
},
dataKey: {
type: String,
default: '',
},
tableCol: {
type: Object,
default: () => ({}),
},
exprBuilder: {
type: Function,
default: null,
},
});
const arrayData = useArrayData($props.dataKey, {
exprBuilder: $props.exprBuilder,
url: 'Tickets/filter',
});
const store = arrayData.store;
const contextMenuProps = computed(() => $props.tableCol.contextMenuProps);
const isMenuEnabled = computed(() => contextMenuProps.value.menuEnabled);
const isFilterAllowed = computed(() => contextMenuProps.value.filterEnabled);
const isActionAllowed = computed(() => contextMenuProps.value.actionEnabled);
const fieldName = computed(() => $props.tableCol.name);
const fieldValue = computed(() => $props.tableRow[fieldName.value]);
const copyValueField = computed(
() => contextMenuProps.value.copyValueField || fieldName.value
);
const menuItems = computed(() => {
// If item does not have type, it will be displayed
return $props.contextMenuItems.filter((item) => {
return (
(item.type === 'filter' && isFilterAllowed.value) ||
(item.type === 'action' && isActionAllowed.value) ||
!item.type
);
});
});
/**
* Filter by current field selection
*/
const filterBySelection = () => {
const where = $props.exprBuilder
? $props.exprBuilder(fieldName.value, fieldValue.value)
: { [fieldName.value]: fieldValue.value };
arrayData.addFilterWhere(where);
};
/**
* Exclude by current field selection
*/
const excludeSelection = () => {
console.log('Exclude selection');
// TODO: Revisar porque no se aplica and en el filtro
let where = { [fieldName.value]: { neq: fieldValue.value } };
console.log('first where: ', where);
if ($props.exprBuilder) {
where = { [fieldName.value]: fieldValue.value };
where = buildFilter(where, (param, value) => {
console.log('build filter where: ', where);
console.log('parammmmm: ', param);
console.log('valueeeee: ', value);
const expr = $props.exprBuilder(param, value);
console.log('expr: ', expr);
const props = Object.keys(expr);
let newExpr = {};
for (let prop of props) {
if (expr[prop].like) {
const operator = expr[prop].like;
newExpr[prop] = { nlike: operator };
} else if (expr[prop].between) {
const operator = expr[prop].between;
newExpr = {
or: [
{ [prop]: { lt: operator[0] } },
{ [prop]: { gt: operator[1] } },
],
};
} else newExpr[prop] = { neq: fieldValue.value };
}
console.log('newExpr: ', newExpr);
return newExpr;
});
}
const filter = { where };
arrayData.addFilter({ filter });
};
const removeFilter = () => {
const userFilter = store.userFilter;
const userParams = store.userParams;
const where = userFilter?.where;
let filterKey = fieldName.value;
if ($props.exprBuilder) {
const param = $props.exprBuilder(fieldName.value, null);
if (param) [filterKey] = Object.keys(param);
}
if (!where) return;
const whereKeys = Object.keys(where);
for (let key of whereKeys) {
removeProp(where, filterKey, key);
if (!Object.keys(where)) delete userFilter.where;
}
function removeProp(obj, targetProp, prop) {
if (prop == targetProp) delete obj[prop];
if (prop === 'and' || prop === 'or') {
const arrayCopy = obj[prop].slice();
for (let param of arrayCopy) {
const [key] = Object.keys(param);
const index = obj[prop].findIndex((param) => {
return Object.keys(param)[0] == key;
});
if (key == targetProp) obj[prop].splice(index, 1);
if (param[key] instanceof Array) removeProp(param, filterKey, key);
if (Object.keys(param).length == 0) obj[prop].splice(index, 1);
}
if (obj[prop].length == 0) delete obj[prop];
}
}
arrayData.applyFilter({ filter: userFilter, params: userParams });
};
/**
* Removes all applied filters
*/
const removeAllFilters = () => {
const filter = { where: null };
arrayData.applyFilter({ filter });
};
/**
* Copies the current field
* value to the clipboard
*/
const copyValue = () => {
console.log('table row: ', $props.tableRow);
console.log('table col: ', $props.tableCol);
navigator.clipboard.writeText($props.tableRow[copyValueField.value]);
};
const menuActions = {
filterBySelection: () => filterBySelection(),
excludeSelection: () => excludeSelection(),
removeFilter: () => removeFilter(),
removeAllFilters: () => removeAllFilters(),
copyValue: () => copyValue(),
};
</script>
<template>
<QMenu v-if="isMenuEnabled" touch-position context-menu v-bind="$attrs">
<QList dense style="min-width: 100px">
<QItem
v-for="(item, index) in menuItems"
:key="index"
clickable
v-close-popup
@click="menuActions[item.action]"
>
<QItemSection>{{ item.label }}</QItemSection>
</QItem>
</QList>
</QMenu>
</template>

View File

@ -833,6 +833,12 @@ item:
specie: Specie
components:
topbar: {}
contextMenu:
filterBySelection: Filter by selection
excludeSelection: Exclude selection
removeFilter: Remove filter
removeAllFilters: Remove all filters
copyValue: Copy value
itemsFilterPanel:
typeFk: Type
value: Value

View File

@ -827,6 +827,12 @@ item:
concept: Concepto
components:
topbar: {}
contextMenu:
filterBySelection: Filtro por selección
excludeSelection: Excluir selección
removeFilter: Quitar filtro por selección
removeAllFilters: Eliminar todos los filtros
copyValue: Copiar valor
itemsFilterPanel:
typeFk: Tipo
value: Valor

View File

@ -47,7 +47,23 @@ const getGroupedStates = (data) => {
/>
<FetchData url="AgencyModes" @on-fetch="(data) => (agencies = data)" auto-load />
<FetchData url="Warehouses" @on-fetch="(data) => (warehouses = data)" auto-load />
<VnFilterPanel :data-key="props.dataKey" :search-button="true">
<VnFilterPanel
:data-key="props.dataKey"
:search-button="true"
:hidden-tags="[
'ts.stateFk',
'c.salesPersonFk',
'a.provinceFk',
'z.hour',
't.shipped',
't.id',
't.refFk',
't.zoneFk',
't.nickname',
't.agencyModeFk',
't.warehouseFk',
]"
>
<template #tags="{ tag, formatFn }">
<div class="q-gutter-x-xs">
<strong>{{ t(`params.${tag.label}`) }}: </strong>

View File

@ -5,7 +5,7 @@ import { useRoute, useRouter } from 'vue-router';
import { useStateStore } from 'stores/useStateStore';
import { useI18n } from 'vue-i18n';
import { useQuasar } from 'quasar';
import { toDate, toCurrency, dashIfEmpty } from 'src/filters/index';
import { toDate, toCurrency, dashIfEmpty, dateRange } from 'src/filters/index';
import useNotify from 'src/composables/useNotify';
import TicketSummary from './Card/TicketSummary.vue';
import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
@ -46,12 +46,14 @@ const userParams = {
from: null,
to: null,
};
onMounted(() => {
initializeFromQuery();
stateStore.rightDrawer = true;
if (!route.query.createForm) return;
onClientSelected(JSON.parse(route.query.createForm));
});
const initializeFromQuery = () => {
const query = route.query.table ? JSON.parse(route.query.table) : {};
from.value = query.from || from.toISOString();
@ -67,6 +69,60 @@ const companiesOptions = ref([]);
const accountingOptions = ref([]);
const amountToReturn = ref();
const exprBuilder = (param, value) => {
switch (param) {
case 'stateFk':
return { 'ts.stateFk': value };
case 'salesPersonFk':
return { 'c.salesPersonFk': value };
case 'provinceFk':
return { 'a.provinceFk': value };
case 'hour':
return { 'z.hour': value };
case 'shipped':
return {
't.shipped': {
between: dateRange(value),
},
};
case 'id':
case 'refFk':
case 'zoneFk':
case 'nickname':
case 'agencyModeFk':
case 'warehouseFk':
return { [`t.${param}`]: value };
}
};
const contextMenuItems = [
{
label: t('components.contextMenu.filterBySelection'),
action: 'filterBySelection',
type: 'filter',
},
{
label: t('components.contextMenu.excludeSelection'),
action: 'excludeSelection',
type: 'filter',
},
{
label: t('components.contextMenu.removeFilter'),
action: 'removeFilter',
type: 'filter',
},
{
label: t('components.contextMenu.removeAllFilters'),
action: 'removeAllFilters',
type: null,
},
{
label: t('components.contextMenu.copyValue'),
action: 'copyValue',
type: 'action',
},
];
const columns = computed(() => [
{
align: 'left',
@ -74,6 +130,11 @@ const columns = computed(() => [
hidden: true,
format: () => '',
columnClass: 'expand',
contextMenuProps: {
menuEnabled: true,
filterEnabled: false,
actionEnabled: false,
},
},
{
align: 'left',
@ -83,6 +144,11 @@ const columns = computed(() => [
condition: () => true,
},
isId: true,
contextMenuProps: {
menuEnabled: true,
filterEnabled: true,
actionEnabled: true,
},
},
{
align: 'left',
@ -100,11 +166,17 @@ const columns = computed(() => [
component: null,
},
columnClass: 'expand',
contextMenuProps: {
menuEnabled: true,
filterEnabled: true,
actionEnabled: true,
copyValueField: 'salesPerson',
},
format: (row, dashIfEmpty) => dashIfEmpty(row.salesPerson),
},
{
align: 'left',
name: 'shippedDate',
name: 'shipped',
cardVisible: true,
label: t('ticketList.shipped'),
columnFilter: {
@ -112,18 +184,34 @@ const columns = computed(() => [
alias: 't',
inWhere: true,
},
contextMenuProps: {
menuEnabled: true,
filterEnabled: true,
actionEnabled: true,
},
format: ({ shippedDate }) => toDate(shippedDate),
},
{
align: 'left',
name: 'shipped',
name: 'shippedHour',
label: t('ticketList.hour'),
contextMenuProps: {
menuEnabled: true,
filterEnabled: false,
actionEnabled: false,
},
format: (row) => toTimeFormat(row.shipped),
},
{
//TODO: Revisar porque no anda exclude filter
align: 'left',
name: 'zoneLanding',
label: t('ticketList.closure'),
contextMenuProps: {
menuEnabled: true,
filterEnabled: true,
actionEnabled: true,
},
format: (row, dashIfEmpty) => dashIfEmpty(toTimeFormat(row.zoneLanding)),
},
{
@ -131,18 +219,34 @@ const columns = computed(() => [
name: 'nickname',
label: t('ticketList.nickname'),
columnClass: 'expand',
contextMenuProps: {
menuEnabled: true,
filterEnabled: true,
actionEnabled: true,
},
},
{
align: 'left',
name: 'addressNickname',
label: t('ticketList.addressNickname'),
columnClass: 'expand',
contextMenuProps: {
menuEnabled: true,
filterEnabled: false,
actionEnabled: true,
},
},
{
align: 'left',
name: 'province',
name: 'provinceFk',
label: t('ticketList.province'),
columnClass: 'expand',
contextMenuProps: {
menuEnabled: true,
filterEnabled: true,
actionEnabled: true,
},
format: (row) => row.province,
},
{
align: 'left',
@ -157,6 +261,11 @@ const columns = computed(() => [
},
},
columnClass: 'expand',
contextMenuProps: {
menuEnabled: true,
filterEnabled: true,
actionEnabled: true,
},
},
{
align: 'left',
@ -172,13 +281,24 @@ const columns = computed(() => [
inWhere: true,
},
columnClass: 'expand',
contextMenuProps: {
menuEnabled: true,
filterEnabled: true,
actionEnabled: true,
},
format: (row, dashIfEmpty) => dashIfEmpty(row.zoneName),
},
{
align: 'left',
name: 'warehouse',
name: 'warehouseFk',
label: t('ticketList.warehouse'),
columnClass: 'expand',
contextMenuProps: {
menuEnabled: true,
filterEnabled: true,
actionEnabled: true,
},
format: (row) => row.warehouse,
},
{
align: 'left',
@ -189,12 +309,22 @@ const columns = computed(() => [
component: 'number',
inWhere: true,
},
contextMenuProps: {
menuEnabled: true,
filterEnabled: false,
actionEnabled: true,
},
format: (row) => toCurrency(row.totalWithVat),
},
{
align: 'left',
name: 'packing',
label: t('ticketSale.packaging'),
contextMenuProps: {
menuEnabled: true,
filterEnabled: false,
actionEnabled: false,
},
format: (row, dashIfEmpty) => dashIfEmpty(row.packing),
},
{
@ -221,6 +351,11 @@ const columns = computed(() => [
},
},
],
contextMenuProps: {
menuEnabled: false,
filterEnabled: false,
actionEnabled: false,
},
},
]);
function redirectToLines(id) {
@ -463,6 +598,7 @@ function setReference(data) {
<TicketFilter data-key="TicketList" />
</template>
</RightMenu>
<VnTable
ref="tableRef"
data-key="TicketList"
@ -484,7 +620,12 @@ function setReference(data) {
'row-key': 'id',
selection: 'multiple',
}"
<<<<<<< Updated upstream
data-cy="ticketListTable"
=======
:context-menu-items="contextMenuItems"
:expr-builder="exprBuilder"
>>>>>>> Stashed changes
>
<template #column-statusIcons="{ row }">
<TicketProblems :row="row" />
@ -495,7 +636,7 @@ function setReference(data) {
<CustomerDescriptorProxy :id="row.salesPersonFk" />
</span>
</template>
<template #column-shippedDate="{ row }">
<template #column-shipped="{ row }">
<span v-if="getDateColor(row.shipped)">
<QChip :class="getDateColor(row.shipped)" dense square>
{{ toDate(row.shippedDate) }}