Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix-front into 8717-reviewAndFixAgencySection
gitea/salix-front/pipeline/pr-dev There was a failure building this commit
Details
gitea/salix-front/pipeline/pr-dev There was a failure building this commit
Details
This commit is contained in:
commit
e28f30d7e9
|
@ -126,7 +126,7 @@ pipeline {
|
||||||
sh "docker-compose ${env.COMPOSE_PARAMS} up -d"
|
sh "docker-compose ${env.COMPOSE_PARAMS} up -d"
|
||||||
|
|
||||||
image.inside("--network ${env.COMPOSE_PROJECT}_default -e CI -e TZ --init") {
|
image.inside("--network ${env.COMPOSE_PROJECT}_default -e CI -e TZ --init") {
|
||||||
sh 'sh test/cypress/cypressParallel.sh 2'
|
sh 'sh test/cypress/cypressParallel.sh 1'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -633,6 +633,7 @@ const rowCtrlClickFunction = computed(() => {
|
||||||
:data-key="$attrs['data-key']"
|
:data-key="$attrs['data-key']"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
:redirect="redirect"
|
:redirect="redirect"
|
||||||
|
v-bind="$attrs?.['table-filter']"
|
||||||
>
|
>
|
||||||
<template
|
<template
|
||||||
v-for="(_, slotName) in $slots"
|
v-for="(_, slotName) in $slots"
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onBeforeMount } from 'vue';
|
import { onBeforeMount, computed } from 'vue';
|
||||||
import { useRouter, onBeforeRouteUpdate, onBeforeRouteLeave } from 'vue-router';
|
import { useRoute, useRouter, onBeforeRouteUpdate, onBeforeRouteLeave } from 'vue-router';
|
||||||
import { useArrayData } from 'src/composables/useArrayData';
|
import { useArrayData } from 'src/composables/useArrayData';
|
||||||
import { useStateStore } from 'stores/useStateStore';
|
import { useStateStore } from 'stores/useStateStore';
|
||||||
import useCardSize from 'src/composables/useCardSize';
|
import useCardSize from 'src/composables/useCardSize';
|
||||||
import VnSubToolbar from '../ui/VnSubToolbar.vue';
|
import VnSubToolbar from '../ui/VnSubToolbar.vue';
|
||||||
|
|
||||||
|
const emit = defineEmits(['onFetch']);
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
id: { type: Number, required: false, default: null },
|
||||||
dataKey: { type: String, required: true },
|
dataKey: { type: String, required: true },
|
||||||
url: { type: String, default: undefined },
|
url: { type: String, default: undefined },
|
||||||
idInWhere: { type: Boolean, default: false },
|
idInWhere: { type: Boolean, default: false },
|
||||||
|
@ -16,10 +19,13 @@ const props = defineProps({
|
||||||
searchDataKey: { type: String, default: undefined },
|
searchDataKey: { type: String, default: undefined },
|
||||||
searchbarProps: { type: Object, default: undefined },
|
searchbarProps: { type: Object, default: undefined },
|
||||||
redirectOnError: { type: Boolean, default: false },
|
redirectOnError: { type: Boolean, default: false },
|
||||||
|
visual: { type: Boolean, default: true },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
const stateStore = useStateStore();
|
const stateStore = useStateStore();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
const entityId = computed(() => props.id || route?.params?.id);
|
||||||
const arrayData = useArrayData(props.dataKey, {
|
const arrayData = useArrayData(props.dataKey, {
|
||||||
url: props.url,
|
url: props.url,
|
||||||
userFilter: props.filter,
|
userFilter: props.filter,
|
||||||
|
@ -35,7 +41,7 @@ onBeforeMount(async () => {
|
||||||
|
|
||||||
const route = router.currentRoute.value;
|
const route = router.currentRoute.value;
|
||||||
try {
|
try {
|
||||||
await fetch(route.params.id);
|
await fetch(entityId.value);
|
||||||
} catch {
|
} catch {
|
||||||
const { matched: matches } = route;
|
const { matched: matches } = route;
|
||||||
const { path } = matches.at(-1);
|
const { path } = matches.at(-1);
|
||||||
|
@ -51,8 +57,7 @@ onBeforeRouteUpdate(async (to, from) => {
|
||||||
router.push({ name, params: to.params });
|
router.push({ name, params: to.params });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const id = to.params.id;
|
if (entityId.value !== to.params.id) await fetch(to.params.id, true);
|
||||||
if (id !== from.params.id) await fetch(id, true);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
async function fetch(id, append = false) {
|
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 if (!regex.test(props.url)) arrayData.store.url = `${props.url}/${id}`;
|
||||||
else arrayData.store.url = props.url.replace(regex, `/${id}`);
|
else arrayData.store.url = props.url.replace(regex, `/${id}`);
|
||||||
await arrayData.fetch({ append, updateRouter: false });
|
await arrayData.fetch({ append, updateRouter: false });
|
||||||
|
emit('onFetch', arrayData.store.data);
|
||||||
}
|
}
|
||||||
function hasRouteParam(params, valueToCheck = ':addressId') {
|
function hasRouteParam(params, valueToCheck = ':addressId') {
|
||||||
return Object.values(params).includes(valueToCheck);
|
return Object.values(params).includes(valueToCheck);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<VnSubToolbar />
|
<template v-if="visual">
|
||||||
<div :class="[useCardSize(), $attrs.class]">
|
<VnSubToolbar />
|
||||||
<RouterView :key="$route.path" />
|
<div :class="[useCardSize(), $attrs.class]">
|
||||||
</div>
|
<RouterView :key="$route.path" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, toRefs, computed, watch, onMounted, useAttrs } from 'vue';
|
import { ref, toRefs, computed, watch, onMounted, useAttrs, nextTick } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useArrayData } from 'src/composables/useArrayData';
|
import { useArrayData } from 'src/composables/useArrayData';
|
||||||
import { useRequired } from 'src/composables/useRequired';
|
import { useRequired } from 'src/composables/useRequired';
|
||||||
|
@ -247,6 +247,7 @@ async function fetchFilter(val) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function filterHandler(val, update) {
|
async function filterHandler(val, update) {
|
||||||
|
if (isLoading.value) return update();
|
||||||
if (!val && lastVal.value === val) {
|
if (!val && lastVal.value === val) {
|
||||||
lastVal.value = val;
|
lastVal.value = val;
|
||||||
return update();
|
return update();
|
||||||
|
@ -294,6 +295,7 @@ async function onScroll({ to, direction, from, index }) {
|
||||||
await arrayData.loadMore();
|
await arrayData.loadMore();
|
||||||
setOptions(arrayData.store.data);
|
setOptions(arrayData.store.data);
|
||||||
vnSelectRef.value.scrollTo(lastIndex);
|
vnSelectRef.value.scrollTo(lastIndex);
|
||||||
|
await nextTick();
|
||||||
isLoading.value = false;
|
isLoading.value = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,12 +4,15 @@ import { vi, afterEach, beforeAll, describe, expect, it } from 'vitest';
|
||||||
|
|
||||||
describe('VnDmsList', () => {
|
describe('VnDmsList', () => {
|
||||||
let vm;
|
let vm;
|
||||||
const dms = {
|
const dms = {
|
||||||
userFk: 1,
|
userFk: 1,
|
||||||
name: 'DMS 1'
|
name: 'DMS 1',
|
||||||
};
|
};
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
|
vi.mock('src/composables/getUrl', () => ({
|
||||||
|
getUrl: vi.fn().mockResolvedValue(''),
|
||||||
|
}));
|
||||||
vi.spyOn(axios, 'get').mockResolvedValue({ data: [] });
|
vi.spyOn(axios, 'get').mockResolvedValue({ data: [] });
|
||||||
vm = createWrapper(VnDmsList, {
|
vm = createWrapper(VnDmsList, {
|
||||||
props: {
|
props: {
|
||||||
|
@ -18,8 +21,8 @@ describe('VnDmsList', () => {
|
||||||
filter: 'wd.workerFk',
|
filter: 'wd.workerFk',
|
||||||
updateModel: 'Workers',
|
updateModel: 'Workers',
|
||||||
deleteModel: 'WorkerDms',
|
deleteModel: 'WorkerDms',
|
||||||
downloadModel: 'WorkerDms'
|
downloadModel: 'WorkerDms',
|
||||||
}
|
},
|
||||||
}).vm;
|
}).vm;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -29,46 +32,45 @@ describe('VnDmsList', () => {
|
||||||
|
|
||||||
describe('setData()', () => {
|
describe('setData()', () => {
|
||||||
const data = [
|
const data = [
|
||||||
{
|
{
|
||||||
userFk: 1,
|
userFk: 1,
|
||||||
name: 'Jessica',
|
name: 'Jessica',
|
||||||
lastName: 'Jones',
|
lastName: 'Jones',
|
||||||
file: '4.jpg',
|
file: '4.jpg',
|
||||||
created: '2021-07-28 21:00:00'
|
created: '2021-07-28 21:00:00',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
userFk: 2,
|
userFk: 2,
|
||||||
name: 'Bruce',
|
name: 'Bruce',
|
||||||
lastName: 'Banner',
|
lastName: 'Banner',
|
||||||
created: '2022-07-28 21:00:00',
|
created: '2022-07-28 21:00:00',
|
||||||
dms: {
|
dms: {
|
||||||
userFk: 2,
|
userFk: 2,
|
||||||
name: 'Bruce',
|
name: 'Bruce',
|
||||||
lastName: 'BannerDMS',
|
lastName: 'BannerDMS',
|
||||||
created: '2022-07-28 21:00:00',
|
created: '2022-07-28 21:00:00',
|
||||||
file: '4.jpg',
|
file: '4.jpg',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
userFk: 3,
|
userFk: 3,
|
||||||
name: 'Natasha',
|
name: 'Natasha',
|
||||||
lastName: 'Romanoff',
|
lastName: 'Romanoff',
|
||||||
file: '4.jpg',
|
file: '4.jpg',
|
||||||
created: '2021-10-28 21:00:00'
|
created: '2021-10-28 21:00:00',
|
||||||
}
|
},
|
||||||
]
|
];
|
||||||
|
|
||||||
it('Should replace objects that contain the "dms" property with the value of the same and sort by creation date', () => {
|
it('Should replace objects that contain the "dms" property with the value of the same and sort by creation date', () => {
|
||||||
vm.setData(data);
|
vm.setData(data);
|
||||||
expect([vm.rows][0][0].lastName).toEqual('BannerDMS');
|
expect([vm.rows][0][0].lastName).toEqual('BannerDMS');
|
||||||
expect([vm.rows][0][1].lastName).toEqual('Romanoff');
|
expect([vm.rows][0][1].lastName).toEqual('Romanoff');
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('parseDms()', () => {
|
describe('parseDms()', () => {
|
||||||
const resultDms = { ...dms, userId:1};
|
const resultDms = { ...dms, userId: 1 };
|
||||||
|
|
||||||
it('Should add properties that end with "Fk" by changing the suffix to "Id"', () => {
|
it('Should add properties that end with "Fk" by changing the suffix to "Id"', () => {
|
||||||
const parsedDms = vm.parseDms(dms);
|
const parsedDms = vm.parseDms(dms);
|
||||||
expect(parsedDms).toEqual(resultDms);
|
expect(parsedDms).toEqual(resultDms);
|
||||||
|
@ -76,12 +78,12 @@ describe('VnDmsList', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('showFormDialog()', () => {
|
describe('showFormDialog()', () => {
|
||||||
const resultDms = { ...dms, userId:1};
|
const resultDms = { ...dms, userId: 1 };
|
||||||
|
|
||||||
it('should call fn parseDms() and set show true if dms is defined', () => {
|
it('should call fn parseDms() and set show true if dms is defined', () => {
|
||||||
vm.showFormDialog(dms);
|
vm.showFormDialog(dms);
|
||||||
expect(vm.formDialog.show).toEqual(true);
|
expect(vm.formDialog.show).toEqual(true);
|
||||||
expect(vm.formDialog.dms).toEqual(resultDms);
|
expect(vm.formDialog.dms).toEqual(resultDms);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,367 +1,38 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onBeforeMount, watch, computed, ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import VnDescriptor from './VnDescriptor.vue';
|
||||||
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';
|
|
||||||
|
|
||||||
const $props = defineProps({
|
const $props = defineProps({
|
||||||
url: {
|
id: {
|
||||||
type: String,
|
|
||||||
default: '',
|
|
||||||
},
|
|
||||||
filter: {
|
|
||||||
type: Object,
|
|
||||||
default: null,
|
|
||||||
},
|
|
||||||
title: {
|
|
||||||
type: String,
|
|
||||||
default: '',
|
|
||||||
},
|
|
||||||
subtitle: {
|
|
||||||
type: Number,
|
type: Number,
|
||||||
default: null,
|
default: false,
|
||||||
},
|
},
|
||||||
dataKey: {
|
card: {
|
||||||
type: String,
|
|
||||||
default: null,
|
|
||||||
},
|
|
||||||
summary: {
|
|
||||||
type: Object,
|
type: Object,
|
||||||
default: null,
|
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 emit = defineEmits(['onFetch']);
|
||||||
|
const entity = ref();
|
||||||
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>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="descriptor" data-cy="cardDescriptor">
|
<component
|
||||||
<template v-if="entity && !isLoading">
|
:is="card"
|
||||||
<div class="header bg-primary q-pa-sm justify-between">
|
:id
|
||||||
<slot name="header-extra-action">
|
:visual="false"
|
||||||
<QBtn
|
v-bind="$attrs"
|
||||||
round
|
@on-fetch="
|
||||||
flat
|
(data) => {
|
||||||
dense
|
entity = data;
|
||||||
size="md"
|
emit('onFetch', data);
|
||||||
: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"
|
|
||||||
data-cy="openSummaryBtn"
|
|
||||||
>
|
|
||||||
<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"
|
|
||||||
data-cy="goToSummaryBtn"
|
|
||||||
>
|
|
||||||
<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)"
|
|
||||||
:data-cy="`${$attrs['data-cy'] ?? 'cardDescriptor'}_title`"
|
|
||||||
>
|
|
||||||
{{ getValueFromPath(title) ?? $props.title }}
|
|
||||||
</span>
|
|
||||||
<slot v-else name="description" :entity="entity">
|
|
||||||
<span
|
|
||||||
:title="entity.name"
|
|
||||||
:data-cy="`${$attrs['data-cy'] ?? 'cardDescriptor'}_description`"
|
|
||||||
v-text="entity.name"
|
|
||||||
/>
|
|
||||||
</slot>
|
|
||||||
</div>
|
|
||||||
</QItemLabel>
|
|
||||||
<QItem>
|
|
||||||
<QItemLabel
|
|
||||||
class="subtitle"
|
|
||||||
:data-cy="`${$attrs['data-cy'] ?? 'cardDescriptor'}_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"
|
|
||||||
:data-cy="`${$attrs['data-cy'] ?? 'cardDescriptor'}_listbox`"
|
|
||||||
>
|
|
||||||
<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: ':';
|
|
||||||
}
|
}
|
||||||
}
|
"
|
||||||
.value {
|
/>
|
||||||
color: var(--vn-text-color);
|
<VnDescriptor v-model="entity" v-bind="$attrs">
|
||||||
font-size: 14px;
|
<template v-for="(_, slotName) in $slots" #[slotName]="slotData" :key="slotName">
|
||||||
margin-left: 4px;
|
<slot :name="slotName" v-bind="slotData ?? {}" :key="slotName" />
|
||||||
overflow: hidden;
|
</template>
|
||||||
text-overflow: ellipsis;
|
</VnDescriptor>
|
||||||
white-space: nowrap;
|
</template>
|
||||||
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>
|
|
||||||
|
|
|
@ -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>
|
|
@ -0,0 +1,318 @@
|
||||||
|
<script setup>
|
||||||
|
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: null,
|
||||||
|
},
|
||||||
|
toModule: {
|
||||||
|
type: String,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
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 ($props.module.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 ($props.toModule) {
|
||||||
|
return router.getRoutes().find((r) => r.name === $props.toModule.name).meta.icon;
|
||||||
|
}
|
||||||
|
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 ($props.toModule) return $props.toModule;
|
||||||
|
if (isSameModuleName) {
|
||||||
|
return router.options.routes[1].children.find((r) => r.name === moduleName.value)
|
||||||
|
?.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" data-cy="vnDescriptor">
|
||||||
|
<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"
|
||||||
|
data-cy="openSummaryBtn"
|
||||||
|
>
|
||||||
|
<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"
|
||||||
|
data-cy="goToSummaryBtn"
|
||||||
|
>
|
||||||
|
<QTooltip>
|
||||||
|
{{ t('components.vnDescriptor.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)"
|
||||||
|
:data-cy="`${$attrs['data-cy'] ?? 'vnDescriptor'}_title`"
|
||||||
|
>
|
||||||
|
{{ getValueFromPath(title) ?? title }}
|
||||||
|
</span>
|
||||||
|
<slot v-else name="description" :entity="entity">
|
||||||
|
<span
|
||||||
|
:title="entity.name"
|
||||||
|
:data-cy="`${$attrs['data-cy'] ?? 'vnDescriptor'}_description`"
|
||||||
|
v-text="entity.name"
|
||||||
|
/>
|
||||||
|
</slot>
|
||||||
|
</div>
|
||||||
|
</QItemLabel>
|
||||||
|
<QItem>
|
||||||
|
<QItemLabel
|
||||||
|
class="subtitle"
|
||||||
|
:data-cy="`${$attrs['data-cy'] ?? 'vnDescriptor'}_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"
|
||||||
|
:data-cy="`${$attrs['data-cy'] ?? 'vnDescriptor'}_listbox`"
|
||||||
|
>
|
||||||
|
<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>
|
||||||
|
en:
|
||||||
|
globals:
|
||||||
|
copyId: Copy ID
|
||||||
|
es:
|
||||||
|
globals:
|
||||||
|
copyId: Copiar ID
|
||||||
|
</i18n>
|
|
@ -6,10 +6,12 @@ const session = useSession();
|
||||||
const token = session.getToken();
|
const token = session.getToken();
|
||||||
|
|
||||||
describe('downloadFile', () => {
|
describe('downloadFile', () => {
|
||||||
const baseUrl = 'http://localhost:9000';
|
|
||||||
let defaulCreateObjectURL;
|
let defaulCreateObjectURL;
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
|
vi.mock('src/composables/getUrl', () => ({
|
||||||
|
getUrl: vi.fn().mockResolvedValue(''),
|
||||||
|
}));
|
||||||
defaulCreateObjectURL = window.URL.createObjectURL;
|
defaulCreateObjectURL = window.URL.createObjectURL;
|
||||||
window.URL.createObjectURL = vi.fn(() => 'blob:http://localhost:9000/blob-id');
|
window.URL.createObjectURL = vi.fn(() => 'blob:http://localhost:9000/blob-id');
|
||||||
});
|
});
|
||||||
|
@ -22,15 +24,14 @@ describe('downloadFile', () => {
|
||||||
headers: { 'content-disposition': 'attachment; filename="test-file.txt"' },
|
headers: { 'content-disposition': 'attachment; filename="test-file.txt"' },
|
||||||
};
|
};
|
||||||
vi.spyOn(axios, 'get').mockImplementation((url) => {
|
vi.spyOn(axios, 'get').mockImplementation((url) => {
|
||||||
if (url == 'Urls/getUrl') return Promise.resolve({ data: baseUrl });
|
if (url.includes('downloadFile')) return Promise.resolve(res);
|
||||||
else if (url.includes('downloadFile')) return Promise.resolve(res);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
await downloadFile(1);
|
await downloadFile(1);
|
||||||
|
|
||||||
expect(axios.get).toHaveBeenCalledWith(
|
expect(axios.get).toHaveBeenCalledWith(
|
||||||
`${baseUrl}/api/dms/1/downloadFile?access_token=${token}`,
|
`/api/dms/1/downloadFile?access_token=${token}`,
|
||||||
{ responseType: 'blob' }
|
{ responseType: 'blob' },
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,20 +5,30 @@ import { exportFile } from 'quasar';
|
||||||
|
|
||||||
const { getTokenMultimedia } = useSession();
|
const { getTokenMultimedia } = useSession();
|
||||||
const token = getTokenMultimedia();
|
const token = getTokenMultimedia();
|
||||||
|
const appUrl = (await getUrl('', 'lilium')).replace('/#/', '');
|
||||||
|
|
||||||
export async function downloadFile(id, model = 'dms', urlPath = '/downloadFile', url) {
|
export async function downloadFile(id, model = 'dms', urlPath = '/downloadFile', url) {
|
||||||
const appUrl = (await getUrl('', 'lilium')).replace('/#/', '');
|
|
||||||
const response = await axios.get(
|
const response = await axios.get(
|
||||||
url ?? `${appUrl}/api/${model}/${id}${urlPath}?access_token=${token}`,
|
url ?? `${appUrl}/api/${model}/${id}${urlPath}?access_token=${token}`,
|
||||||
{ responseType: 'blob' }
|
{ responseType: 'blob' }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
download(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function downloadDocuware(url, params) {
|
||||||
|
const response = await axios.get(`${appUrl}/api/` + url, {
|
||||||
|
responseType: 'blob',
|
||||||
|
params,
|
||||||
|
});
|
||||||
|
|
||||||
|
download(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
function download(response) {
|
||||||
const contentDisposition = response.headers['content-disposition'];
|
const contentDisposition = response.headers['content-disposition'];
|
||||||
const matches = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/.exec(contentDisposition);
|
const matches = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/.exec(contentDisposition);
|
||||||
const filename =
|
const filename = matches?.[1] ? matches[1].replace(/['"]/g, '') : 'downloaded-file';
|
||||||
matches != null && matches[1]
|
|
||||||
? matches[1].replace(/['"]/g, '')
|
|
||||||
: 'downloaded-file';
|
|
||||||
|
|
||||||
exportFile(filename, response.data);
|
exportFile(filename, response.data);
|
||||||
}
|
}
|
||||||
|
|
|
@ -646,6 +646,7 @@ worker:
|
||||||
model: Model
|
model: Model
|
||||||
serialNumber: Serial number
|
serialNumber: Serial number
|
||||||
removePDA: Deallocate PDA
|
removePDA: Deallocate PDA
|
||||||
|
sendToTablet: Send to tablet
|
||||||
create:
|
create:
|
||||||
lastName: Last name
|
lastName: Last name
|
||||||
birth: Birth
|
birth: Birth
|
||||||
|
@ -892,6 +893,8 @@ components:
|
||||||
VnLv:
|
VnLv:
|
||||||
copyText: '{copyValue} has been copied to the clipboard'
|
copyText: '{copyValue} has been copied to the clipboard'
|
||||||
iban_tooltip: 'IBAN: ES21 1234 5678 90 0123456789'
|
iban_tooltip: 'IBAN: ES21 1234 5678 90 0123456789'
|
||||||
|
VnNotes:
|
||||||
|
clientWithoutPhone: 'The following clients do not have a phone number and the message will not be sent to them: {clientWithoutPhone}'
|
||||||
weekdays:
|
weekdays:
|
||||||
sun: Sunday
|
sun: Sunday
|
||||||
mon: Monday
|
mon: Monday
|
||||||
|
|
|
@ -731,6 +731,7 @@ worker:
|
||||||
model: Modelo
|
model: Modelo
|
||||||
serialNumber: Número de serie
|
serialNumber: Número de serie
|
||||||
removePDA: Desasignar PDA
|
removePDA: Desasignar PDA
|
||||||
|
sendToTablet: Enviar a la tablet
|
||||||
create:
|
create:
|
||||||
lastName: Apellido
|
lastName: Apellido
|
||||||
birth: Fecha de nacimiento
|
birth: Fecha de nacimiento
|
||||||
|
@ -976,6 +977,8 @@ components:
|
||||||
VnLv:
|
VnLv:
|
||||||
copyText: '{copyValue} se ha copiado al portapepeles'
|
copyText: '{copyValue} se ha copiado al portapepeles'
|
||||||
iban_tooltip: 'IBAN: ES21 1234 5678 90 0123456789'
|
iban_tooltip: 'IBAN: ES21 1234 5678 90 0123456789'
|
||||||
|
VnNotes:
|
||||||
|
clientWithoutPhone: 'Estos clientes no tienen asociado número de télefono y el sms no les será enviado: {clientWithoutPhone}'
|
||||||
weekdays:
|
weekdays:
|
||||||
sun: Domingo
|
sun: Domingo
|
||||||
mon: Lunes
|
mon: Lunes
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { useRoute, useRouter } from 'vue-router';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useQuasar } from 'quasar';
|
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 VnLv from 'src/components/ui/VnLv.vue';
|
||||||
|
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
@ -48,11 +48,12 @@ const removeAlias = () => {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<CardDescriptor
|
<EntityDescriptor
|
||||||
ref="descriptor"
|
ref="descriptor"
|
||||||
:url="`MailAliases/${entityId}`"
|
:url="`MailAliases/${entityId}`"
|
||||||
data-key="Alias"
|
data-key="Alias"
|
||||||
title="alias"
|
title="alias"
|
||||||
|
:to-module="{ name: 'AccountAlias' }"
|
||||||
>
|
>
|
||||||
<template #menu>
|
<template #menu>
|
||||||
<QItem v-ripple clickable @click="removeAlias()">
|
<QItem v-ripple clickable @click="removeAlias()">
|
||||||
|
@ -62,7 +63,7 @@ const removeAlias = () => {
|
||||||
<template #body="{ entity }">
|
<template #body="{ entity }">
|
||||||
<VnLv :label="t('role.description')" :value="entity.description" />
|
<VnLv :label="t('role.description')" :value="entity.description" />
|
||||||
</template>
|
</template>
|
||||||
</CardDescriptor>
|
</EntityDescriptor>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<i18n>
|
<i18n>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, onMounted } from 'vue';
|
import { ref, computed, onMounted } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
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 VnLv from 'src/components/ui/VnLv.vue';
|
||||||
import AccountDescriptorMenu from './AccountDescriptorMenu.vue';
|
import AccountDescriptorMenu from './AccountDescriptorMenu.vue';
|
||||||
import VnImg from 'src/components/ui/VnImg.vue';
|
import VnImg from 'src/components/ui/VnImg.vue';
|
||||||
|
@ -20,7 +20,7 @@ onMounted(async () => {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<CardDescriptor
|
<EntityDescriptor
|
||||||
ref="descriptor"
|
ref="descriptor"
|
||||||
:url="`VnUsers/preview`"
|
:url="`VnUsers/preview`"
|
||||||
:filter="{ ...filter, where: { id: entityId } }"
|
:filter="{ ...filter, where: { id: entityId } }"
|
||||||
|
@ -78,7 +78,7 @@ onMounted(async () => {
|
||||||
</QIcon>
|
</QIcon>
|
||||||
</QCardActions>
|
</QCardActions>
|
||||||
</template>
|
</template>
|
||||||
</CardDescriptor>
|
</EntityDescriptor>
|
||||||
</template>
|
</template>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.q-item__label {
|
.q-item__label {
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { useI18n } from 'vue-i18n';
|
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 VnLv from 'src/components/ui/VnLv.vue';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import useNotify from 'src/composables/useNotify.js';
|
import useNotify from 'src/composables/useNotify.js';
|
||||||
|
@ -32,11 +32,12 @@ const removeRole = async () => {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<CardDescriptor
|
<EntityDescriptor
|
||||||
url="VnRoles"
|
url="VnRoles"
|
||||||
:filter="{ where: { id: entityId } }"
|
:filter="{ where: { id: entityId } }"
|
||||||
data-key="Role"
|
data-key="Role"
|
||||||
:summary="$props.summary"
|
:summary="$props.summary"
|
||||||
|
:to-module="{ name: 'AccountRoles' }"
|
||||||
>
|
>
|
||||||
<template #menu>
|
<template #menu>
|
||||||
<QItem v-ripple clickable @click="removeRole()">
|
<QItem v-ripple clickable @click="removeRole()">
|
||||||
|
@ -46,7 +47,7 @@ const removeRole = async () => {
|
||||||
<template #body="{ entity }">
|
<template #body="{ entity }">
|
||||||
<VnLv :label="t('role.description')" :value="entity.description" />
|
<VnLv :label="t('role.description')" :value="entity.description" />
|
||||||
</template>
|
</template>
|
||||||
</CardDescriptor>
|
</EntityDescriptor>
|
||||||
</template>
|
</template>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.q-item__label {
|
.q-item__label {
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { toDateHourMinSec, toPercentage } from 'src/filters';
|
||||||
import TicketDescriptorProxy from 'pages/Ticket/Card/TicketDescriptorProxy.vue';
|
import TicketDescriptorProxy from 'pages/Ticket/Card/TicketDescriptorProxy.vue';
|
||||||
import ClaimDescriptorMenu from 'pages/Claim/Card/ClaimDescriptorMenu.vue';
|
import ClaimDescriptorMenu from 'pages/Claim/Card/ClaimDescriptorMenu.vue';
|
||||||
import DepartmentDescriptorProxy from 'src/pages/Worker/Department/Card/DepartmentDescriptorProxy.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 VnLv from 'src/components/ui/VnLv.vue';
|
||||||
import VnUserLink from 'src/components/ui/VnUserLink.vue';
|
import VnUserLink from 'src/components/ui/VnUserLink.vue';
|
||||||
import { getUrl } from 'src/composables/getUrl';
|
import { getUrl } from 'src/composables/getUrl';
|
||||||
|
@ -44,7 +44,7 @@ onMounted(async () => {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<CardDescriptor
|
<EntityDescriptor
|
||||||
:url="`Claims/${entityId}`"
|
:url="`Claims/${entityId}`"
|
||||||
:filter="filter"
|
:filter="filter"
|
||||||
title="client.name"
|
title="client.name"
|
||||||
|
@ -147,7 +147,7 @@ onMounted(async () => {
|
||||||
</QBtn>
|
</QBtn>
|
||||||
</QCardActions>
|
</QCardActions>
|
||||||
</template>
|
</template>
|
||||||
</CardDescriptor>
|
</EntityDescriptor>
|
||||||
</template>
|
</template>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.q-item__label {
|
.q-item__label {
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { toCurrency, toDate } from 'src/filters';
|
||||||
|
|
||||||
import useCardDescription from 'src/composables/useCardDescription';
|
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 VnLv from 'src/components/ui/VnLv.vue';
|
||||||
import CustomerDescriptorMenu from './CustomerDescriptorMenu.vue';
|
import CustomerDescriptorMenu from './CustomerDescriptorMenu.vue';
|
||||||
import DepartmentDescriptorProxy from 'src/pages/Worker/Department/Card/DepartmentDescriptorProxy.vue';
|
import DepartmentDescriptorProxy from 'src/pages/Worker/Department/Card/DepartmentDescriptorProxy.vue';
|
||||||
|
@ -54,7 +54,7 @@ const debtWarning = computed(() => {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<CardDescriptor
|
<EntityDescriptor
|
||||||
:url="`Clients/${entityId}/getCard`"
|
:url="`Clients/${entityId}/getCard`"
|
||||||
:summary="$props.summary"
|
:summary="$props.summary"
|
||||||
data-key="Customer"
|
data-key="Customer"
|
||||||
|
@ -232,7 +232,7 @@ const debtWarning = computed(() => {
|
||||||
</QBtn>
|
</QBtn>
|
||||||
</QCardActions>
|
</QCardActions>
|
||||||
</template>
|
</template>
|
||||||
</CardDescriptor>
|
</EntityDescriptor>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<i18n>
|
<i18n>
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { toDate } from 'src/filters';
|
||||||
import { getUrl } from 'src/composables/getUrl';
|
import { getUrl } from 'src/composables/getUrl';
|
||||||
import { useQuasar } from 'quasar';
|
import { useQuasar } from 'quasar';
|
||||||
import { usePrintService } from 'composables/usePrintService';
|
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 VnLv from 'src/components/ui/VnLv.vue';
|
||||||
import TravelDescriptorProxy from 'src/pages/Travel/Card/TravelDescriptorProxy.vue';
|
import TravelDescriptorProxy from 'src/pages/Travel/Card/TravelDescriptorProxy.vue';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
@ -145,7 +145,7 @@ async function deleteEntry() {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<CardDescriptor
|
<EntityDescriptor
|
||||||
:url="`Entries/${entityId}`"
|
:url="`Entries/${entityId}`"
|
||||||
:filter="entryFilter"
|
:filter="entryFilter"
|
||||||
title="supplier.nickname"
|
title="supplier.nickname"
|
||||||
|
@ -264,7 +264,7 @@ async function deleteEntry() {
|
||||||
</QBtn>
|
</QBtn>
|
||||||
</QCardActions>
|
</QCardActions>
|
||||||
</template>
|
</template>
|
||||||
</CardDescriptor>
|
</EntityDescriptor>
|
||||||
</template>
|
</template>
|
||||||
<i18n>
|
<i18n>
|
||||||
es:
|
es:
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { useI18n } from 'vue-i18n';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { toCurrency, toDate } from 'src/filters';
|
import { toCurrency, toDate } from 'src/filters';
|
||||||
import VnLv from 'src/components/ui/VnLv.vue';
|
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 SupplierDescriptorProxy from 'src/pages/Supplier/Card/SupplierDescriptorProxy.vue';
|
||||||
import filter from './InvoiceInFilter.js';
|
import filter from './InvoiceInFilter.js';
|
||||||
import InvoiceInDescriptorMenu from './InvoiceInDescriptorMenu.vue';
|
import InvoiceInDescriptorMenu from './InvoiceInDescriptorMenu.vue';
|
||||||
|
@ -84,7 +84,7 @@ async function setInvoiceCorrection(id) {
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<CardDescriptor
|
<EntityDescriptor
|
||||||
ref="cardDescriptorRef"
|
ref="cardDescriptorRef"
|
||||||
data-key="InvoiceIn"
|
data-key="InvoiceIn"
|
||||||
:url="`InvoiceIns/${entityId}`"
|
:url="`InvoiceIns/${entityId}`"
|
||||||
|
@ -159,7 +159,7 @@ async function setInvoiceCorrection(id) {
|
||||||
</QBtn>
|
</QBtn>
|
||||||
</QCardActions>
|
</QCardActions>
|
||||||
</template>
|
</template>
|
||||||
</CardDescriptor>
|
</EntityDescriptor>
|
||||||
</template>
|
</template>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.q-dialog {
|
.q-dialog {
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { ref, computed } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { useI18n } from 'vue-i18n';
|
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 CustomerDescriptorProxy from 'pages/Customer/Card/CustomerDescriptorProxy.vue';
|
||||||
import VnLv from 'src/components/ui/VnLv.vue';
|
import VnLv from 'src/components/ui/VnLv.vue';
|
||||||
import InvoiceOutDescriptorMenu from './InvoiceOutDescriptorMenu.vue';
|
import InvoiceOutDescriptorMenu from './InvoiceOutDescriptorMenu.vue';
|
||||||
|
@ -34,7 +34,7 @@ function ticketFilter(invoice) {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<CardDescriptor
|
<EntityDescriptor
|
||||||
ref="descriptor"
|
ref="descriptor"
|
||||||
:url="`InvoiceOuts/${entityId}`"
|
:url="`InvoiceOuts/${entityId}`"
|
||||||
:filter="filter"
|
:filter="filter"
|
||||||
|
@ -93,5 +93,5 @@ function ticketFilter(invoice) {
|
||||||
</QBtn>
|
</QBtn>
|
||||||
</QCardActions>
|
</QCardActions>
|
||||||
</template>
|
</template>
|
||||||
</CardDescriptor>
|
</EntityDescriptor>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { computed, ref, onMounted } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { useI18n } from 'vue-i18n';
|
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 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 ItemDescriptorImage from 'src/pages/Item/Card/ItemDescriptorImage.vue';
|
import ItemDescriptorImage from 'src/pages/Item/Card/ItemDescriptorImage.vue';
|
||||||
|
@ -90,7 +90,7 @@ const updateStock = async () => {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<CardDescriptor
|
<EntityDescriptor
|
||||||
data-key="Item"
|
data-key="Item"
|
||||||
:summary="$props.summary"
|
:summary="$props.summary"
|
||||||
:url="`Items/${entityId}/getCard`"
|
:url="`Items/${entityId}/getCard`"
|
||||||
|
@ -162,7 +162,7 @@ const updateStock = async () => {
|
||||||
</QBtn>
|
</QBtn>
|
||||||
</QCardActions>
|
</QCardActions>
|
||||||
</template>
|
</template>
|
||||||
</CardDescriptor>
|
</EntityDescriptor>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<i18n>
|
<i18n>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
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 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 filter from './ItemTypeFilter.js';
|
import filter from './ItemTypeFilter.js';
|
||||||
|
@ -25,11 +25,12 @@ const entityId = computed(() => {
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<CardDescriptor
|
<EntityDescriptor
|
||||||
:url="`ItemTypes/${entityId}`"
|
:url="`ItemTypes/${entityId}`"
|
||||||
:filter="filter"
|
:filter="filter"
|
||||||
title="code"
|
title="code"
|
||||||
data-key="ItemType"
|
data-key="ItemType"
|
||||||
|
:to-module="{ name: 'ItemTypeList' }"
|
||||||
>
|
>
|
||||||
<template #body="{ entity }">
|
<template #body="{ entity }">
|
||||||
<VnLv :label="$t('itemType.shared.code')" :value="entity.code" />
|
<VnLv :label="$t('itemType.shared.code')" :value="entity.code" />
|
||||||
|
@ -45,5 +46,5 @@ const entityId = computed(() => {
|
||||||
:value="entity.category?.name"
|
:value="entity.category?.name"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</CardDescriptor>
|
</EntityDescriptor>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -118,8 +118,6 @@ const getLocale = (label) => {
|
||||||
rounded
|
rounded
|
||||||
:label="t('globals.params.departmentFk')"
|
:label="t('globals.params.departmentFk')"
|
||||||
v-model="params.departmentFk"
|
v-model="params.departmentFk"
|
||||||
option-value="id"
|
|
||||||
option-label="name"
|
|
||||||
url="Departments"
|
url="Departments"
|
||||||
/>
|
/>
|
||||||
</QItemSection>
|
</QItemSection>
|
||||||
|
@ -209,20 +207,6 @@ const getLocale = (label) => {
|
||||||
/>
|
/>
|
||||||
</QItemSection>
|
</QItemSection>
|
||||||
</QItem>
|
</QItem>
|
||||||
<QItem>
|
|
||||||
<QItemSection>
|
|
||||||
<VnSelect
|
|
||||||
outlined
|
|
||||||
dense
|
|
||||||
rounded
|
|
||||||
:label="t('globals.params.departmentFk')"
|
|
||||||
v-model="params.department"
|
|
||||||
option-label="name"
|
|
||||||
option-value="name"
|
|
||||||
url="Departments"
|
|
||||||
/>
|
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
<QItem>
|
<QItem>
|
||||||
<QItemSection>
|
<QItemSection>
|
||||||
<VnSelect
|
<VnSelect
|
||||||
|
|
|
@ -6,9 +6,11 @@ import filter from './OrderFilter.js';
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<VnCard
|
<VnCard
|
||||||
data-key="Order"
|
:data-key="$attrs['data-key'] ?? 'Order'"
|
||||||
url="Orders"
|
url="Orders"
|
||||||
:filter="filter"
|
:filter="filter"
|
||||||
:descriptor="OrderDescriptor"
|
:descriptor="OrderDescriptor"
|
||||||
|
v-bind="$attrs"
|
||||||
|
v-on="$attrs"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -4,10 +4,10 @@ import { useRoute } from 'vue-router';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { toCurrency, toDate } from 'src/filters';
|
import { toCurrency, toDate } from 'src/filters';
|
||||||
import { useState } from 'src/composables/useState';
|
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 VnLv from 'src/components/ui/VnLv.vue';
|
||||||
import FetchData from 'components/FetchData.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';
|
import DepartmentDescriptorProxy from 'src/pages/Worker/Department/Card/DepartmentDescriptorProxy.vue';
|
||||||
|
|
||||||
const DEFAULT_ITEMS = 0;
|
const DEFAULT_ITEMS = 0;
|
||||||
|
@ -24,11 +24,14 @@ const route = useRoute();
|
||||||
const state = useState();
|
const state = useState();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const getTotalRef = ref();
|
const getTotalRef = ref();
|
||||||
|
const total = ref(0);
|
||||||
|
|
||||||
const entityId = computed(() => {
|
const entityId = computed(() => {
|
||||||
return $props.id || route.params.id;
|
return $props.id || route.params.id;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const orderTotal = computed(() => state.get('orderTotal') ?? 0);
|
||||||
|
|
||||||
const setData = (entity) => {
|
const setData = (entity) => {
|
||||||
if (!entity) return;
|
if (!entity) return;
|
||||||
getTotalRef.value && getTotalRef.value.fetch();
|
getTotalRef.value && getTotalRef.value.fetch();
|
||||||
|
@ -38,9 +41,6 @@ const setData = (entity) => {
|
||||||
const getConfirmationValue = (isConfirmed) => {
|
const getConfirmationValue = (isConfirmed) => {
|
||||||
return t(isConfirmed ? 'globals.confirmed' : 'order.summary.notConfirmed');
|
return t(isConfirmed ? 'globals.confirmed' : 'order.summary.notConfirmed');
|
||||||
};
|
};
|
||||||
|
|
||||||
const orderTotal = computed(() => state.get('orderTotal') ?? 0);
|
|
||||||
const total = ref(0);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -54,12 +54,12 @@ const total = ref(0);
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
<CardDescriptor
|
<CardDescriptor
|
||||||
ref="descriptor"
|
v-bind="$attrs"
|
||||||
:url="`Orders/${entityId}`"
|
:id="entityId"
|
||||||
:filter="filter"
|
:card="OrderCard"
|
||||||
title="client.name"
|
title="client.name"
|
||||||
@on-fetch="setData"
|
@on-fetch="setData"
|
||||||
data-key="Order"
|
module="Order"
|
||||||
>
|
>
|
||||||
<template #body="{ entity }">
|
<template #body="{ entity }">
|
||||||
<VnLv
|
<VnLv
|
||||||
|
|
|
@ -12,6 +12,11 @@ const $props = defineProps({
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<QPopupProxy>
|
<QPopupProxy>
|
||||||
<OrderDescriptor v-if="$props.id" :id="$props.id" :summary="OrderSummary" />
|
<OrderDescriptor
|
||||||
|
v-if="$props.id"
|
||||||
|
:id="$props.id"
|
||||||
|
:summary="OrderSummary"
|
||||||
|
data-key="OrderDescriptor"
|
||||||
|
/>
|
||||||
</QPopupProxy>
|
</QPopupProxy>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { computed } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { useArrayData } from 'src/composables/useArrayData';
|
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';
|
import VnLv from 'components/ui/VnLv.vue';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
@ -21,14 +21,15 @@ const { store } = useArrayData();
|
||||||
const card = computed(() => store.data);
|
const card = computed(() => store.data);
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<CardDescriptor
|
<EntityDescriptor
|
||||||
data-key="Agency"
|
data-key="Agency"
|
||||||
:url="`Agencies/${entityId}`"
|
:url="`Agencies/${entityId}`"
|
||||||
:title="card?.name"
|
:title="card?.name"
|
||||||
:subtitle="props.id"
|
:subtitle="props.id"
|
||||||
|
:to-module="{ name: 'RouteAgency' }"
|
||||||
>
|
>
|
||||||
<template #body="{ entity: agency }">
|
<template #body="{ entity: agency }">
|
||||||
<VnLv :label="t('globals.name')" :value="agency.name" />
|
<VnLv :label="t('globals.name')" :value="agency.name" />
|
||||||
</template>
|
</template>
|
||||||
</CardDescriptor>
|
</EntityDescriptor>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, onMounted } from 'vue';
|
import { ref, computed, onMounted } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import CardDescriptor from 'components/ui/CardDescriptor.vue';
|
import EntityDescriptor from 'components/ui/EntityDescriptor.vue';
|
||||||
import useCardDescription from 'composables/useCardDescription';
|
import useCardDescription from 'composables/useCardDescription';
|
||||||
import VnLv from 'components/ui/VnLv.vue';
|
import VnLv from 'components/ui/VnLv.vue';
|
||||||
import { dashIfEmpty, toDate } from 'src/filters';
|
import { dashIfEmpty, toDate } from 'src/filters';
|
||||||
|
@ -41,13 +41,12 @@ const getZone = async () => {
|
||||||
zone.value = zoneData.name;
|
zone.value = zoneData.name;
|
||||||
};
|
};
|
||||||
const data = ref(useCardDescription());
|
const data = ref(useCardDescription());
|
||||||
const setData = (entity) => (data.value = useCardDescription(entity.code, entity.id));
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
getZone();
|
getZone();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<CardDescriptor
|
<EntityDescriptor
|
||||||
:url="`Routes/${entityId}`"
|
:url="`Routes/${entityId}`"
|
||||||
:filter="filter"
|
:filter="filter"
|
||||||
:title="null"
|
:title="null"
|
||||||
|
@ -69,7 +68,7 @@ onMounted(async () => {
|
||||||
<template #menu="{ entity }">
|
<template #menu="{ entity }">
|
||||||
<RouteDescriptorMenu :route="entity" />
|
<RouteDescriptorMenu :route="entity" />
|
||||||
</template>
|
</template>
|
||||||
</CardDescriptor>
|
</EntityDescriptor>
|
||||||
</template>
|
</template>
|
||||||
<i18n>
|
<i18n>
|
||||||
es:
|
es:
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { useI18n } from 'vue-i18n';
|
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 VnLv from 'components/ui/VnLv.vue';
|
||||||
import { dashIfEmpty, toDateHourMin } from 'src/filters';
|
import { dashIfEmpty, toDateHourMin } from 'src/filters';
|
||||||
import SupplierDescriptorProxy from 'pages/Supplier/Card/SupplierDescriptorProxy.vue';
|
import SupplierDescriptorProxy from 'pages/Supplier/Card/SupplierDescriptorProxy.vue';
|
||||||
|
@ -30,11 +30,12 @@ const entityId = computed(() => {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<CardDescriptor
|
<EntityDescriptor
|
||||||
:url="`Roadmaps/${entityId}`"
|
:url="`Roadmaps/${entityId}`"
|
||||||
:filter="filter"
|
:filter="filter"
|
||||||
data-key="Roadmap"
|
data-key="Roadmap"
|
||||||
:summary="summary"
|
:summary="summary"
|
||||||
|
:to-module="{ name: 'RouteRoadmap' }"
|
||||||
>
|
>
|
||||||
<template #body="{ entity }">
|
<template #body="{ entity }">
|
||||||
<VnLv :label="t('Roadmap')" :value="entity?.name" />
|
<VnLv :label="t('Roadmap')" :value="entity?.name" />
|
||||||
|
@ -51,7 +52,7 @@ const entityId = computed(() => {
|
||||||
<template #menu="{ entity }">
|
<template #menu="{ entity }">
|
||||||
<RoadmapDescriptorMenu :route="entity" />
|
<RoadmapDescriptorMenu :route="entity" />
|
||||||
</template>
|
</template>
|
||||||
</CardDescriptor>
|
</EntityDescriptor>
|
||||||
</template>
|
</template>
|
||||||
<i18n>
|
<i18n>
|
||||||
es:
|
es:
|
||||||
|
|
|
@ -199,12 +199,22 @@ const confirmRemove = (ticket) => {
|
||||||
const openSmsDialog = async () => {
|
const openSmsDialog = async () => {
|
||||||
const clientsId = [];
|
const clientsId = [];
|
||||||
const clientsPhone = [];
|
const clientsPhone = [];
|
||||||
|
const clientWithoutPhone = [];
|
||||||
for (let ticket of selectedRows.value) {
|
for (let ticket of selectedRows.value) {
|
||||||
clientsId.push(ticket?.clientFk);
|
clientsId.push(ticket?.clientFk);
|
||||||
const { data: client } = await axios.get(`Clients/${ticket?.clientFk}`);
|
const { data: client } = await axios.get(`Clients/${ticket?.clientFk}`);
|
||||||
|
if (!client.phone) {
|
||||||
|
clientWithoutPhone.push(ticket?.clientFk);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
clientsPhone.push(client.phone);
|
clientsPhone.push(client.phone);
|
||||||
}
|
}
|
||||||
|
if (clientWithoutPhone.length) {
|
||||||
|
quasar.notify({
|
||||||
|
type: 'warning',
|
||||||
|
message: t('components.VnNotes.clientWithoutPhone', { clientWithoutPhone }),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
quasar.dialog({
|
quasar.dialog({
|
||||||
component: SendSmsDialog,
|
component: SendSmsDialog,
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import VnLv from 'src/components/ui/VnLv.vue';
|
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 axios from 'axios';
|
||||||
import useNotify from 'src/composables/useNotify.js';
|
import useNotify from 'src/composables/useNotify.js';
|
||||||
|
|
||||||
|
@ -20,10 +20,11 @@ const route = useRoute();
|
||||||
const entityId = computed(() => props.id || route.params.id);
|
const entityId = computed(() => props.id || route.params.id);
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<CardDescriptor
|
<EntityDescriptor
|
||||||
:url="`Vehicles/${entityId}`"
|
:url="`Vehicles/${entityId}`"
|
||||||
data-key="Vehicle"
|
data-key="Vehicle"
|
||||||
title="numberPlate"
|
title="numberPlate"
|
||||||
|
:to-module="{ name: 'RouteVehicle' }"
|
||||||
>
|
>
|
||||||
<template #menu="{ entity }">
|
<template #menu="{ entity }">
|
||||||
<QItem
|
<QItem
|
||||||
|
@ -53,7 +54,7 @@ const entityId = computed(() => props.id || route.params.id);
|
||||||
<VnLv :label="$t('globals.model')" :value="entity.model" />
|
<VnLv :label="$t('globals.model')" :value="entity.model" />
|
||||||
<VnLv :label="$t('globals.country')" :value="entity.countryCodeFk" />
|
<VnLv :label="$t('globals.country')" :value="entity.countryCodeFk" />
|
||||||
</template>
|
</template>
|
||||||
</CardDescriptor>
|
</EntityDescriptor>
|
||||||
</template>
|
</template>
|
||||||
<i18n>
|
<i18n>
|
||||||
es:
|
es:
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { useI18n } from 'vue-i18n';
|
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 VnLv from 'components/ui/VnLv.vue';
|
||||||
import ShelvingDescriptorMenu from 'pages/Shelving/Card/ShelvingDescriptorMenu.vue';
|
import ShelvingDescriptorMenu from 'pages/Shelving/Card/ShelvingDescriptorMenu.vue';
|
||||||
import VnUserLink from 'src/components/ui/VnUserLink.vue';
|
import VnUserLink from 'src/components/ui/VnUserLink.vue';
|
||||||
|
@ -24,7 +24,7 @@ const entityId = computed(() => {
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<CardDescriptor
|
<EntityDescriptor
|
||||||
:url="`Shelvings/${entityId}`"
|
:url="`Shelvings/${entityId}`"
|
||||||
:filter="filter"
|
:filter="filter"
|
||||||
title="code"
|
title="code"
|
||||||
|
@ -45,5 +45,5 @@ const entityId = computed(() => {
|
||||||
<template #menu="{ entity }">
|
<template #menu="{ entity }">
|
||||||
<ShelvingDescriptorMenu :shelving="entity" />
|
<ShelvingDescriptorMenu :shelving="entity" />
|
||||||
</template>
|
</template>
|
||||||
</CardDescriptor>
|
</EntityDescriptor>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
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 VnLv from 'components/ui/VnLv.vue';
|
||||||
import filter from './ParkingFilter.js';
|
import filter from './ParkingFilter.js';
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
@ -16,17 +16,17 @@ const route = useRoute();
|
||||||
const entityId = computed(() => props.id || route.params.id);
|
const entityId = computed(() => props.id || route.params.id);
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<CardDescriptor
|
<EntityDescriptor
|
||||||
data-key="Parking"
|
data-key="Parking"
|
||||||
:url="`Parkings/${entityId}`"
|
:url="`Parkings/${entityId}`"
|
||||||
title="code"
|
title="code"
|
||||||
:filter="filter"
|
:filter="filter"
|
||||||
:to-module="{ name: 'ParkingList' }"
|
:to-module="{ name: 'ParkingMain' }"
|
||||||
>
|
>
|
||||||
<template #body="{ entity }">
|
<template #body="{ entity }">
|
||||||
<VnLv :label="$t('globals.code')" :value="entity.code" />
|
<VnLv :label="$t('globals.code')" :value="entity.code" />
|
||||||
<VnLv :label="$t('parking.pickingOrder')" :value="entity.pickingOrder" />
|
<VnLv :label="$t('parking.pickingOrder')" :value="entity.pickingOrder" />
|
||||||
<VnLv :label="$t('parking.sector')" :value="entity.sector?.description" />
|
<VnLv :label="$t('parking.sector')" :value="entity.sector?.description" />
|
||||||
</template>
|
</template>
|
||||||
</CardDescriptor>
|
</EntityDescriptor>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { ref, computed, onMounted } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { useI18n } from 'vue-i18n';
|
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 VnLv from 'src/components/ui/VnLv.vue';
|
||||||
|
|
||||||
import { toDateString } from 'src/filters';
|
import { toDateString } from 'src/filters';
|
||||||
|
@ -61,7 +61,7 @@ const getEntryQueryParams = (supplier) => {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<CardDescriptor
|
<EntityDescriptor
|
||||||
:url="`Suppliers/${entityId}`"
|
:url="`Suppliers/${entityId}`"
|
||||||
:filter="filter"
|
:filter="filter"
|
||||||
data-key="Supplier"
|
data-key="Supplier"
|
||||||
|
@ -136,7 +136,7 @@ const getEntryQueryParams = (supplier) => {
|
||||||
</QBtn>
|
</QBtn>
|
||||||
</QCardActions>
|
</QCardActions>
|
||||||
</template>
|
</template>
|
||||||
</CardDescriptor>
|
</EntityDescriptor>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<i18n>
|
<i18n>
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { useRoute } from 'vue-router';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import CustomerDescriptorProxy from 'pages/Customer/Card/CustomerDescriptorProxy.vue';
|
import CustomerDescriptorProxy from 'pages/Customer/Card/CustomerDescriptorProxy.vue';
|
||||||
import DepartmentDescriptorProxy from 'pages/Worker/Department/Card/DepartmentDescriptorProxy.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 TicketDescriptorMenu from './TicketDescriptorMenu.vue';
|
||||||
import VnLv from 'src/components/ui/VnLv.vue';
|
import VnLv from 'src/components/ui/VnLv.vue';
|
||||||
import { toDateTimeFormat } from 'src/filters/date';
|
import { toDateTimeFormat } from 'src/filters/date';
|
||||||
|
@ -57,7 +57,7 @@ function getInfo() {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<CardDescriptor
|
<EntityDescriptor
|
||||||
:url="`Tickets/${entityId}`"
|
:url="`Tickets/${entityId}`"
|
||||||
:filter="filter"
|
:filter="filter"
|
||||||
data-key="Ticket"
|
data-key="Ticket"
|
||||||
|
@ -155,7 +155,7 @@ function getInfo() {
|
||||||
</QBtn>
|
</QBtn>
|
||||||
</QCardActions>
|
</QCardActions>
|
||||||
</template>
|
</template>
|
||||||
</CardDescriptor>
|
</EntityDescriptor>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<i18n>
|
<i18n>
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { computed, ref } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { useI18n } from 'vue-i18n';
|
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 VnLv from 'src/components/ui/VnLv.vue';
|
||||||
import useCardDescription from 'src/composables/useCardDescription';
|
import useCardDescription from 'src/composables/useCardDescription';
|
||||||
import TravelDescriptorMenuItems from './TravelDescriptorMenuItems.vue';
|
import TravelDescriptorMenuItems from './TravelDescriptorMenuItems.vue';
|
||||||
|
@ -31,7 +31,7 @@ const setData = (entity) => (data.value = useCardDescription(entity.ref, entity.
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<CardDescriptor
|
<EntityDescriptor
|
||||||
:url="`Travels/${entityId}`"
|
:url="`Travels/${entityId}`"
|
||||||
:title="data.title"
|
:title="data.title"
|
||||||
:subtitle="data.subtitle"
|
:subtitle="data.subtitle"
|
||||||
|
@ -79,7 +79,7 @@ const setData = (entity) => (data.value = useCardDescription(entity.ref, entity.
|
||||||
</QBtn>
|
</QBtn>
|
||||||
</QCardActions>
|
</QCardActions>
|
||||||
</template>
|
</template>
|
||||||
</CardDescriptor>
|
</EntityDescriptor>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<i18n>
|
<i18n>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
import { computed, ref } from 'vue';
|
import { computed, ref } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { useI18n } from 'vue-i18n';
|
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 VnLv from 'src/components/ui/VnLv.vue';
|
||||||
import VnLinkPhone from 'src/components/ui/VnLinkPhone.vue';
|
import VnLinkPhone from 'src/components/ui/VnLinkPhone.vue';
|
||||||
import VnChangePassword from 'src/components/common/VnChangePassword.vue';
|
import VnChangePassword from 'src/components/common/VnChangePassword.vue';
|
||||||
|
@ -52,7 +52,7 @@ const handlePhotoUpdated = (evt = false) => {
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<CardDescriptor
|
<EntityDescriptor
|
||||||
ref="cardDescriptorRef"
|
ref="cardDescriptorRef"
|
||||||
:data-key="dataKey"
|
:data-key="dataKey"
|
||||||
:summary="$props.summary"
|
:summary="$props.summary"
|
||||||
|
@ -167,7 +167,7 @@ const handlePhotoUpdated = (evt = false) => {
|
||||||
</QBtn>
|
</QBtn>
|
||||||
</QCardActions>
|
</QCardActions>
|
||||||
</template>
|
</template>
|
||||||
</CardDescriptor>
|
</EntityDescriptor>
|
||||||
<VnChangePassword
|
<VnChangePassword
|
||||||
ref="changePassRef"
|
ref="changePassRef"
|
||||||
:submit-fn="
|
:submit-fn="
|
||||||
|
@ -190,9 +190,3 @@ const handlePhotoUpdated = (evt = false) => {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<i18n>
|
|
||||||
es:
|
|
||||||
Click to allow the user to be disabled: Marcar para deshabilitar
|
|
||||||
Click to exclude the user from getting disabled: Marcar para no deshabilitar
|
|
||||||
</i18n>
|
|
||||||
|
|
|
@ -63,3 +63,8 @@ const showChangePasswordDialog = () => {
|
||||||
</QItemSection>
|
</QItemSection>
|
||||||
</QItem>
|
</QItem>
|
||||||
</template>
|
</template>
|
||||||
|
<i18n>
|
||||||
|
es:
|
||||||
|
Click to allow the user to be disabled: Marcar para deshabilitar
|
||||||
|
Click to exclude the user from getting disabled: Marcar para no deshabilitar
|
||||||
|
</i18n>
|
||||||
|
|
|
@ -5,24 +5,25 @@ import { ref, computed } from 'vue';
|
||||||
|
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import useNotify from 'src/composables/useNotify.js';
|
import useNotify from 'src/composables/useNotify.js';
|
||||||
|
import { useVnConfirm } from 'composables/useVnConfirm';
|
||||||
|
import { useArrayData } from 'src/composables/useArrayData';
|
||||||
|
import { downloadDocuware } from 'src/composables/downloadFile';
|
||||||
|
|
||||||
import FetchData from 'components/FetchData.vue';
|
import FetchData from 'components/FetchData.vue';
|
||||||
import FormModelPopup from 'src/components/FormModelPopup.vue';
|
import FormModelPopup from 'src/components/FormModelPopup.vue';
|
||||||
import { useVnConfirm } from 'composables/useVnConfirm';
|
|
||||||
|
|
||||||
import VnPaginate from 'src/components/ui/VnPaginate.vue';
|
|
||||||
import VnRow from 'components/ui/VnRow.vue';
|
import VnRow from 'components/ui/VnRow.vue';
|
||||||
import VnSelect from 'src/components/common/VnSelect.vue';
|
import VnSelect from 'src/components/common/VnSelect.vue';
|
||||||
import VnInput from 'src/components/common/VnInput.vue';
|
import VnTable from 'src/components/VnTable/VnTable.vue';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { notify } = useNotify();
|
const { notify } = useNotify();
|
||||||
|
const loadingDocuware = ref(true);
|
||||||
const paginate = ref();
|
const tableRef = ref();
|
||||||
const dialog = ref();
|
const dialog = ref();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { openConfirmationModal } = useVnConfirm();
|
const { openConfirmationModal } = useVnConfirm();
|
||||||
const routeId = computed(() => route.params.id);
|
const routeId = computed(() => route.params.id);
|
||||||
|
const worker = computed(() => useArrayData('Worker').store.data);
|
||||||
const initialData = computed(() => {
|
const initialData = computed(() => {
|
||||||
return {
|
return {
|
||||||
userFk: routeId.value,
|
userFk: routeId.value,
|
||||||
|
@ -31,154 +32,268 @@ const initialData = computed(() => {
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const deallocatePDA = async (deviceProductionFk) => {
|
const columns = computed(() => [
|
||||||
await axios.post(`Workers/${route.params.id}/deallocatePDA`, {
|
{
|
||||||
pda: deviceProductionFk,
|
align: 'center',
|
||||||
});
|
label: t('globals.state'),
|
||||||
notify(t('PDA deallocated'), 'positive');
|
name: 'state',
|
||||||
|
format: (row) => row?.docuware?.state,
|
||||||
paginate.value.fetch();
|
columnFilter: false,
|
||||||
};
|
chip: {
|
||||||
|
condition: (_, row) => !!row.docuware,
|
||||||
|
color: (row) => (isSigned(row) ? 'bg-positive' : 'bg-warning'),
|
||||||
|
},
|
||||||
|
visible: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
align: 'right',
|
||||||
|
label: t('worker.pda.currentPDA'),
|
||||||
|
name: 'deviceProductionFk',
|
||||||
|
columnClass: 'shrink',
|
||||||
|
cardVisible: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
align: 'left',
|
||||||
|
label: t('Model'),
|
||||||
|
name: 'modelFk',
|
||||||
|
format: ({ deviceProduction }) => deviceProduction.modelFk,
|
||||||
|
cardVisible: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
align: 'right',
|
||||||
|
label: t('Serial number'),
|
||||||
|
name: 'serialNumber',
|
||||||
|
format: ({ deviceProduction }) => deviceProduction.serialNumber,
|
||||||
|
cardVisible: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
align: 'left',
|
||||||
|
label: t('Current SIM'),
|
||||||
|
name: 'simFk',
|
||||||
|
cardVisible: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
align: 'right',
|
||||||
|
name: 'actions',
|
||||||
|
columnFilter: false,
|
||||||
|
cardVisible: true,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
function reloadData() {
|
function reloadData() {
|
||||||
initialData.value.deviceProductionFk = null;
|
initialData.value.deviceProductionFk = null;
|
||||||
initialData.value.simFk = null;
|
initialData.value.simFk = null;
|
||||||
paginate.value.fetch();
|
tableRef.value.reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchDocuware() {
|
||||||
|
loadingDocuware.value = true;
|
||||||
|
|
||||||
|
const id = `${worker.value?.lastName} ${worker.value?.firstName}`;
|
||||||
|
const rows = tableRef.value.CrudModelRef.formData;
|
||||||
|
|
||||||
|
const promises = rows.map(async (row) => {
|
||||||
|
const { data } = await axios.post(`Docuwares/${id}/checkFile`, {
|
||||||
|
fileCabinet: 'hr',
|
||||||
|
signed: false,
|
||||||
|
mergeFilter: [
|
||||||
|
{
|
||||||
|
DBName: 'TIPO_DOCUMENTO',
|
||||||
|
Value: ['PDA'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
DBName: 'FILENAME',
|
||||||
|
Value: [`${row.deviceProductionFk}-pda`],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
row.docuware = data;
|
||||||
|
});
|
||||||
|
|
||||||
|
await Promise.allSettled(promises);
|
||||||
|
loadingDocuware.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function sendToTablet(rows) {
|
||||||
|
const promises = rows.map(async (row) => {
|
||||||
|
await axios.post(`Docuwares/upload-pda-pdf`, {
|
||||||
|
ids: [row.deviceProductionFk],
|
||||||
|
});
|
||||||
|
row.docuware = true;
|
||||||
|
});
|
||||||
|
await Promise.allSettled(promises);
|
||||||
|
notify(t('PDF sended to signed'), 'positive');
|
||||||
|
tableRef.value.reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function deallocatePDA(deviceProductionFk) {
|
||||||
|
await axios.post(`Workers/${route.params.id}/deallocatePDA`, {
|
||||||
|
pda: deviceProductionFk,
|
||||||
|
});
|
||||||
|
const index = tableRef.value.CrudModelRef.formData.findIndex(
|
||||||
|
(data) => data?.deviceProductionFk == deviceProductionFk,
|
||||||
|
);
|
||||||
|
delete tableRef.value.CrudModelRef.formData[index];
|
||||||
|
notify(t('PDA deallocated'), 'positive');
|
||||||
|
}
|
||||||
|
|
||||||
|
function isSigned(row) {
|
||||||
|
return row.docuware?.state === 'Firmado';
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<QPage class="column items-center q-pa-md centerCard">
|
<FetchData
|
||||||
<FetchData
|
url="workers/getAvailablePda"
|
||||||
url="workers/getAvailablePda"
|
@on-fetch="(data) => (deviceProductions = data)"
|
||||||
@on-fetch="(data) => (deviceProductions = data)"
|
auto-load
|
||||||
auto-load
|
/>
|
||||||
/>
|
<VnTable
|
||||||
<VnPaginate
|
ref="tableRef"
|
||||||
ref="paginate"
|
data-key="WorkerPda"
|
||||||
data-key="WorkerPda"
|
url="DeviceProductionUsers"
|
||||||
url="DeviceProductionUsers"
|
:user-filter="{ order: 'id' }"
|
||||||
:user-filter="{ where: { userFk: routeId } }"
|
:filter="{ where: { userFk: routeId } }"
|
||||||
order="id"
|
search-url="pda"
|
||||||
search-url="pda"
|
auto-load
|
||||||
auto-load
|
:columns="columns"
|
||||||
>
|
@onFetch="fetchDocuware"
|
||||||
<template #body="{ rows }">
|
:hasSubToolbar="true"
|
||||||
<QCard
|
:default-remove="false"
|
||||||
flat
|
:default-reset="false"
|
||||||
bordered
|
:default-save="false"
|
||||||
:key="row.id"
|
:table="{
|
||||||
v-for="row of rows"
|
'row-key': 'deviceProductionFk',
|
||||||
class="card q-px-md q-mb-sm container"
|
selection: 'multiple',
|
||||||
>
|
}"
|
||||||
<VnRow>
|
:table-filter="{ hiddenTags: ['userFk'] }"
|
||||||
<VnInput
|
>
|
||||||
:label="t('worker.pda.currentPDA')"
|
<template #moreBeforeActions>
|
||||||
:model-value="row?.deviceProductionFk"
|
|
||||||
disable
|
|
||||||
/>
|
|
||||||
<VnInput
|
|
||||||
:label="t('Model')"
|
|
||||||
:model-value="row?.deviceProduction?.modelFk"
|
|
||||||
disable
|
|
||||||
/>
|
|
||||||
<VnInput
|
|
||||||
:label="t('Serial number')"
|
|
||||||
:model-value="row?.deviceProduction?.serialNumber"
|
|
||||||
disable
|
|
||||||
/>
|
|
||||||
<VnInput
|
|
||||||
:label="t('Current SIM')"
|
|
||||||
:model-value="row?.simFk"
|
|
||||||
disable
|
|
||||||
/>
|
|
||||||
<QBtn
|
|
||||||
flat
|
|
||||||
icon="delete"
|
|
||||||
color="primary"
|
|
||||||
class="btn-delete"
|
|
||||||
@click="
|
|
||||||
openConfirmationModal(
|
|
||||||
t(`Remove PDA`),
|
|
||||||
t('Do you want to remove this PDA?'),
|
|
||||||
() => deallocatePDA(row.deviceProductionFk),
|
|
||||||
)
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<QTooltip>
|
|
||||||
{{ t('worker.pda.removePDA') }}
|
|
||||||
</QTooltip>
|
|
||||||
</QBtn>
|
|
||||||
</VnRow>
|
|
||||||
</QCard>
|
|
||||||
</template>
|
|
||||||
</VnPaginate>
|
|
||||||
<QPageSticky :offset="[18, 18]">
|
|
||||||
<QBtn
|
<QBtn
|
||||||
@click.stop="dialog.show()"
|
:label="t('globals.refresh')"
|
||||||
|
icon="refresh"
|
||||||
|
@click="tableRef.reload()"
|
||||||
|
/>
|
||||||
|
<QBtn
|
||||||
|
:disable="!tableRef?.selected?.length"
|
||||||
|
:label="t('globals.send')"
|
||||||
|
icon="install_mobile"
|
||||||
|
@click="sendToTablet(tableRef?.selected)"
|
||||||
|
class="bg-primary"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #column-actions="{ row }">
|
||||||
|
<QBtn
|
||||||
|
flat
|
||||||
|
icon="delete"
|
||||||
color="primary"
|
color="primary"
|
||||||
fab
|
@click="
|
||||||
icon="add"
|
openConfirmationModal(
|
||||||
v-shortcut="'+'"
|
t(`Remove PDA`),
|
||||||
|
t('Do you want to remove this PDA?'),
|
||||||
|
() => deallocatePDA(row.deviceProductionFk),
|
||||||
|
)
|
||||||
|
"
|
||||||
|
data-cy="workerPda-remove"
|
||||||
>
|
>
|
||||||
<QDialog ref="dialog">
|
<QTooltip>
|
||||||
<FormModelPopup
|
{{ t('worker.pda.removePDA') }}
|
||||||
:title="t('Add new device')"
|
</QTooltip>
|
||||||
url-create="DeviceProductionUsers"
|
|
||||||
model="DeviceProductionUser"
|
|
||||||
:form-initial-data="initialData"
|
|
||||||
@on-data-saved="reloadData()"
|
|
||||||
>
|
|
||||||
<template #form-inputs="{ data }">
|
|
||||||
<VnRow>
|
|
||||||
<VnSelect
|
|
||||||
:label="t('worker.pda.newPDA')"
|
|
||||||
v-model="data.deviceProductionFk"
|
|
||||||
:options="deviceProductions"
|
|
||||||
option-label="id"
|
|
||||||
option-value="id"
|
|
||||||
id="deviceProductionFk"
|
|
||||||
hide-selected
|
|
||||||
data-cy="pda-dialog-select"
|
|
||||||
:required="true"
|
|
||||||
>
|
|
||||||
<template #option="scope">
|
|
||||||
<QItem v-bind="scope.itemProps">
|
|
||||||
<QItemSection>
|
|
||||||
<QItemLabel
|
|
||||||
>ID: {{ scope.opt?.id }}</QItemLabel
|
|
||||||
>
|
|
||||||
<QItemLabel caption>
|
|
||||||
{{ scope.opt?.modelFk }},
|
|
||||||
{{ scope.opt?.serialNumber }}
|
|
||||||
</QItemLabel>
|
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
</template>
|
|
||||||
</VnSelect>
|
|
||||||
<VnInput
|
|
||||||
v-model="data.simFk"
|
|
||||||
:label="t('SIM serial number')"
|
|
||||||
id="simSerialNumber"
|
|
||||||
use-input
|
|
||||||
/>
|
|
||||||
</VnRow>
|
|
||||||
</template>
|
|
||||||
</FormModelPopup>
|
|
||||||
</QDialog>
|
|
||||||
</QBtn>
|
</QBtn>
|
||||||
<QTooltip>
|
<QBtn
|
||||||
{{ t('globals.new') }}
|
v-if="!isSigned(row)"
|
||||||
</QTooltip>
|
:loading="loadingDocuware"
|
||||||
</QPageSticky>
|
icon="install_mobile"
|
||||||
</QPage>
|
flat
|
||||||
|
color="primary"
|
||||||
|
@click="
|
||||||
|
openConfirmationModal(
|
||||||
|
t('Sign PDA'),
|
||||||
|
t('Are you sure you want to send it?'),
|
||||||
|
() => sendToTablet([row]),
|
||||||
|
)
|
||||||
|
"
|
||||||
|
data-cy="workerPda-send"
|
||||||
|
>
|
||||||
|
<QTooltip>
|
||||||
|
{{ t('worker.pda.sendToTablet') }}
|
||||||
|
</QTooltip>
|
||||||
|
</QBtn>
|
||||||
|
<QBtn
|
||||||
|
v-if="isSigned(row)"
|
||||||
|
:loading="loadingDocuware"
|
||||||
|
icon="cloud_download"
|
||||||
|
flat
|
||||||
|
color="primary"
|
||||||
|
@click="
|
||||||
|
downloadDocuware('Docuwares/download-pda-pdf', {
|
||||||
|
file: row.deviceProductionFk + '-pda',
|
||||||
|
worker: worker?.lastName + ' ' + worker?.firstName,
|
||||||
|
})
|
||||||
|
"
|
||||||
|
data-cy="workerPda-download"
|
||||||
|
>
|
||||||
|
<QTooltip>
|
||||||
|
{{ t('worker.pda.download') }}
|
||||||
|
</QTooltip>
|
||||||
|
</QBtn>
|
||||||
|
</template>
|
||||||
|
</VnTable>
|
||||||
|
<QPageSticky :offset="[18, 18]">
|
||||||
|
<QBtn @click.stop="dialog.show()" color="primary" fab icon="add" v-shortcut="'+'">
|
||||||
|
<QDialog ref="dialog">
|
||||||
|
<FormModelPopup
|
||||||
|
:title="t('Add new device')"
|
||||||
|
url-create="DeviceProductionUsers"
|
||||||
|
model="DeviceProductionUser"
|
||||||
|
:form-initial-data="initialData"
|
||||||
|
@on-data-saved="reloadData()"
|
||||||
|
>
|
||||||
|
<template #form-inputs="{ data }">
|
||||||
|
<VnRow>
|
||||||
|
<VnSelect
|
||||||
|
:label="t('PDA')"
|
||||||
|
v-model="data.deviceProductionFk"
|
||||||
|
:options="deviceProductions"
|
||||||
|
option-label="modelFk"
|
||||||
|
option-value="id"
|
||||||
|
id="deviceProductionFk"
|
||||||
|
hide-selected
|
||||||
|
data-cy="pda-dialog-select"
|
||||||
|
:required="true"
|
||||||
|
>
|
||||||
|
<template #option="scope">
|
||||||
|
<QItem v-bind="scope.itemProps">
|
||||||
|
<QItemSection>
|
||||||
|
<QItemLabel
|
||||||
|
>ID: {{ scope.opt?.id }}</QItemLabel
|
||||||
|
>
|
||||||
|
<QItemLabel caption>
|
||||||
|
{{ scope.opt?.modelFk }},
|
||||||
|
{{ scope.opt?.serialNumber }}
|
||||||
|
</QItemLabel>
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
</template>
|
||||||
|
</VnSelect>
|
||||||
|
<VnSelect
|
||||||
|
url="Sims"
|
||||||
|
option-label="line"
|
||||||
|
option-value="code"
|
||||||
|
v-model="data.simFk"
|
||||||
|
:label="t('SIM serial number')"
|
||||||
|
id="simSerialNumber"
|
||||||
|
/>
|
||||||
|
</VnRow>
|
||||||
|
</template>
|
||||||
|
</FormModelPopup>
|
||||||
|
</QDialog>
|
||||||
|
</QBtn>
|
||||||
|
<QTooltip>
|
||||||
|
{{ t('globals.new') }}
|
||||||
|
</QTooltip>
|
||||||
|
</QPageSticky>
|
||||||
</template>
|
</template>
|
||||||
<style lang="scss" scoped>
|
|
||||||
.btn-delete {
|
|
||||||
max-width: 4%;
|
|
||||||
margin-top: 30px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<i18n>
|
<i18n>
|
||||||
es:
|
es:
|
||||||
Model: Modelo
|
Model: Modelo
|
||||||
|
@ -190,4 +305,6 @@ es:
|
||||||
Do you want to remove this PDA?: ¿Desea eliminar este PDA?
|
Do you want to remove this PDA?: ¿Desea eliminar este PDA?
|
||||||
You can only have one PDA: Solo puedes tener un PDA si no eres autonomo
|
You can only have one PDA: Solo puedes tener un PDA si no eres autonomo
|
||||||
This PDA is already assigned to another user: Este PDA ya está asignado a otro usuario
|
This PDA is already assigned to another user: Este PDA ya está asignado a otro usuario
|
||||||
|
Are you sure you want to send it?: ¿Seguro que quieres enviarlo?
|
||||||
|
Sign PDA: Firmar PDA
|
||||||
</i18n>
|
</i18n>
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { useRoute, useRouter } from 'vue-router';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useVnConfirm } from 'composables/useVnConfirm';
|
import { useVnConfirm } from 'composables/useVnConfirm';
|
||||||
import VnLv from 'src/components/ui/VnLv.vue';
|
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 axios from 'axios';
|
||||||
import useNotify from 'src/composables/useNotify.js';
|
import useNotify from 'src/composables/useNotify.js';
|
||||||
|
@ -40,7 +40,7 @@ const removeDepartment = async () => {
|
||||||
const { openConfirmationModal } = useVnConfirm();
|
const { openConfirmationModal } = useVnConfirm();
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<CardDescriptor
|
<EntityDescriptor
|
||||||
ref="DepartmentDescriptorRef"
|
ref="DepartmentDescriptorRef"
|
||||||
:url="`Departments/${entityId}`"
|
:url="`Departments/${entityId}`"
|
||||||
:summary="$props.summary"
|
:summary="$props.summary"
|
||||||
|
@ -95,7 +95,7 @@ const { openConfirmationModal } = useVnConfirm();
|
||||||
</QBtn>
|
</QBtn>
|
||||||
</QCardActions>
|
</QCardActions>
|
||||||
</template>
|
</template>
|
||||||
</CardDescriptor>
|
</EntityDescriptor>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<i18n>
|
<i18n>
|
||||||
|
|
|
@ -16,6 +16,7 @@ const $props = defineProps({
|
||||||
v-if="$props.id"
|
v-if="$props.id"
|
||||||
:id="$props.id"
|
:id="$props.id"
|
||||||
:summary="DepartmentSummary"
|
:summary="DepartmentSummary"
|
||||||
|
data-key="DepartmentDescriptorProxy"
|
||||||
/>
|
/>
|
||||||
</QPopupProxy>
|
</QPopupProxy>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
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 VnLv from 'src/components/ui/VnLv.vue';
|
||||||
import { toTimeFormat } from 'src/filters/date';
|
import { toTimeFormat } from 'src/filters/date';
|
||||||
import { toCurrency } from 'filters/index';
|
import { toCurrency } from 'filters/index';
|
||||||
|
@ -25,7 +25,7 @@ const entityId = computed(() => {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<CardDescriptor :url="`Zones/${entityId}`" :filter="filter" data-key="Zone">
|
<EntityDescriptor :url="`Zones/${entityId}`" :filter="filter" data-key="Zone">
|
||||||
<template #menu="{ entity }">
|
<template #menu="{ entity }">
|
||||||
<ZoneDescriptorMenuItems :zone="entity" />
|
<ZoneDescriptorMenuItems :zone="entity" />
|
||||||
</template>
|
</template>
|
||||||
|
@ -36,5 +36,5 @@ const entityId = computed(() => {
|
||||||
<VnLv :label="$t('list.price')" :value="toCurrency(entity.price)" />
|
<VnLv :label="$t('list.price')" :value="toCurrency(entity.price)" />
|
||||||
<VnLv :label="$t('zone.bonus')" :value="toCurrency(entity.bonus)" />
|
<VnLv :label="$t('zone.bonus')" :value="toCurrency(entity.bonus)" />
|
||||||
</template>
|
</template>
|
||||||
</CardDescriptor>
|
</EntityDescriptor>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -271,12 +271,14 @@ export default {
|
||||||
path: 'department',
|
path: 'department',
|
||||||
name: 'Department',
|
name: 'Department',
|
||||||
redirect: { name: 'WorkerDepartment' },
|
redirect: { name: 'WorkerDepartment' },
|
||||||
component: () => import('src/pages/Worker/WorkerDepartment.vue'),
|
meta: { title: 'department', icon: 'vn:greuge' },
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
|
component: () =>
|
||||||
|
import('src/pages/Worker/WorkerDepartment.vue'),
|
||||||
|
meta: { title: 'department', icon: 'vn:greuge' },
|
||||||
name: 'WorkerDepartment',
|
name: 'WorkerDepartment',
|
||||||
path: 'list',
|
path: 'list',
|
||||||
meta: { title: 'department', icon: 'vn:greuge' },
|
|
||||||
},
|
},
|
||||||
departmentCard,
|
departmentCard,
|
||||||
],
|
],
|
||||||
|
|
|
@ -25,7 +25,7 @@ describe('VnLog', () => {
|
||||||
|
|
||||||
it('should show claimDescriptor', () => {
|
it('should show claimDescriptor', () => {
|
||||||
cy.dataCy('iconLaunch-claimFk').first().click();
|
cy.dataCy('iconLaunch-claimFk').first().click();
|
||||||
cy.dataCy('cardDescriptor_subtitle').contains('1');
|
cy.dataCy('vnDescriptor_subtitle').contains('1');
|
||||||
cy.dataCy('iconLaunch-claimFk').first().click();
|
cy.dataCy('iconLaunch-claimFk').first().click();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,23 +1,80 @@
|
||||||
describe('WorkerPda', () => {
|
describe('WorkerPda', () => {
|
||||||
const select = '[data-cy="pda-dialog-select"]';
|
const deviceId = 4;
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
cy.viewport(1920, 1080);
|
|
||||||
cy.login('developer');
|
cy.login('developer');
|
||||||
cy.visit(`/#/worker/1110/pda`);
|
cy.visit(`/#/worker/1110/pda`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('assign pda', () => {
|
it('assign and delete pda', () => {
|
||||||
cy.addBtnClick();
|
creatNewPDA();
|
||||||
cy.get(select).click();
|
cy.checkNotification('Data created');
|
||||||
cy.get(select).type('{downArrow}{enter}');
|
cy.visit(`/#/worker/1110/pda`);
|
||||||
cy.get('.q-notification__message').should('have.text', 'Data created');
|
removeNewPDA();
|
||||||
|
cy.checkNotification('PDA deallocated');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('delete pda', () => {
|
it('send and download pdf to docuware', () => {
|
||||||
cy.get('.btn-delete').click();
|
//Send
|
||||||
cy.get(
|
cy.intercept('POST', '/api/Docuwares/upload-pda-pdf', (req) => {
|
||||||
'.q-card__actions > .q-btn--unelevated > .q-btn__content > .block'
|
req.reply({
|
||||||
).click();
|
statusCode: 200,
|
||||||
cy.get('.q-notification__message').should('have.text', 'PDA deallocated');
|
body: {},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
creatNewPDA();
|
||||||
|
|
||||||
|
cy.dataCy('workerPda-send').click();
|
||||||
|
cy.clickConfirm();
|
||||||
|
cy.checkNotification('PDF sended to signed');
|
||||||
|
|
||||||
|
//Download
|
||||||
|
cy.intercept('POST', /\/api\/Docuwares\/Jones%20Jessica\/checkFile/, (req) => {
|
||||||
|
req.reply({
|
||||||
|
statusCode: 200,
|
||||||
|
body: {
|
||||||
|
id: deviceId,
|
||||||
|
state: 'Firmado',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
cy.get('#st-actions').contains('refresh').click();
|
||||||
|
cy.intercept('GET', '/api/Docuwares/download-pda-pdf**', (req) => {
|
||||||
|
req.reply({
|
||||||
|
statusCode: 200,
|
||||||
|
body: {},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
cy.dataCy('workerPda-download').click();
|
||||||
|
removeNewPDA();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('send 2 pdfs to docuware', () => {
|
||||||
|
cy.intercept('POST', '/api/Docuwares/upload-pda-pdf', (req) => {
|
||||||
|
req.reply({
|
||||||
|
statusCode: 200,
|
||||||
|
body: {},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
creatNewPDA();
|
||||||
|
creatNewPDA(2);
|
||||||
|
cy.selectRows([1, 2]);
|
||||||
|
cy.get('#st-actions').contains('Send').click();
|
||||||
|
cy.checkNotification('PDF sended to signed');
|
||||||
|
|
||||||
|
removeNewPDA();
|
||||||
|
});
|
||||||
|
|
||||||
|
function creatNewPDA(id = deviceId) {
|
||||||
|
cy.addBtnClick();
|
||||||
|
cy.selectOption('[data-cy="pda-dialog-select"]', id);
|
||||||
|
cy.saveCard();
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeNewPDA() {
|
||||||
|
cy.dataCy('workerPda-remove').first().click();
|
||||||
|
cy.clickConfirm();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -371,7 +371,7 @@ Cypress.Commands.add('validateContent', (selector, expectedValue) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
Cypress.Commands.add('openActionsDescriptor', () => {
|
Cypress.Commands.add('openActionsDescriptor', () => {
|
||||||
cy.get('[data-cy="cardDescriptor"] [data-cy="descriptor-more-opts"]').click();
|
cy.get('[data-cy="vnDescriptor"] [data-cy="descriptor-more-opts"]').click();
|
||||||
});
|
});
|
||||||
|
|
||||||
Cypress.Commands.add('openUserPanel', () => {
|
Cypress.Commands.add('openUserPanel', () => {
|
||||||
|
@ -466,16 +466,16 @@ Cypress.Commands.add('validateDescriptor', (toCheck = {}) => {
|
||||||
|
|
||||||
const popupSelector = popup ? '[role="menu"] ' : '';
|
const popupSelector = popup ? '[role="menu"] ' : '';
|
||||||
|
|
||||||
if (title) cy.get(`${popupSelector}[data-cy="cardDescriptor_title"]`).contains(title);
|
if (title) cy.get(`${popupSelector}[data-cy="vnDescriptor_title"]`).contains(title);
|
||||||
if (description)
|
if (description)
|
||||||
cy.get(`${popupSelector}[data-cy="cardDescriptor_description"]`).contains(
|
cy.get(`${popupSelector}[data-cy="vnDescriptor_description"]`).contains(
|
||||||
description,
|
description,
|
||||||
);
|
);
|
||||||
if (subtitle)
|
if (subtitle)
|
||||||
cy.get(`${popupSelector}[data-cy="cardDescriptor_subtitle"]`).contains(subtitle);
|
cy.get(`${popupSelector}[data-cy="vnDescriptor_subtitle"]`).contains(subtitle);
|
||||||
|
|
||||||
for (const index in listbox)
|
for (const index in listbox)
|
||||||
cy.get(`${popupSelector}[data-cy="cardDescriptor_listbox"] > *`)
|
cy.get(`${popupSelector}[data-cy="vnDescriptor_listbox"] > *`)
|
||||||
.eq(index)
|
.eq(index)
|
||||||
.should('contain.text', listbox[index]);
|
.should('contain.text', listbox[index]);
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue