0
0
Fork 0

feat: fix bugs and filters

This commit is contained in:
Javier Segarra 2024-07-18 15:20:44 +02:00
parent b24c7b0352
commit 7cbdf0d98b
13 changed files with 101 additions and 169 deletions

View File

@ -35,7 +35,9 @@ function stopEventPropagation(event) {
dense
square
>
<span v-if="!col.chip.icon">{{ row[col.name] }}</span>
<span v-if="!col.chip.icon">
{{ col.format ? col.format(row) : row[col.name] }}
</span>
<QIcon v-else :name="col.chip.icon" color="primary-light" />
</QChip>
</span>

View File

@ -147,7 +147,7 @@ const col = computed(() => {
}
if (
(newColumn.name.startsWith('is') || newColumn.name.startsWith('has')) &&
!newColumn.component
newColumn.component == null
)
newColumn.component = 'checkbox';
if ($props.default && !newColumn.component) newColumn.component = $props.default;
@ -158,7 +158,7 @@ const col = computed(() => {
const components = computed(() => $props.components ?? defaultComponents);
</script>
<template>
<div class="row no-wrap" :style="$props.column.style">
<div class="row no-wrap">
<VnComponent
v-if="col.before"
:prop="col.before"

View File

@ -64,6 +64,7 @@ const components = {
attrs: {
...defaultAttrs,
clearable: true,
type: 'number',
},
forceAttrs,
},

View File

@ -1,7 +1,7 @@
<script setup>
import { ref } from 'vue';
import { useArrayData } from 'composables/useArrayData';
const model = defineModel({ type: Object, required: true });
const model = defineModel({ type: Object });
const $props = defineProps({
name: {
type: String,
@ -56,7 +56,7 @@ defineExpose({ orderBy });
<span :title="label">{{ label }}</span>
<QChip
v-if="name"
:label="!vertical && model?.index"
:label="!vertical ? model?.index : ''"
:icon="
(model?.index || hover) && !vertical
? model?.direction == 'DESC'

View File

@ -96,9 +96,9 @@ const route = useRoute();
const router = useRouter();
const quasar = useQuasar();
const DEFAULT_MODE = 'card';
const CARD_MODE = 'card';
const TABLE_MODE = 'table';
const mode = ref(DEFAULT_MODE);
const mode = ref(CARD_MODE);
const selected = ref([]);
const routeQuery = JSON.parse(route?.query[$props.searchUrl] ?? '{}');
const params = ref({ ...routeQuery, ...routeQuery.filter?.where });
@ -117,13 +117,16 @@ const tableModes = [
{
icon: 'grid_view',
title: t('grid view'),
value: DEFAULT_MODE,
value: CARD_MODE,
disable: $props.disableOption?.card,
},
];
onMounted(() => {
mode.value = quasar.platform.is.mobile ? DEFAULT_MODE : $props.defaultMode;
mode.value =
quasar.platform.is.mobile && !$props.disableOption?.card
? CARD_MODE
: $props.defaultMode;
stateStore.rightDrawer = true;
setUserParams(route.query[$props.searchUrl]);
columnsVisibilitySkiped.value = [
@ -212,6 +215,7 @@ function stopEventPropagation(event) {
}
function reload(params) {
selected.value = [];
CrudModelRef.value.reload(params);
}
@ -360,7 +364,7 @@ function handleOnDataSaved(_, res) {
/>
</template>
<template #header-cell="{ col }">
<QTh v-if="col.visible ?? true" auto-width>
<QTh v-if="col.visible ?? true" :class="[col.columnClass]">
<div
class="column self-start q-ml-xs ellipsis"
:class="`text-${col?.align ?? 'left'}`"
@ -385,6 +389,7 @@ function handleOnDataSaved(_, res) {
:data-key="$attrs['data-key']"
v-model="params[columnName(col)]"
:search-url="searchUrl"
class="full-width"
/>
</div>
</QTh>
@ -409,7 +414,7 @@ function handleOnDataSaved(_, res) {
<QTd
auto-width
class="no-margin q-px-xs"
:class="[getColAlign(col), col.class, col.columnField?.class]"
:class="[getColAlign(col), col.columnClass]"
v-if="col.visible ?? true"
>
<slot :name="`column-${col.name}`" :col="col" :row="row">
@ -432,6 +437,7 @@ function handleOnDataSaved(_, res) {
>
<QBtn
v-for="(btn, index) of col.actions"
v-show="btn.show ? btn.show(row) : true"
:key="index"
:title="btn.title"
:icon="btn.icon"

View File

@ -17,15 +17,17 @@ const $props = defineProps({
},
});
let mixed;
const componentArray = computed(() => {
if (typeof $props.prop === 'object') return [$props.prop];
return $props.prop;
});
function mix(toComponent) {
if (mixed) return mixed;
const { component, attrs, event } = toComponent;
const customComponent = $props.components[component];
return {
mixed = {
component: customComponent?.component ?? component,
attrs: {
...toValueAttrs(attrs),
@ -35,6 +37,7 @@ function mix(toComponent) {
},
event: event ?? customComponent?.event,
};
return mixed;
}
function toValueAttrs(attrs) {

View File

@ -98,6 +98,7 @@ watch(
:class="{ required: $attrs.required }"
:rules="$attrs.required ? [requiredFieldRule] : null"
:clearable="false"
@click="isPopupOpen = true"
>
<template #append>
<QIcon

View File

@ -1,18 +1,28 @@
<script setup>
defineProps({ wrap: { type: Boolean, default: false } });
</script>
<template>
<div class="vn-row q-gutter-md q-mb-md">
<slot></slot>
<div class="vn-row q-gutter-md q-mb-md" :class="{ wrap }">
<slot />
</div>
</template>
<style lang="scss" scopped>
<style lang="scss" scoped>
.vn-row {
display: flex;
> * {
flex: 1;
&.wrap {
flex-wrap: wrap;
}
&:not(.wrap) {
> :slotted(*) {
flex: 1;
}
}
}
@media screen and (max-width: 800px) {
.vn-row {
flex-direction: column;
&:not(.wrap) {
flex-direction: column;
}
}
}
</style>

View File

@ -233,27 +233,23 @@ input::-webkit-inner-spin-button {
}
.q-table {
thead,
tbody {
th {
.q-select {
max-width: 120px;
}
}
td {
padding: 1px 10px 1px 10px;
max-width: 100px;
div span {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
th,
td {
padding: 1px 10px 1px 10px;
max-width: 100px;
div span {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.expand {
max-width: 400px;
}
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.shrink {
min-width: 65px;
}
.expand {
max-width: 200px;
}
}

View File

@ -1271,6 +1271,7 @@ components:
active: Is active
visible: Is visible
floramondo: Is floramondo
showBadDates: Show future items
userPanel:
copyToken: Token copied to clipboard
settings: Settings

View File

@ -1252,6 +1252,7 @@ components:
active: Activo
visible: Visible
floramondo: Floramondo
showBadDates: Ver items a futuro
userPanel:
copyToken: Token copiado al portapapeles
settings: Configuración

View File

@ -9,13 +9,14 @@ import VnSelect from 'src/components/common/VnSelect.vue';
import VnInputDate from 'src/components/common/VnInputDate.vue';
import EditTableCellValueForm from 'src/components/EditTableCellValueForm.vue';
import ItemFixedPriceFilter from './ItemFixedPriceFilter.vue';
import { useQuasar } from 'quasar';
import ItemDescriptorProxy from './Card/ItemDescriptorProxy.vue';
import { tMobile } from 'src/composables/tMobile';
import { useStateStore } from 'stores/useStateStore';
import { dashIfEmpty, toDate } from 'src/filters';
import { toDate } from 'src/filters';
import { useVnConfirm } from 'composables/useVnConfirm';
import { useState } from 'src/composables/useState';
import { toCurrency } from 'filters/index';
import useNotify from 'src/composables/useNotify.js';
import axios from 'axios';
import { isLower, isBigger } from 'src/filters/date.js';
@ -23,7 +24,6 @@ import RightMenu from 'src/components/common/RightMenu.vue';
import VnTable from 'src/components/VnTable/VnTable.vue';
import { QCheckbox } from 'quasar';
const checked = ref(false);
const stateStore = useStateStore();
const { t } = useI18n();
const { openConfirmationModal } = useVnConfirm();
@ -54,61 +54,6 @@ const exprBuilder = (param, value) => {
};
const params = reactive({});
// const arrayData = useArrayData('ItemFixedPrices', {
// url: 'FixedPrices/filter',
// userParams: params,
// order: ['name ASC', 'itemFk'],
// exprBuilder: exprBuilder,
// });
// const store = arrayData.store;
// const fetchFixedPrices = async () => {
// await arrayData.fetch({ append: false });
// };
// const onFixedPricesFetched = (data) => {
// data.forEach((item) => {
// console.log(item.hasMinPrice);
// item.hasMinPrice = `${item.hasMinPrice !== 0}`;
// });
// fixedPrices.value = data;
// // el objetivo de guardar una copia de las rows es evitar guardar cambios si la data no cambió al disparar los eventos
// fixedPricesOriginalData.value = JSON.parse(JSON.stringify(data));
// };
// watch(
// () => store.data,
// (data) => onFixedPricesFetched(data)
// );
// const applyColumnFilter = async (col) => {
// try {
// const paramKey = col.columnFilter?.filterParamKey || col.field;
// params[paramKey] = col.columnFilter.filterValue;
// await arrayData.addFilter({ params });
// } catch (err) {
// console.error('Error applying column filter', err);
// }
// };
// const getColumnInputEvents = (col) => {
// return col.columnFilter.type === 'select'
// ? { 'update:modelValue': () => applyColumnFilter(col) }
// : {
// 'keyup.enter': () => applyColumnFilter(col),
// };
// };
// const defaultColumnFilter = {
// component: VnInput,
// type: 'text',
// filterValue: null,
// event: getColumnInputEvents,
// attrs: {
// dense: true,
// },
// };
const defaultColumnAttrs = {
align: 'left',
sortable: true,
@ -123,6 +68,7 @@ const columns = computed(() => [
...defaultColumnAttrs,
isId: true,
cardVisible: true,
columnClass: 'shrink',
columnField: {
component: 'input',
type: 'number',
@ -131,6 +77,7 @@ const columns = computed(() => [
{
label: t('globals.name'),
field: 'name',
columnClass: 'shrink',
name: 'description',
...defaultColumnAttrs,
create: true,
@ -142,9 +89,6 @@ const columns = computed(() => [
name: 'rate2',
...defaultColumnAttrs,
cardVisible: true,
class: 'expand',
style: 'max-width: 80px',
},
{
label: t('item.fixedPrice.packingPrice'),
@ -152,12 +96,11 @@ const columns = computed(() => [
name: 'rate3',
...defaultColumnAttrs,
cardVisible: true,
class: 'expand',
style: 'max-width: 80px',
},
{
label: t('item.fixedPrice.minPrice'),
class: 'expand',
field: 'minPrice',
name: 'minPrice',
...defaultColumnAttrs,
@ -172,16 +115,17 @@ const columns = computed(() => [
label: t('item.fixedPrice.started'),
field: 'started',
name: 'started',
...defaultColumnAttrs,
format: ({ started }) => toDate(started),
cardVisible: true,
...defaultColumnAttrs,
component: 'date',
format: (row) => toDate(row.started),
},
{
label: t('item.fixedPrice.ended'),
field: 'ended',
name: 'ended',
...defaultColumnAttrs,
columnClass: 'expand',
cardVisible: true,
component: 'date',
format: (row) => toDate(row.ended),
@ -270,29 +214,7 @@ async function saveOnRowChange(row) {
else if (rowsSelected.value.length === 1)
await upsertFixedPrice(rowsSelected.value[0]);
rowsSelected.value = [row];
// if (rowsSelected.value.length > 0) {
// disableUnselectedRows();
// } else {
// resetRowStates();
// }
// if (lastRow.value && lastRow.value !== row.id) {
// console.log('update');
// // await upsertPrice(row);
// }
// lastRow.value = row.id;
}
// function disableUnselectedRows() {
// fixedPrices.value.forEach((row) => {
// row.disabled = !rowsSelected.value.includes(row.id);
// });
// }
// function resetRowStates() {
// fixedPrices.value.forEach((row) => {
// row.disable = false;
// });
// // Aquí puedes guardar los cambios si es necesario
// console.log('Guardando cambios...');
// }
const tableRef = ref();
function checkLastVisibleRow() {
const rows = document
@ -367,25 +289,6 @@ const openEditTableCellDialog = () => {
const onEditCellDataSaved = async () => {
rowsSelected.value = [];
};
/*const lastRow = ref(null);
async function saveOnRowChange(row) {
if (lastRow.value && lastRow.value !== row.id) {
console.log('update');
await upsertPrice(row);
return;
}
lastRow.value = row.id;
}*/
// const onWarehousesFetched = (data) => {
// warehousesOptions.value = data;
// // Actualiza las 'options' del elemento con field 'warehouseFk' en 'editTableFieldsOptions'.
// const warehouseField = editTableFieldsOptions.find(
// (field) => field.field === 'warehouseFk'
// );
// warehouseField.attrs.options = data;
// };
import { useQuasar } from 'quasar';
const removeFuturePrice = async () => {
try {
rowsSelected.value.forEach(({ id }) => {
@ -405,11 +308,21 @@ function confirmRemove(item) {
component: VnConfirm,
componentProps: {
title: t('This row will be removed'),
message: t('Do you want to clone this item?'),
message: t('Do you want to remove?'),
promise: async () => removePrice(item.id),
},
});
}
function confirmRemoveFuturePrice(item) {
quasar.dialog({
component: VnConfirm,
componentProps: {
title: t('This row will be removed'),
message: t('Do you want to remove?'),
promise: async () => removeFuturePrice(item.id),
},
});
}
const removePrice = async (id) => {
try {
@ -433,7 +346,6 @@ function handleOnDataSave(CrudModelRef) {
nextTick(() => {
highlightNewRow(checkLastVisibleRow());
});
// CrudModelRef.value.insert(lastItem);
}
onUnmounted(() => (stateStore.rightDrawer = false));
</script>
@ -465,12 +377,20 @@ onUnmounted(() => (stateStore.rightDrawer = false));
{{ t('Edit fixed price(s)') }}
</QTooltip>
</QBtn>
<QBtn
:label="tMobile('globals.remove')"
color="primary"
icon="delete"
flat
@click="confirmRemoveFuturePrice"
:title="t('globals.remove')"
v-if="rowsSelected.length"
/>
</template>
</VnSubToolbar>
<QPage>
{{ lastRow }}
{{ rowsSelected }}
<VnTable
:default-remove="false"
data-key="ItemFixedPrices"
url="FixedPrices/filter"
:filter="{ where: exprBuilder }"
@ -500,14 +420,7 @@ onUnmounted(() => (stateStore.rightDrawer = false));
</template>
<template #body-selection="scope">
{{ scope }}
<QCheckbox
flat
style="width: 10px; margin-left: -20px"
v-model="scope.selected"
/>
<!--:disable="
rowsSelected.length > 0 && rowsSelected[0].id !== scope.row.id
"-->
<QCheckbox flat v-model="scope.selected" />
</template>
<template #column-itemId="props">
@ -538,13 +451,16 @@ onUnmounted(() => (stateStore.rightDrawer = false));
{{ row.name }}
</span>
<ItemDescriptorProxy :id="row.itemFk" />
<FetchedTags style="max-width: 220px" :item="row" :max-length="6" />
<FetchedTags
style="width: max-content; max-width: 220px"
:item="row"
:max-length="6"
/>
</QTd>
</template>
<template #column-rate2="props">
<QTd class="col">
<VnInput
style="max-width: 80px"
mask="###.##"
v-model.number="props.row.rate2"
v-on="getRowUpdateInputEvents(props)"
@ -556,7 +472,6 @@ onUnmounted(() => (stateStore.rightDrawer = false));
<template #column-rate3="props">
<QTd class="col">
<VnInput
style="width: 80px"
mask="###.##"
v-model.number="props.row.rate3"
v-on="getRowUpdateInputEvents(props)"
@ -577,12 +492,11 @@ onUnmounted(() => (stateStore.rightDrawer = false));
<VnInput
class="col"
mask="###.##"
style="width: 80px"
:disable="props.row.hasMinPrice === 1"
v-model.number="props.row.minPrice"
v-on="getRowUpdateInputEvents(props)"
>
<template #append>{{ props.row.hasMinPrice }}</template>
<template #append></template>
</VnInput>
</div>
</QTd>
@ -590,6 +504,7 @@ onUnmounted(() => (stateStore.rightDrawer = false));
<template #column-started="props">
<QTd class="col">
<VnInputDate
style="min-width: 147px"
:show-event="true"
v-model="props.row.started"
v-on="getRowUpdateInputEvents(props, false, 'date')"
@ -607,6 +522,7 @@ onUnmounted(() => (stateStore.rightDrawer = false));
<template #column-ended="props">
<QTd class="col">
<VnInputDate
style="min-width: 147px"
:show-event="true"
v-model="props.row.ended"
v-on="getRowUpdateInputEvents(props, false, 'date')"
@ -691,7 +607,6 @@ onUnmounted(() => (stateStore.rightDrawer = false));
.q-field__append {
padding: 0;
}
/* height or max-height is important */
tbody tr.highlight .q-td {
animation: highlight-animation 4s ease-in-out;

View File

@ -24,8 +24,7 @@ const route = useRoute();
const itemTypeWorkersOptions = ref([]);
const sanitizeParam = (param) => {
if (!route?.query?.params) return 'false';
const params = JSON.parse(route?.query?.params);
const params = JSON.parse(route?.query?.table);
return params[param] ?? 'false';
};
const $params = ref({});
@ -110,19 +109,16 @@ const pushParam = (param) => ({
:false-value="'false'"
@update:model-value="searchFn(pushParam('mine'))"
/>
</QItemSection>
<QItemSection>
<QCheckbox
size="sm"
v-model="checked"
:label="t(`Show future items`)"
v-model="$params.showBadDates"
:label="t(`components.itemsFilterPanel.showBadDates`)"
:true-value="'true'"
:false-value="'false'"
@update:model-value="searchFn(pushParam('showBadDates'))"
>
</QCheckbox>
</QItemSection>
<QItemSection>
<QCheckbox
:label="t('components.itemsFilterPanel.hasMinPrice')"
v-model="$params.hasMinPrice"