feat: refs #8463 cardDescriptorBeta #1291

Closed
alexm wants to merge 10 commits from 8463-CardDescriptor_useCard into dev
29 changed files with 498 additions and 424 deletions

View File

@ -1,12 +1,15 @@
<script setup>
import { onBeforeMount } from 'vue';
import { useRouter, onBeforeRouteUpdate, onBeforeRouteLeave } from 'vue-router';
import { onBeforeMount, computed } from 'vue';
import { useRoute, useRouter, onBeforeRouteUpdate, onBeforeRouteLeave } from 'vue-router';
import { useArrayData } from 'src/composables/useArrayData';
import { useStateStore } from 'stores/useStateStore';
import useCardSize from 'src/composables/useCardSize';
import VnSubToolbar from '../ui/VnSubToolbar.vue';
const emit = defineEmits(['onFetch']);
const props = defineProps({
id: { type: Number, required: false, default: null },
dataKey: { type: String, required: true },
url: { type: String, default: undefined },
idInWhere: { type: Boolean, default: false },
@ -16,10 +19,13 @@ const props = defineProps({
searchDataKey: { type: String, default: undefined },
searchbarProps: { type: Object, default: undefined },
redirectOnError: { type: Boolean, default: false },
visual: { type: Boolean, default: true },
Review

Se añade una prop para hacer que el template sea visible o no (v-if)

Se añade una prop para hacer que el template sea visible o no (v-if)
Review

Sugerencia, la variable porque no se llamaba visible?

Sugerencia, la variable porque no se llamaba visible?
});
const route = useRoute();
const stateStore = useStateStore();
const router = useRouter();
const entityId = computed(() => props.id || route?.params?.id);
const arrayData = useArrayData(props.dataKey, {
url: props.url,
userFilter: props.filter,
@ -35,7 +41,7 @@ onBeforeMount(async () => {
const route = router.currentRoute.value;
try {
await fetch(route.params.id);
await fetch(entityId.value);
} catch {
const { matched: matches } = route;
const { path } = matches.at(-1);
@ -51,8 +57,7 @@ onBeforeRouteUpdate(async (to, from) => {
router.push({ name, params: to.params });
}
}
const id = to.params.id;
if (id !== from.params.id) await fetch(id, true);
if (entityId.value !== to.params.id) await fetch(to.params.id, true);
Review

He visto que asi funciona mejor. Si no hacia 1 1. Pq el entityId no sehabia actualizado antes cambiar de seccion

He visto que asi funciona mejor. Si no hacia 1 1. Pq el entityId no sehabia actualizado antes cambiar de seccion
});
async function fetch(id, append = false) {
@ -61,14 +66,17 @@ async function fetch(id, append = false) {
else if (!regex.test(props.url)) arrayData.store.url = `${props.url}/${id}`;
else arrayData.store.url = props.url.replace(regex, `/${id}`);
await arrayData.fetch({ append, updateRouter: false });
emit('onFetch', arrayData.store.data);
}
function hasRouteParam(params, valueToCheck = ':addressId') {
return Object.values(params).includes(valueToCheck);
}
</script>
<template>
<VnSubToolbar />
<div :class="[useCardSize(), $attrs.class]">
<RouterView :key="$route.path" />
</div>
<template v-if="visual">
alexm marked this conversation as resolved Outdated

la etiqueta span se suele usar para texto, en este caso usaria div

la etiqueta span se suele usar para texto, en este caso usaria div
<VnSubToolbar />
<div :class="[useCardSize(), $attrs.class]">
<RouterView :key="$route.path" />
</div>
</template>
</template>

View File

@ -1,353 +1,38 @@
<script setup>
Review

Al cardDescriptor le quitamos la funcionalidad del template

Al cardDescriptor le quitamos la funcionalidad del template
import { onBeforeMount, watch, computed, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import SkeletonDescriptor from 'components/ui/SkeletonDescriptor.vue';
import { useArrayData } from 'composables/useArrayData';
import { useSummaryDialog } from 'src/composables/useSummaryDialog';
import { useState } from 'src/composables/useState';
import { useRoute, useRouter } from 'vue-router';
import { useClipboard } from 'src/composables/useClipboard';
import VnMoreOptions from './VnMoreOptions.vue';
import { ref } from 'vue';
import VnDescriptor from './VnDescriptor.vue';
const $props = defineProps({
url: {
type: String,
default: '',
},
filter: {
type: Object,
default: null,
},
title: {
type: String,
default: '',
},
subtitle: {
id: {
type: Number,
default: null,
default: false,
},
dataKey: {
type: String,
default: null,
},
summary: {
card: {
type: Object,
default: null,
},
width: {
type: String,
default: 'md-width',
},
});
const state = useState();
const route = useRoute();
const router = useRouter();
const { t } = useI18n();
const { copyText } = useClipboard();
const { viewSummary } = useSummaryDialog();
let arrayData;
let store;
let entity;
const isLoading = ref(false);
const isSameDataKey = computed(() => $props.dataKey === route.meta.moduleName);
const DESCRIPTOR_PROXY = 'DescriptorProxy';
const moduleName = ref();
const isSameModuleName = route.matched[1].meta.moduleName !== moduleName.value;
defineExpose({ getData });
onBeforeMount(async () => {
arrayData = useArrayData($props.dataKey, {
url: $props.url,
userFilter: $props.filter,
skip: 0,
oneRecord: true,
});
store = arrayData.store;
entity = computed(() => {
const data = store.data ?? {};
if (data) emit('onFetch', data);
return data;
});
// It enables to load data only once if the module is the same as the dataKey
if (!isSameDataKey.value || !route.params.id) await getData();
watch(
() => [$props.url, $props.filter],
async () => {
if (!isSameDataKey.value) await getData();
},
);
});
function getName() {
let name = $props.dataKey;
if ($props.dataKey.includes(DESCRIPTOR_PROXY)) {
name = name.split(DESCRIPTOR_PROXY)[0];
}
return name;
}
const routeName = computed(() => {
let routeName = getName();
return `${routeName}Summary`;
});
async function getData() {
store.url = $props.url;
store.filter = $props.filter ?? {};
isLoading.value = true;
try {
const { data } = await arrayData.fetch({ append: false, updateRouter: false });
state.set($props.dataKey, data);
emit('onFetch', data);
} finally {
isLoading.value = false;
}
}
function getValueFromPath(path) {
if (!path) return;
const keys = path.toString().split('.');
let current = entity.value;
for (const key of keys) {
if (current[key] === undefined) return undefined;
else current = current[key];
}
return current;
}
function copyIdText(id) {
copyText(id, {
component: {
copyValue: id,
},
});
}
const emit = defineEmits(['onFetch']);
const iconModule = computed(() => {
moduleName.value = getName();
if (isSameModuleName) {
return router.options.routes[1].children.find((r) => r.name === moduleName.value)
?.meta?.icon;
} else {
return route.matched[1].meta.icon;
}
});
const toModule = computed(() => {
moduleName.value = getName();
if (isSameModuleName) {
return router.options.routes[1].children.find((r) => r.name === moduleName.value)
?.children[0]?.redirect;
} else {
return route.matched[1].path.split('/').length > 2
? route.matched[1].redirect
: route.matched[1].children[0].redirect;
}
});
const entity = ref();
</script>
<template>
<div class="descriptor">
<template v-if="entity && !isLoading">
<div class="header bg-primary q-pa-sm justify-between">
<slot name="header-extra-action">
<QBtn
round
flat
dense
size="md"
:icon="iconModule"
color="white"
class="link"
:to="toModule"
>
<QTooltip>
{{ t('globals.goToModuleIndex') }}
</QTooltip>
</QBtn>
</slot>
<QBtn
@click.stop="viewSummary(entity.id, $props.summary, $props.width)"
round
flat
dense
size="md"
icon="preview"
color="white"
class="link"
v-if="summary"
>
<QTooltip>
{{ t('components.smartCard.openSummary') }}
</QTooltip>
</QBtn>
<RouterLink :to="{ name: routeName, params: { id: entity.id } }">
<QBtn
class="link"
color="white"
dense
flat
icon="launch"
round
size="md"
>
<QTooltip>
{{ t('components.cardDescriptor.summary') }}
</QTooltip>
</QBtn>
</RouterLink>
<VnMoreOptions v-if="$slots.menu">
<template #menu="{ menuRef }">
<slot name="menu" :entity="entity" :menu-ref="menuRef" />
</template>
</VnMoreOptions>
</div>
<slot name="before" />
<div class="body q-py-sm">
<QList dense>
<QItemLabel header class="ellipsis text-h5" :lines="1">
<div class="title">
<span v-if="$props.title" :title="getValueFromPath(title)">
{{ getValueFromPath(title) ?? $props.title }}
</span>
<slot v-else name="description" :entity="entity">
<span :title="entity.name">
{{ entity.name }}
</span>
</slot>
</div>
</QItemLabel>
<QItem>
<QItemLabel class="subtitle">
#{{ getValueFromPath(subtitle) ?? entity.id }}
</QItemLabel>
<QBtn
round
flat
dense
size="sm"
icon="content_copy"
color="primary"
@click.stop="copyIdText(entity.id)"
>
<QTooltip>
{{ t('globals.copyId') }}
</QTooltip>
</QBtn>
</QItem>
</QList>
<div class="list-box q-mt-xs">
<slot name="body" :entity="entity" />
</div>
</div>
<div class="icons">
<slot name="icons" :entity="entity" />
</div>
<div class="actions justify-center" data-cy="descriptor_actions">
<slot name="actions" :entity="entity" />
</div>
<slot name="after" />
</template>
<SkeletonDescriptor v-if="!entity || isLoading" />
</div>
<QInnerLoading
:label="t('globals.pleaseWait')"
:showing="isLoading"
color="primary"
/>
</template>
<style lang="scss">
.body {
background-color: var(--vn-section-color);
.text-h5 {
font-size: 20px;
padding-top: 5px;
padding-bottom: 0px;
}
.q-item {
min-height: 20px;
.link {
margin-left: 10px;
}
}
.vn-label-value {
display: flex;
padding: 0px 16px;
.label {
color: var(--vn-label-color);
font-size: 14px;
&:not(:has(a))::after {
content: ':';
<component
:is="card"
:id
:visual="false"
v-bind="$attrs"
@on-fetch="
(data) => {
entity = data;
emit('onFetch', data);
}
}
.value {
color: var(--vn-text-color);
font-size: 14px;
margin-left: 4px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
text-align: left;
}
.info {
margin-left: 5px;
}
}
}
</style>
<style lang="scss" scoped>
.title {
overflow: hidden;
text-overflow: ellipsis;
span {
color: var(--vn-text-color);
font-weight: bold;
}
}
.subtitle {
color: var(--vn-text-color);
font-size: 16px;
margin-bottom: 2px;
}
.list-box {
.q-item__label {
color: var(--vn-label-color);
padding-bottom: 0%;
}
}
.descriptor {
width: 256px;
.header {
display: flex;
align-items: center;
}
.icons {
margin: 0 10px;
display: flex;
justify-content: center;
.q-icon {
margin-right: 5px;
}
}
.actions {
margin: 0 5px;
justify-content: center !important;
}
}
</style>
<i18n>
en:
globals:
copyId: Copy ID
es:
globals:
copyId: Copiar ID
</i18n>
"
/>
<VnDescriptor v-model="entity" v-bind="$attrs">
<template v-for="(_, slotName) in $slots" #[slotName]="slotData" :key="slotName">
<slot :name="slotName" v-bind="slotData ?? {}" :key="slotName" />
</template>
</VnDescriptor>
</template>

View File

@ -0,0 +1,78 @@
<script setup>
import { onBeforeMount, watch, computed, ref } from 'vue';
import { useArrayData } from 'composables/useArrayData';
import { useState } from 'src/composables/useState';
import { useRoute } from 'vue-router';
import VnDescriptor from './VnDescriptor.vue';
const $props = defineProps({
url: {
type: String,
default: '',
},
filter: {
type: Object,
default: null,
},
dataKey: {
type: String,
default: null,
},
});
const state = useState();
const route = useRoute();
let arrayData;
let store;
let entity;
const isLoading = ref(false);
const isSameDataKey = computed(() => $props.dataKey === route.meta.moduleName);
defineExpose({ getData });
onBeforeMount(async () => {
arrayData = useArrayData($props.dataKey, {
url: $props.url,
userFilter: $props.filter,
skip: 0,
oneRecord: true,
});
store = arrayData.store;
entity = computed(() => {
const data = store.data ?? {};
if (data) emit('onFetch', data);
return data;
});
// It enables to load data only once if the module is the same as the dataKey
if (!isSameDataKey.value || !route.params.id) await getData();
watch(
() => [$props.url, $props.filter],
async () => {
if (!isSameDataKey.value) await getData();
},
);
});
async function getData() {
store.url = $props.url;
store.filter = $props.filter ?? {};
isLoading.value = true;
try {
const { data } = await arrayData.fetch({ append: false, updateRouter: false });
state.set($props.dataKey, data);
emit('onFetch', data);
} finally {
isLoading.value = false;
}
}
const emit = defineEmits(['onFetch']);
</script>
<template>
<VnDescriptor v-model="entity" v-bind="$attrs" :module="dataKey">
<template v-for="(_, slotName) in $slots" #[slotName]="slotData" :key="slotName">
<slot :name="slotName" v-bind="slotData ?? {}" :key="slotName" />
</template>
</VnDescriptor>
</template>

View File

@ -0,0 +1,296 @@
<script setup>
Review

El template base para los 2 componentes

El template base para los 2 componentes
import { computed, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import SkeletonDescriptor from 'components/ui/SkeletonDescriptor.vue';
import { useSummaryDialog } from 'src/composables/useSummaryDialog';
import { useRoute, useRouter } from 'vue-router';
import { useClipboard } from 'src/composables/useClipboard';
import VnMoreOptions from './VnMoreOptions.vue';
const entity = defineModel({ type: Object, default: null });
const $props = defineProps({
title: {
type: String,
default: '',
},
subtitle: {
type: Number,
default: null,
},
summary: {
type: Object,
default: null,
},
width: {
type: String,
default: 'md-width',
},
module: {
type: String,
default: '',
},
});
const route = useRoute();
const router = useRouter();
const { t } = useI18n();
const { copyText } = useClipboard();
const { viewSummary } = useSummaryDialog();
const DESCRIPTOR_PROXY = 'DescriptorProxy';
const moduleName = ref();
const isSameModuleName = route.matched[1].meta.moduleName !== moduleName.value;
function getName() {
let name = $props.module;
if (name.includes(DESCRIPTOR_PROXY)) {
name = name.split(DESCRIPTOR_PROXY)[0];
}
return name;
}
const routeName = computed(() => {
let routeName = getName();
return `${routeName}Summary`;
});
function getValueFromPath(path) {
if (!path) return;
const keys = path.toString().split('.');
let current = entity.value;
for (const key of keys) {
if (current[key] === undefined) return undefined;
else current = current[key];
}
return current;
}
function copyIdText(id) {
copyText(id, {
component: {
copyValue: id,
},
});
}
const emit = defineEmits(['onFetch']);
const iconModule = computed(() => {
moduleName.value = getName();
if (isSameModuleName) {
return router.options.routes[1].children.find((r) => r.name === moduleName.value)
?.meta?.icon;
} else {
return route.matched[1].meta.icon;
}
});
const toModule = computed(() => {
moduleName.value = getName();
if (isSameModuleName) {
return router.options.routes[1].children.find((r) => r.name === moduleName.value)
?.children[0]?.redirect;
} else {
return route.matched[1].path.split('/').length > 2
? route.matched[1].redirect
: route.matched[1].children[0].redirect;
}
});
</script>
<template>
<div class="descriptor">
<template v-if="entity && entity?.id">
<div class="header bg-primary q-pa-sm justify-between">
<slot name="header-extra-action">
<QBtn
round
flat
dense
size="md"
:icon="iconModule"
color="white"
class="link"
:to="toModule"
>
<QTooltip>
{{ t('globals.goToModuleIndex') }}
</QTooltip>
</QBtn>
</slot>
<QBtn
@click.stop="viewSummary(entity.id, summary, width)"
round
flat
dense
size="md"
icon="preview"
color="white"
class="link"
v-if="summary"
>
<QTooltip>
{{ t('components.smartCard.openSummary') }}
</QTooltip>
</QBtn>
<RouterLink :to="{ name: routeName, params: { id: entity.id } }">
<QBtn
class="link"
color="white"
dense
flat
icon="launch"
round
size="md"
>
<QTooltip>
{{ t('components.cardDescriptor.summary') }}
</QTooltip>
</QBtn>
</RouterLink>
<VnMoreOptions v-if="$slots.menu">
<template #menu="{ menuRef }">
<slot name="menu" :entity="entity" :menu-ref="menuRef" />
</template>
</VnMoreOptions>
</div>
<slot name="before" />
<div class="body q-py-sm">
<QList dense>
<QItemLabel header class="ellipsis text-h5" :lines="1">
<div class="title">
<span v-if="title" :title="getValueFromPath(title)">
alexm marked this conversation as resolved Outdated

el parámetro de la función entiendo que viene de $props.title
Entonces porque viewSummary si que los pasas?

Ya que lo movemos podemos hacer cambios que antes no veiamos

el parámetro de la función entiendo que viene de $props.title Entonces porque viewSummary si que los pasas? Ya que lo movemos podemos hacer cambios que antes no veiamos
{{ getValueFromPath(title) ?? title }}
</span>
<slot v-else name="description" :entity="entity">
<span :title="entity.name">
{{ entity.name }}
</span>
</slot>
</div>
</QItemLabel>
<QItem>
<QItemLabel class="subtitle">
#{{ getValueFromPath(subtitle) ?? entity.id }}
</QItemLabel>
<QBtn
round
flat
dense
size="sm"
icon="content_copy"
color="primary"
@click.stop="copyIdText(entity.id)"
>
<QTooltip>
{{ t('globals.copyId') }}
</QTooltip>
</QBtn>
</QItem>
</QList>
<div class="list-box q-mt-xs">
<slot name="body" :entity="entity" />
</div>
</div>
<div class="icons">
<slot name="icons" :entity="entity" />
</div>
<div class="actions justify-center" data-cy="descriptor_actions">
<slot name="actions" :entity="entity" />
</div>
<slot name="after" />
</template>
<SkeletonDescriptor v-if="!entity" />
</div>
<QInnerLoading :label="t('globals.pleaseWait')" :showing="!entity" color="primary" />
</template>
<style lang="scss">
.body {
background-color: var(--vn-section-color);
.text-h5 {
font-size: 20px;
padding-top: 5px;
padding-bottom: 0px;
}
.q-item {
min-height: 20px;
.link {
margin-left: 10px;
}
}
.vn-label-value {
display: flex;
padding: 0px 16px;
.label {
color: var(--vn-label-color);
font-size: 14px;
&:not(:has(a))::after {
content: ':';
}
}
.value {
color: var(--vn-text-color);
font-size: 14px;
margin-left: 4px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
text-align: left;
}
.info {
margin-left: 5px;
}
}
}
</style>
<style lang="scss" scoped>
.title {
overflow: hidden;
text-overflow: ellipsis;
span {
color: var(--vn-text-color);
font-weight: bold;
}
}
.subtitle {
color: var(--vn-text-color);
font-size: 16px;
margin-bottom: 2px;
}
.list-box {
.q-item__label {
color: var(--vn-label-color);
padding-bottom: 0%;
}
}
.descriptor {
width: 256px;
.header {
display: flex;
align-items: center;
}
.icons {
margin: 0 10px;
display: flex;
justify-content: center;
.q-icon {
margin-right: 5px;
}
}
.actions {
margin: 0 5px;
justify-content: center !important;
}
}
</style>
<i18n>
alexm marked this conversation as resolved
Review

esto debería estar aquí?

esto debería estar aquí?
en:
globals:
copyId: Copy ID
es:
globals:
copyId: Copiar ID
</i18n>

View File

@ -4,7 +4,7 @@ import { useRoute, useRouter } from 'vue-router';
import { useI18n } from 'vue-i18n';
import { useQuasar } from 'quasar';
import CardDescriptor from 'components/ui/CardDescriptor.vue';
import EntityDescriptor from 'components/ui/EntityDescriptor.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import axios from 'axios';
@ -48,7 +48,7 @@ const removeAlias = () => {
</script>
<template>
<CardDescriptor
<EntityDescriptor
ref="descriptor"
:url="`MailAliases/${entityId}`"
data-key="Alias"
@ -62,7 +62,7 @@ const removeAlias = () => {
<template #body="{ entity }">
<VnLv :label="t('role.description')" :value="entity.description" />
</template>
</CardDescriptor>
</EntityDescriptor>
</template>
<i18n>

View File

@ -1,7 +1,7 @@
<script setup>
import { ref, computed, onMounted } from 'vue';
import { useRoute } from 'vue-router';
import CardDescriptor from 'components/ui/CardDescriptor.vue';
import EntityDescriptor from 'components/ui/EntityDescriptor.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import AccountDescriptorMenu from './AccountDescriptorMenu.vue';
import VnImg from 'src/components/ui/VnImg.vue';
@ -20,7 +20,7 @@ onMounted(async () => {
</script>
<template>
<CardDescriptor
<EntityDescriptor
ref="descriptor"
:url="`VnUsers/preview`"
:filter="{ ...filter, where: { id: entityId } }"
@ -78,7 +78,7 @@ onMounted(async () => {
</QIcon>
</QCardActions>
</template>
</CardDescriptor>
</EntityDescriptor>
</template>
<style scoped>
.q-item__label {

View File

@ -2,7 +2,7 @@
import { computed } from 'vue';
import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n';
import CardDescriptor from 'components/ui/CardDescriptor.vue';
import EntityDescriptor from 'components/ui/EntityDescriptor.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import axios from 'axios';
import useNotify from 'src/composables/useNotify.js';
@ -32,7 +32,7 @@ const removeRole = async () => {
</script>
<template>
<CardDescriptor
<EntityDescriptor
url="VnRoles"
:filter="{ where: { id: entityId } }"
data-key="Role"
@ -46,7 +46,7 @@ const removeRole = async () => {
<template #body="{ entity }">
<VnLv :label="t('role.description')" :value="entity.description" />
</template>
</CardDescriptor>
</EntityDescriptor>
</template>
<style scoped>
.q-item__label {

View File

@ -6,7 +6,7 @@ import { toDateHourMinSec, toPercentage } from 'src/filters';
import TicketDescriptorProxy from 'pages/Ticket/Card/TicketDescriptorProxy.vue';
import ClaimDescriptorMenu from 'pages/Claim/Card/ClaimDescriptorMenu.vue';
import DepartmentDescriptorProxy from 'src/pages/Worker/Department/Card/DepartmentDescriptorProxy.vue';
import CardDescriptor from 'components/ui/CardDescriptor.vue';
import EntityDescriptor from 'components/ui/EntityDescriptor.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import VnUserLink from 'src/components/ui/VnUserLink.vue';
import { getUrl } from 'src/composables/getUrl';
@ -44,7 +44,7 @@ onMounted(async () => {
</script>
<template>
<CardDescriptor
<EntityDescriptor
:url="`Claims/${entityId}`"
:filter="filter"
title="client.name"
@ -147,7 +147,7 @@ onMounted(async () => {
</QBtn>
</QCardActions>
</template>
</CardDescriptor>
</EntityDescriptor>
</template>
<style scoped>
.q-item__label {

View File

@ -7,7 +7,7 @@ import { toCurrency, toDate } from 'src/filters';
import useCardDescription from 'src/composables/useCardDescription';
import CardDescriptor from 'components/ui/CardDescriptor.vue';
import EntityDescriptor from 'components/ui/EntityDescriptor.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import CustomerDescriptorMenu from './CustomerDescriptorMenu.vue';
import DepartmentDescriptorProxy from 'src/pages/Worker/Department/Card/DepartmentDescriptorProxy.vue';
@ -54,7 +54,7 @@ const debtWarning = computed(() => {
</script>
<template>
<CardDescriptor
<EntityDescriptor
:url="`Clients/${entityId}/getCard`"
:summary="$props.summary"
data-key="Customer"
@ -232,7 +232,7 @@ const debtWarning = computed(() => {
</QBtn>
</QCardActions>
</template>
</CardDescriptor>
</EntityDescriptor>
</template>
<i18n>

View File

@ -6,7 +6,7 @@ import { toDate } from 'src/filters';
import { getUrl } from 'src/composables/getUrl';
import { useQuasar } from 'quasar';
import { usePrintService } from 'composables/usePrintService';
import CardDescriptor from 'components/ui/CardDescriptor.vue';
import EntityDescriptor from 'components/ui/EntityDescriptor.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import TravelDescriptorProxy from 'src/pages/Travel/Card/TravelDescriptorProxy.vue';
import axios from 'axios';
@ -145,7 +145,7 @@ async function deleteEntry() {
</script>
<template>
<CardDescriptor
<EntityDescriptor
:url="`Entries/${entityId}`"
:filter="entryFilter"
title="supplier.nickname"
@ -264,7 +264,7 @@ async function deleteEntry() {
</QBtn>
</QCardActions>
</template>
</CardDescriptor>
</EntityDescriptor>
</template>
<i18n>
es:

View File

@ -5,7 +5,7 @@ import { useI18n } from 'vue-i18n';
import axios from 'axios';
import { toCurrency, toDate } from 'src/filters';
import VnLv from 'src/components/ui/VnLv.vue';
import CardDescriptor from 'components/ui/CardDescriptor.vue';
import EntityDescriptor from 'components/ui/EntityDescriptor.vue';
import SupplierDescriptorProxy from 'src/pages/Supplier/Card/SupplierDescriptorProxy.vue';
import filter from './InvoiceInFilter.js';
import InvoiceInDescriptorMenu from './InvoiceInDescriptorMenu.vue';
@ -88,7 +88,7 @@ async function setInvoiceCorrection(id) {
}
</script>
<template>
<CardDescriptor
<EntityDescriptor
ref="cardDescriptorRef"
data-key="InvoiceIn"
:url="`InvoiceIns/${entityId}`"
@ -163,7 +163,7 @@ async function setInvoiceCorrection(id) {
</QBtn>
</QCardActions>
</template>
</CardDescriptor>
</EntityDescriptor>
</template>
<style lang="scss" scoped>
.q-dialog {

View File

@ -3,7 +3,7 @@ import { ref, computed } from 'vue';
import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n';
import CardDescriptor from 'components/ui/CardDescriptor.vue';
import EntityDescriptor from 'components/ui/EntityDescriptor.vue';
import CustomerDescriptorProxy from 'pages/Customer/Card/CustomerDescriptorProxy.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import InvoiceOutDescriptorMenu from './InvoiceOutDescriptorMenu.vue';
@ -34,7 +34,7 @@ function ticketFilter(invoice) {
</script>
<template>
<CardDescriptor
<EntityDescriptor
ref="descriptor"
:url="`InvoiceOuts/${entityId}`"
:filter="filter"
@ -93,5 +93,5 @@ function ticketFilter(invoice) {
</QBtn>
</QCardActions>
</template>
</CardDescriptor>
</EntityDescriptor>
</template>

View File

@ -3,7 +3,7 @@ import { computed, ref, onMounted } from 'vue';
import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n';
import CardDescriptor from 'src/components/ui/CardDescriptor.vue';
import EntityDescriptor from 'src/components/ui/EntityDescriptor.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
import ItemDescriptorImage from 'src/pages/Item/Card/ItemDescriptorImage.vue';
@ -90,7 +90,7 @@ const updateStock = async () => {
</script>
<template>
<CardDescriptor
<EntityDescriptor
data-key="Item"
:summary="$props.summary"
:url="`Items/${entityId}/getCard`"
@ -162,7 +162,7 @@ const updateStock = async () => {
</QBtn>
</QCardActions>
</template>
</CardDescriptor>
</EntityDescriptor>
</template>
<i18n>

View File

@ -2,7 +2,7 @@
import { computed } from 'vue';
import { useRoute } from 'vue-router';
import CardDescriptor from 'components/ui/CardDescriptor.vue';
import EntityDescriptor from 'components/ui/EntityDescriptor.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
import filter from './ItemTypeFilter.js';
@ -25,7 +25,7 @@ const entityId = computed(() => {
});
</script>
<template>
<CardDescriptor
<EntityDescriptor
:url="`ItemTypes/${entityId}`"
:filter="filter"
title="code"
@ -45,5 +45,5 @@ const entityId = computed(() => {
:value="entity.category?.name"
/>
</template>
</CardDescriptor>
</EntityDescriptor>
</template>

View File

@ -6,9 +6,11 @@ import filter from './OrderFilter.js';
<template>
<VnCard
data-key="Order"
:data-key="$attrs['data-key'] ?? 'Order'"
url="Orders"
:filter="filter"
:descriptor="OrderDescriptor"
v-bind="$attrs"
v-on="$attrs"
/>
</template>

View File

@ -4,10 +4,10 @@ import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n';
import { toCurrency, toDate } from 'src/filters';
import { useState } from 'src/composables/useState';
import filter from './OrderFilter.js';
import CardDescriptor from 'components/ui/CardDescriptor.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import FetchData from 'components/FetchData.vue';
import OrderCard from './OrderCard.vue';
import CardDescriptor from 'src/components/ui/CardDescriptor.vue';
import DepartmentDescriptorProxy from 'src/pages/Worker/Department/Card/DepartmentDescriptorProxy.vue';
const DEFAULT_ITEMS = 0;
@ -24,11 +24,14 @@ const route = useRoute();
const state = useState();
const { t } = useI18n();
const getTotalRef = ref();
const total = ref(0);
const entityId = computed(() => {
return $props.id || route.params.id;
});
const orderTotal = computed(() => state.get('orderTotal') ?? 0);
const setData = (entity) => {
if (!entity) return;
getTotalRef.value && getTotalRef.value.fetch();
@ -38,9 +41,6 @@ const setData = (entity) => {
const getConfirmationValue = (isConfirmed) => {
return t(isConfirmed ? 'globals.confirmed' : 'order.summary.notConfirmed');
};
const orderTotal = computed(() => state.get('orderTotal') ?? 0);
const total = ref(0);
</script>
<template>
@ -54,12 +54,12 @@ const total = ref(0);
"
/>
<CardDescriptor
ref="descriptor"
:url="`Orders/${entityId}`"
:filter="filter"
v-bind="$attrs"
:id="entityId"
:card="OrderCard"
title="client.name"
@on-fetch="setData"
data-key="Order"
module="Order"
>
<template #body="{ entity }">
<VnLv

View File

@ -12,6 +12,11 @@ const $props = defineProps({
<template>
<QPopupProxy>
<OrderDescriptor v-if="$props.id" :id="$props.id" :summary="OrderSummary" />
<OrderDescriptor
v-if="$props.id"
:id="$props.id"
:summary="OrderSummary"
data-key="OrderDescriptor"
Outdated
Review

hay que cambiar el dataKey cuando es popup. sino si estas en ticket y abres un ticketDescriptor, te usara el mismo arrayData para los dos

hay que cambiar el dataKey cuando es popup. sino si estas en ticket y abres un ticketDescriptor, te usara el mismo arrayData para los dos

Si si, esto es vital

Si si, esto es vital
/>
</QPopupProxy>
</template>

View File

@ -3,7 +3,7 @@ import { computed } from 'vue';
import { useI18n } from 'vue-i18n';
import { useRoute } from 'vue-router';
import { useArrayData } from 'src/composables/useArrayData';
import CardDescriptor from 'components/ui/CardDescriptor.vue';
import EntityDescriptor from 'components/ui/EntityDescriptor.vue';
import VnLv from 'components/ui/VnLv.vue';
const props = defineProps({
@ -21,7 +21,7 @@ const { store } = useArrayData('Parking');
const card = computed(() => store.data);
</script>
<template>
<CardDescriptor
<EntityDescriptor
data-key="Agency"
:url="`Agencies/${entityId}`"
:title="card?.name"
@ -30,5 +30,5 @@ const card = computed(() => store.data);
<template #body="{ entity: agency }">
<VnLv :label="t('globals.name')" :value="agency.name" />
</template>
</CardDescriptor>
</EntityDescriptor>
</template>

View File

@ -1,7 +1,7 @@
<script setup>
import { ref, computed, onMounted } from 'vue';
import { useRoute } from 'vue-router';
import CardDescriptor from 'components/ui/CardDescriptor.vue';
import EntityDescriptor from 'components/ui/EntityDescriptor.vue';
import VnLv from 'components/ui/VnLv.vue';
import { dashIfEmpty, toDate } from 'src/filters';
import RouteDescriptorMenu from 'pages/Route/Card/RouteDescriptorMenu.vue';
@ -47,7 +47,7 @@ onMounted(async () => {
});
</script>
<template>
<CardDescriptor
<EntityDescriptor
:url="`Routes/${entityId}`"
:filter="filter"
:title="null"
@ -69,7 +69,7 @@ onMounted(async () => {
<template #menu="{ entity }">
<RouteDescriptorMenu :route="entity" />
</template>
</CardDescriptor>
</EntityDescriptor>
</template>
<i18n>
es:

View File

@ -2,7 +2,7 @@
import { computed } from 'vue';
import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n';
import CardDescriptor from 'components/ui/CardDescriptor.vue';
import EntityDescriptor from 'components/ui/EntityDescriptor.vue';
import VnLv from 'components/ui/VnLv.vue';
import { dashIfEmpty, toDateHourMin } from 'src/filters';
import SupplierDescriptorProxy from 'pages/Supplier/Card/SupplierDescriptorProxy.vue';
@ -30,7 +30,7 @@ const entityId = computed(() => {
</script>
<template>
<CardDescriptor
<EntityDescriptor
:url="`Roadmaps/${entityId}`"
:filter="filter"
data-key="Roadmap"
@ -51,7 +51,7 @@ const entityId = computed(() => {
<template #menu="{ entity }">
<RoadmapDescriptorMenu :route="entity" />
</template>
</CardDescriptor>
</EntityDescriptor>
</template>
<i18n>
es:

View File

@ -2,7 +2,7 @@
import { computed } from 'vue';
import { useRoute } from 'vue-router';
import VnLv from 'src/components/ui/VnLv.vue';
import CardDescriptor from 'components/ui/CardDescriptor.vue';
import EntityDescriptor from 'components/ui/EntityDescriptor.vue';
import axios from 'axios';
import useNotify from 'src/composables/useNotify.js';
@ -20,7 +20,7 @@ const route = useRoute();
const entityId = computed(() => props.id || route.params.id);
</script>
<template>
<CardDescriptor
<EntityDescriptor
:url="`Vehicles/${entityId}`"
data-key="Vehicle"
title="numberPlate"
@ -53,7 +53,7 @@ const entityId = computed(() => props.id || route.params.id);
<VnLv :label="$t('globals.model')" :value="entity.model" />
<VnLv :label="$t('globals.country')" :value="entity.countryCodeFk" />
</template>
</CardDescriptor>
</EntityDescriptor>
</template>
<i18n>
es:

View File

@ -2,7 +2,7 @@
import { computed } from 'vue';
import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n';
import CardDescriptor from 'components/ui/CardDescriptor.vue';
import EntityDescriptor from 'components/ui/EntityDescriptor.vue';
import VnLv from 'components/ui/VnLv.vue';
import ShelvingDescriptorMenu from 'pages/Shelving/Card/ShelvingDescriptorMenu.vue';
import VnUserLink from 'src/components/ui/VnUserLink.vue';
@ -24,7 +24,7 @@ const entityId = computed(() => {
});
</script>
<template>
<CardDescriptor
<EntityDescriptor
:url="`Shelvings/${entityId}`"
:filter="filter"
title="code"
@ -45,5 +45,5 @@ const entityId = computed(() => {
<template #menu="{ entity }">
<ShelvingDescriptorMenu :shelving="entity" />
</template>
</CardDescriptor>
</EntityDescriptor>
</template>

View File

@ -1,7 +1,7 @@
<script setup>
import { computed } from 'vue';
import { useRoute } from 'vue-router';
import CardDescriptor from 'components/ui/CardDescriptor.vue';
import EntityDescriptor from 'components/ui/EntityDescriptor.vue';
import VnLv from 'components/ui/VnLv.vue';
import filter from './ParkingFilter.js';
const props = defineProps({
@ -16,7 +16,7 @@ const route = useRoute();
const entityId = computed(() => props.id || route.params.id);
</script>
<template>
<CardDescriptor
<EntityDescriptor
data-key="Parking"
:url="`Parkings/${entityId}`"
title="code"
@ -28,5 +28,5 @@ const entityId = computed(() => props.id || route.params.id);
<VnLv :label="$t('parking.pickingOrder')" :value="entity.pickingOrder" />
<VnLv :label="$t('parking.sector')" :value="entity.sector?.description" />
</template>
</CardDescriptor>
</EntityDescriptor>
</template>

View File

@ -3,7 +3,7 @@ import { ref, computed, onMounted } from 'vue';
import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n';
import CardDescriptor from 'components/ui/CardDescriptor.vue';
import EntityDescriptor from 'components/ui/EntityDescriptor.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import { toDateString } from 'src/filters';
@ -61,7 +61,7 @@ const getEntryQueryParams = (supplier) => {
</script>
<template>
<CardDescriptor
<EntityDescriptor
:url="`Suppliers/${entityId}`"
:filter="filter"
data-key="Supplier"
@ -136,7 +136,7 @@ const getEntryQueryParams = (supplier) => {
</QBtn>
</QCardActions>
</template>
</CardDescriptor>
</EntityDescriptor>
</template>
<i18n>

View File

@ -4,7 +4,7 @@ import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n';
import CustomerDescriptorProxy from 'pages/Customer/Card/CustomerDescriptorProxy.vue';
import DepartmentDescriptorProxy from 'pages/Worker/Department/Card/DepartmentDescriptorProxy.vue';
import CardDescriptor from 'components/ui/CardDescriptor.vue';
import EntityDescriptor from 'components/ui/EntityDescriptor.vue';
import TicketDescriptorMenu from './TicketDescriptorMenu.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import { toDateTimeFormat } from 'src/filters/date';
@ -57,7 +57,7 @@ function getInfo() {
</script>
<template>
<CardDescriptor
<EntityDescriptor
:url="`Tickets/${entityId}`"
:filter="filter"
data-key="Ticket"
@ -155,7 +155,7 @@ function getInfo() {
</QBtn>
</QCardActions>
</template>
</CardDescriptor>
</EntityDescriptor>
</template>
<i18n>

View File

@ -3,7 +3,7 @@ import { computed, ref } from 'vue';
import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n';
import CardDescriptor from 'components/ui/CardDescriptor.vue';
import EntityDescriptor from 'components/ui/EntityDescriptor.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import useCardDescription from 'src/composables/useCardDescription';
import TravelDescriptorMenuItems from './TravelDescriptorMenuItems.vue';
@ -31,7 +31,7 @@ const setData = (entity) => (data.value = useCardDescription(entity.ref, entity.
</script>
<template>
<CardDescriptor
<EntityDescriptor
:url="`Travels/${entityId}`"
:title="data.title"
:subtitle="data.subtitle"
@ -79,7 +79,7 @@ const setData = (entity) => (data.value = useCardDescription(entity.ref, entity.
</QBtn>
</QCardActions>
</template>
</CardDescriptor>
</EntityDescriptor>
</template>
<i18n>

View File

@ -2,7 +2,7 @@
import { computed, ref } from 'vue';
import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n';
import CardDescriptor from 'src/components/ui/CardDescriptor.vue';
import EntityDescriptor from 'src/components/ui/EntityDescriptor.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import VnLinkPhone from 'src/components/ui/VnLinkPhone.vue';
import VnChangePassword from 'src/components/common/VnChangePassword.vue';
@ -52,7 +52,7 @@ const handlePhotoUpdated = (evt = false) => {
};
</script>
<template>
<CardDescriptor
<EntityDescriptor
ref="cardDescriptorRef"
:data-key="dataKey"
:summary="$props.summary"
@ -167,7 +167,7 @@ const handlePhotoUpdated = (evt = false) => {
</QBtn>
</QCardActions>
</template>
</CardDescriptor>
</EntityDescriptor>
<VnChangePassword
ref="changePassRef"
:submit-fn="

View File

@ -4,7 +4,7 @@ import { useRoute, useRouter } from 'vue-router';
import { useI18n } from 'vue-i18n';
import { useVnConfirm } from 'composables/useVnConfirm';
import VnLv from 'src/components/ui/VnLv.vue';
import CardDescriptor from 'src/components/ui/CardDescriptor.vue';
import EntityDescriptor from 'src/components/ui/EntityDescriptor.vue';
import axios from 'axios';
import useNotify from 'src/composables/useNotify.js';
@ -40,7 +40,7 @@ const removeDepartment = async () => {
const { openConfirmationModal } = useVnConfirm();
</script>
<template>
<CardDescriptor
<EntityDescriptor
ref="DepartmentDescriptorRef"
:url="`Departments/${entityId}`"
:summary="$props.summary"
@ -95,7 +95,7 @@ const { openConfirmationModal } = useVnConfirm();
</QBtn>
</QCardActions>
</template>
</CardDescriptor>
</EntityDescriptor>
</template>
<i18n>

View File

@ -2,7 +2,7 @@
import { computed } from 'vue';
import { useRoute } from 'vue-router';
import CardDescriptor from 'components/ui/CardDescriptor.vue';
import EntityDescriptor from 'components/ui/EntityDescriptor.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import { toTimeFormat } from 'src/filters/date';
import { toCurrency } from 'filters/index';
@ -25,7 +25,7 @@ const entityId = computed(() => {
</script>
<template>
<CardDescriptor :url="`Zones/${entityId}`" :filter="filter" data-key="Zone">
<EntityDescriptor :url="`Zones/${entityId}`" :filter="filter" data-key="Zone">
<template #menu="{ entity }">
<ZoneDescriptorMenuItems :zone="entity" />
</template>
@ -36,5 +36,5 @@ const entityId = computed(() => {
<VnLv :label="$t('list.price')" :value="toCurrency(entity.price)" />
<VnLv :label="$t('zone.bonus')" :value="toCurrency(entity.bonus)" />
</template>
</CardDescriptor>
</EntityDescriptor>
</template>