feat: refs #8004 enhance FetchedTags component with column support and styling updates
gitea/salix-front/pipeline/pr-dev This commit looks good Details

This commit is contained in:
Pablo Natek 2024-11-28 09:23:25 +01:00
parent a7e798a7ad
commit 1b6bb39c3e
8 changed files with 74 additions and 56 deletions

View File

@ -16,7 +16,13 @@ const $props = defineProps({
required: false, required: false,
default: 'value', default: 'value',
}, },
columns: {
type: Number,
required: false,
default: null,
},
}); });
const tags = computed(() => { const tags = computed(() => {
return Object.keys($props.item) return Object.keys($props.item)
.filter((i) => i.startsWith(`${$props.tag}`)) .filter((i) => i.startsWith(`${$props.tag}`))
@ -28,10 +34,21 @@ const tags = computed(() => {
return acc; return acc;
}, {}); }, {});
}); });
const columnStyle = computed(() => {
if ($props.columns) {
return {
'grid-template-columns': `repeat(${$props.columns}, 1fr)`,
'max-width': `${$props.columns * 4}rem`,
};
}
return {};
});
</script> </script>
<template> <template>
<div class="fetchedTags"> <div class="fetchedTags">
<div class="wrap"> <div class="wrap" :style="columnStyle">
<div <div
v-for="(val, key) in tags" v-for="(val, key) in tags"
:key="key" :key="key"
@ -39,7 +56,7 @@ const tags = computed(() => {
:title="`${key}: ${val}`" :title="`${key}: ${val}`"
:class="{ empty: !val }" :class="{ empty: !val }"
> >
{{ val }} <span class="text">{{ val }} </span>
</div> </div>
</div> </div>
</div> </div>
@ -49,27 +66,33 @@ const tags = computed(() => {
.fetchedTags { .fetchedTags {
align-items: center; align-items: center;
.wrap { .wrap {
width: 100%;
flex-wrap: wrap; flex-wrap: wrap;
display: flex; display: grid;
} }
.inline-tag { .inline-tag {
height: 1rem; height: 1rem;
margin: 0.05rem; margin: 0.05rem;
color: $color-font-secondary; color: var(--vn-label-color);
text-align: center; text-align: center;
font-size: smaller; font-size: smaller;
padding: 1px; padding: 1px;
flex: 1; border: 1px solid var(--vn-label-color);
border: 1px solid $color-spacer;
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden;
min-width: 4rem; min-width: 4rem;
max-width: 4rem; max-width: 4rem;
} }
.text {
vertical-align: middle;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-size: smaller;
}
.empty { .empty {
border: 1px solid #2b2b2b; border: 1px solid var(--vn-empty-tag);
} }
} }
</style> </style>

View File

@ -11,6 +11,7 @@ body.body--light {
--vn-text-color: var(--font-color); --vn-text-color: var(--font-color);
--vn-label-color: #5f5f5f; --vn-label-color: #5f5f5f;
--vn-accent-color: #e7e3e3; --vn-accent-color: #e7e3e3;
--vn-empty-tag: #acacac;
background-color: var(--vn-page-color); background-color: var(--vn-page-color);
@ -26,6 +27,7 @@ body.body--dark {
--vn-text-color: white; --vn-text-color: white;
--vn-label-color: #a8a8a8; --vn-label-color: #a8a8a8;
--vn-accent-color: #424242; --vn-accent-color: #424242;
--vn-empty-tag: #2d2d2d;
background-color: var(--vn-page-color); background-color: var(--vn-page-color);
} }

View File

@ -469,7 +469,7 @@ function handleOnDataSave({ CrudModelRef }) {
</span> </span>
<span class="subName">{{ row.subName }}</span> <span class="subName">{{ row.subName }}</span>
<ItemDescriptorProxy :id="row.itemFk" /> <ItemDescriptorProxy :id="row.itemFk" />
<FetchedTags :item="row" /> <FetchedTags :item="row" :columns="3" />
</template> </template>
<template #column-rate2="props"> <template #column-rate2="props">
<QTd class="col"> <QTd class="col">

View File

@ -11,6 +11,7 @@ import { useSummaryDialog } from 'src/composables/useSummaryDialog';
import ItemSummary from '../Item/Card/ItemSummary.vue'; import ItemSummary from '../Item/Card/ItemSummary.vue';
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue'; import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
import ItemDescriptorProxy from './Card/ItemDescriptorProxy.vue'; import ItemDescriptorProxy from './Card/ItemDescriptorProxy.vue';
import ItemTypeDescriptorProxy from './ItemType/Card/ItemTypeDescriptorProxy.vue';
import { cloneItem } from 'src/pages/Item/composables/cloneItem'; import { cloneItem } from 'src/pages/Item/composables/cloneItem';
import RightMenu from 'src/components/common/RightMenu.vue'; import RightMenu from 'src/components/common/RightMenu.vue';
import ItemListFilter from './ItemListFilter.vue'; import ItemListFilter from './ItemListFilter.vue';
@ -67,7 +68,6 @@ const columns = computed(() => [
}, },
}, },
columnFilter: false, columnFilter: false,
cardVisible: true,
}, },
{ {
label: t('item.list.id'), label: t('item.list.id'),
@ -105,7 +105,7 @@ const columns = computed(() => [
columnFilter: { columnFilter: {
name: 'search', name: 'search',
}, },
cardVisible: true, columnClass: 'expand',
}, },
{ {
label: t('item.list.stems'), label: t('item.list.stems'),
@ -143,10 +143,13 @@ const columns = computed(() => [
fields: ['id', 'name'], fields: ['id', 'name'],
}, },
}, },
columnField: {
component: null,
},
create: true, create: true,
visible: false,
},
{
label: t('item.list.typeName'),
name: 'typeName',
align: 'left',
}, },
{ {
label: t('item.list.category'), label: t('item.list.category'),
@ -230,7 +233,6 @@ const columns = computed(() => [
{ {
label: t('item.list.weightByPiece'), label: t('item.list.weightByPiece'),
name: 'weightByPiece', name: 'weightByPiece',
align: 'left',
component: 'input', component: 'input',
columnField: { columnField: {
component: null, component: null,
@ -305,36 +307,7 @@ const columns = computed(() => [
], ],
}, },
]); ]);
const redirectToItemCreate = () => {
router.push({ name: 'ItemCreate' });
};
const redirectToItemSummary = (id) => {
router.push({ name: 'ItemSummary', params: { id } });
};
const cloneItem = async (itemFk) => {
try {
const { data } = await axios.post(`Items/${itemFk}/clone`);
if (!data) return;
router.push({ name: 'ItemTags', params: { id: data.id } });
} catch (err) {
console.error('Error cloning item', err);
}
};
onMounted(async () => {
stateStore.rightDrawer = true;
const filteredColumns = columns.value.filter(
(col) => col.name !== 'picture' && col.name !== 'actions'
);
allColumnNames.value = filteredColumns.map((col) => col.name);
});
onUnmounted(() => (stateStore.rightDrawer = false));
</script> </script>
<template> <template>
<VnSearchbar <VnSearchbar
data-key="ItemList" data-key="ItemList"
@ -361,7 +334,6 @@ onUnmounted(() => (stateStore.rightDrawer = false));
}" }"
:order="['isActive DESC', 'name', 'id']" :order="['isActive DESC', 'name', 'id']"
:columns="columns" :columns="columns"
auto-load
redirect="Item" redirect="Item"
:is-editable="false" :is-editable="false"
:right-search="false" :right-search="false"
@ -373,6 +345,13 @@ onUnmounted(() => (stateStore.rightDrawer = false));
<ItemDescriptorProxy :id="row.id" /> <ItemDescriptorProxy :id="row.id" />
</span> </span>
</template> </template>
<template #column-typeName="{ row }">
<span class="link" @click.stop>
{{ row.typeName }}
{{ row.typeFk }}
<ItemTypeDescriptorProxy :id="row.typeFk" />
</span>
</template>
<template #column-userName="{ row }"> <template #column-userName="{ row }">
<span class="link" @click.stop> <span class="link" @click.stop>
{{ row.userName }} {{ row.userName }}
@ -386,11 +365,10 @@ onUnmounted(() => (stateStore.rightDrawer = false));
{{ row?.subName.toUpperCase() }} {{ row?.subName.toUpperCase() }}
</div> </div>
</div> </div>
<FetchedTags :item="row" :max-length="6" /> <FetchedTags :item="row" :columns="3" />
</template> </template>
</VnTable> </VnTable>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
.subName { .subName {
text-transform: uppercase; text-transform: uppercase;

View File

@ -6,13 +6,11 @@ import { useI18n } from 'vue-i18n';
import CardDescriptor from 'components/ui/CardDescriptor.vue'; import CardDescriptor from 'components/ui/CardDescriptor.vue';
import VnLv from 'src/components/ui/VnLv.vue'; import VnLv from 'src/components/ui/VnLv.vue';
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue'; import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
import useCardDescription from 'src/composables/useCardDescription'; import useCardDescription from 'src/composables/useCardDescription';
const $props = defineProps({ const $props = defineProps({
id: { id: {
type: Number, type: Number,
required: false,
default: null, default: null,
}, },
summary: { summary: {
@ -24,6 +22,10 @@ const $props = defineProps({
const route = useRoute(); const route = useRoute();
const { t } = useI18n(); const { t } = useI18n();
const entityId = computed(() => {
return $props.id || route.params.id;
});
const itemTypeFilter = { const itemTypeFilter = {
include: [ include: [
{ relation: 'worker' }, { relation: 'worker' },
@ -33,10 +35,6 @@ const itemTypeFilter = {
], ],
}; };
const entityId = computed(() => {
return $props.id || route.params.id;
});
const data = ref(useCardDescription()); const data = ref(useCardDescription());
const setData = (entity) => (data.value = useCardDescription(entity.code, entity.id)); const setData = (entity) => (data.value = useCardDescription(entity.code, entity.id));
</script> </script>
@ -48,8 +46,8 @@ const setData = (entity) => (data.value = useCardDescription(entity.code, entity
:filter="itemTypeFilter" :filter="itemTypeFilter"
:title="data.title" :title="data.title"
:subtitle="data.subtitle" :subtitle="data.subtitle"
data-key="itemTypeDescriptor"
@on-fetch="setData" @on-fetch="setData"
data-key="entry"
> >
<template #body="{ entity }"> <template #body="{ entity }">
<VnLv :label="t('shared.code')" :value="entity.code" /> <VnLv :label="t('shared.code')" :value="entity.code" />

View File

@ -0,0 +1,17 @@
<script setup>
import ItemTypeDescriptor from './ItemTypeDescriptor.vue';
import ItemTypeSummary from './ItemTypeSummary.vue';
const $props = defineProps({
id: {
type: Number,
required: true,
},
});
</script>
<template>
<QPopupProxy>
<ItemTypeDescriptor v-if="$props.id" :id="$props.id" :summary="ItemTypeSummary" />
</QPopupProxy>
</template>

View File

@ -124,7 +124,7 @@ item:
size: Size size: Size
origin: Origin origin: Origin
userName: Buyer userName: Buyer
weightByPiece: Weight/Piece weightByPiece: Weight/stem
stemMultiplier: Multiplier stemMultiplier: Multiplier
producer: Producer producer: Producer
landed: Landed landed: Landed

View File

@ -125,7 +125,7 @@ item:
isActive: Activo isActive: Activo
size: Medida size: Medida
origin: Origen origin: Origen
weightByPiece: Peso (gramos)/tallo weightByPiece: Peso/tallo
userName: Comprador userName: Comprador
stemMultiplier: Multiplicador stemMultiplier: Multiplicador
producer: Productor producer: Productor