refactor(CustomeDms): refs #7527 use VnDmsList
gitea/salix-front/pipeline/pr-dev Something is wrong with the build of this commit Details

This commit is contained in:
Alex Moreno 2025-04-11 09:56:11 +02:00
parent cb9eb61b16
commit 33c6a94df4
7 changed files with 12 additions and 987 deletions

View File

@ -48,6 +48,10 @@ const $props = defineProps({
type: String,
required: true,
},
description: {
type: String,
deafult: undefined,
},
});
const dmsFilter = {
@ -88,7 +92,6 @@ const dmsFilter = {
],
},
},
where: { [$props.filter]: route.params.id },
};
const columns = computed(() => [
@ -298,6 +301,7 @@ defineExpose({
:data-key="$props.model"
:url="$props.model"
:user-filter="dmsFilter"
:filter="{ where: { [filter]: route.params.id } }"
:order="['dmsFk DESC']"
auto-load
@on-fetch="setData"

View File

@ -1,269 +0,0 @@
<script setup>
import { computed, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import { useRoute, useRouter } from 'vue-router';
import { QBadge, QBtn, QCheckbox } from 'quasar';
import { downloadFile } from 'src/composables/downloadFile';
import { toDateTimeFormat } from 'src/filters/date';
import FetchData from 'components/FetchData.vue';
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
import CustomerFileManagementActions from 'src/pages/Customer/components/CustomerFileManagementActions.vue';
const { t } = useI18n();
const route = useRoute();
const router = useRouter();
const ClientDmsRef = ref(null);
const rows = ref([]);
const filter = {
include: {
relation: 'dms',
scope: {
fields: [
'dmsTypeFk',
'reference',
'hardCopyNumber',
'workerFk',
'description',
'hasFile',
'file',
'created',
],
include: [
{ relation: 'dmsType', scope: { fields: ['name'] } },
{
relation: 'worker',
scope: {
fields: ['id'],
include: { relation: 'user', scope: { fields: ['name'] } },
},
},
],
},
},
where: { clientFk: route.params.id },
order: ['dmsFk DESC'],
limit: 20,
};
const tableColumnComponents = {
id: {
component: 'span',
props: () => {},
event: () => {},
},
type: {
component: 'span',
props: () => {},
event: () => {},
},
order: {
component: QBadge,
props: () => {},
event: () => {},
},
reference: {
component: 'span',
props: () => {},
event: () => {},
},
description: {
component: 'span',
props: () => {},
event: () => {},
},
original: {
component: QCheckbox,
props: (prop) => ({
disable: true,
'model-value': Boolean(prop.value),
}),
event: () => {},
},
file: {
component: QBtn,
props: () => ({ flat: true }),
event: ({ row }) => downloadFile(row.dmsFk),
},
employee: {
component: QBtn,
props: () => ({ flat: true }),
event: () => {},
},
created: {
component: 'span',
props: () => {},
event: () => {},
},
actions: {
component: CustomerFileManagementActions,
props: (prop) => ({
id: prop.row.dmsFk,
promise: setData,
}),
event: () => {},
},
};
const columns = computed(() => [
{
align: 'left',
field: ({ dms }) => dms.id,
label: t('Id'),
name: 'id',
},
{
align: 'left',
field: ({ dms }) => dms.dmsType.name,
label: t('Type'),
name: 'type',
},
{
align: 'left',
field: ({ dms }) => dms.hardCopyNumber,
label: t('Order'),
name: 'order',
},
{
align: 'left',
field: ({ dms }) => dms.reference,
label: t('Reference'),
name: 'reference',
},
{
align: 'left',
field: ({ dms }) => dms.description,
label: t('Description'),
name: 'description',
},
{
align: 'left',
field: ({ dms }) => dms.hasFile,
label: t('Original'),
name: 'original',
},
{
align: 'left',
field: ({ dms }) => dms.file,
label: t('File'),
name: 'file',
},
{
align: 'left',
field: ({ dms }) => dms.worker.user.name,
label: t('Employee'),
name: 'employee',
},
{
align: 'left',
field: (value) => value.dms.created,
label: t('Created'),
name: 'created',
format: (value) => toDateTimeFormat(value),
},
{
align: 'right',
field: 'actions',
label: '',
name: 'actions',
},
]);
const setData = () => {
ClientDmsRef.value.fetch();
};
const toCustomerFileManagementCreate = () => {
router.push({ name: 'CustomerFileManagementCreate' });
};
</script>
<template>
<FetchData
ref="ClientDmsRef"
:filter="filter"
@on-fetch="(data) => (rows = data)"
auto-load
url="ClientDms"
/>
<QPage class="column items-center q-pa-md">
<QTable
:columns="columns"
:pagination="{ rowsPerPage: 12 }"
:rows="rows"
class="full-width q-mt-md"
row-key="id"
v-if="rows?.length"
>
<template #body-cell="props">
<QTd :props="props">
<QTr :props="props" class="cursor-pointer">
<component
:is="
props.col.name === 'order' && !props.value
? 'span'
: tableColumnComponents[props.col.name].component
"
@click="tableColumnComponents[props.col.name].event(props)"
class="col-content"
v-bind="tableColumnComponents[props.col.name].props(props)"
>
<template v-if="props.col.name !== 'original'">
<span
:class="{
link:
props.col.name === 'employee' ||
props.col.name === 'file',
}"
>
{{ props.value }}
</span>
</template>
<WorkerDescriptorProxy
:id="props.row.dms.workerFk"
v-if="props.col.name === 'employee'"
/>
</component>
</QTr>
</QTd>
</template>
</QTable>
<h5 class="flex justify-center color-vn-label" v-else>
{{ t('globals.noResults') }}
</h5>
</QPage>
<QPageSticky :offset="[18, 18]">
<QBtn
@click.stop="toCustomerFileManagementCreate()"
color="primary"
fab
v-shortcut="'+'"
icon="add"
/>
<QTooltip>
{{ t('Upload file') }}
</QTooltip>
</QPageSticky>
</template>
<i18n>
es:
Id: Id
Type: Tipo
Order: Orden
Reference: Referencia
Description: Descripción
Original: Original
File: Fichero
Employee: Empleado
Created: Fecha creación
Upload file: Subir fichero
</i18n>

View File

@ -1,96 +0,0 @@
<script setup>
import { useI18n } from 'vue-i18n';
import { useRoute, useRouter } from 'vue-router';
import { useQuasar } from 'quasar';
import { downloadFile } from 'src/composables/downloadFile';
import CustomerFileManagementDelete from 'src/pages/Customer/components/CustomerFileManagementDelete.vue';
const { t } = useI18n();
const quasar = useQuasar();
const route = useRoute();
const router = useRouter();
const $props = defineProps({
id: {
type: Number,
required: true,
},
promise: {
type: Function,
required: true,
},
});
const setDownloadFile = () => downloadFile($props.id);
const toCustomerFileManagementEdit = () => {
router.push({
name: 'CustomerFileManagementEdit',
params: {
id: route.params.id,
dmsId: $props.id,
},
});
};
const showCustomerFileManagementDeleteDialog = () => {
quasar.dialog({
component: CustomerFileManagementDelete,
componentProps: {
id: $props.id,
promise: setData,
},
});
};
const setData = () => {
$props.promise();
};
</script>
<template>
<div>
<QIcon
@click.stop="setDownloadFile"
color="primary"
name="cloud_download"
size="sm"
>
<QTooltip>
{{ t('actionFile', { action: t('globals.download') }) }}
</QTooltip>
</QIcon>
<QIcon
@click.stop="toCustomerFileManagementEdit"
class="q-ml-md"
color="primary"
name="edit"
size="sm"
>
<QTooltip>
{{ t('actionFile', { action: t('globals.edit') }) }}
</QTooltip>
</QIcon>
<QIcon
@click.stop="showCustomerFileManagementDeleteDialog"
class="q-ml-md"
color="primary"
name="delete"
size="sm"
>
<QTooltip>
{{ t('actionFile', { action: t('globals.remove') }) }}
</QTooltip>
</QIcon>
</div>
</template>
<i18n>
en:
actionFile: '{action} file'
es:
actionFile: '{action} fichero'
</i18n>

View File

@ -1,260 +0,0 @@
<script setup>
import { onBeforeMount, ref, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import { useRoute, useRouter } from 'vue-router';
import axios from 'axios';
import { useState } from 'src/composables/useState';
import { useValidator } from 'src/composables/useValidator';
import useNotify from 'src/composables/useNotify';
import FetchData from 'components/FetchData.vue';
import VnRow from 'components/ui/VnRow.vue';
import VnSelect from 'src/components/common/VnSelect.vue';
import VnInput from 'src/components/common/VnInput.vue';
const { notify } = useNotify();
const { t } = useI18n();
const { validate } = useValidator();
const route = useRoute();
const router = useRouter();
const state = useState();
const user = state.getUser();
const filterFindOne = { where: { code: 'paymentsLaw' } };
const filterCompanies = { order: ['code'] };
const filterWarehouses = { order: ['name'] };
const inputFileRef = ref();
const client = ref({});
const findOne = ref([]);
const allowedContentTypes = ref([]);
const optionsCompanies = ref([]);
const optionsWarehouses = ref([]);
const optionsDmsTypes = ref([]);
const isLoading = ref(false);
const dms = ref({
hasFile: false,
});
onBeforeMount(() => {
const { companyFk, warehouseFk } = user.value;
dms.value.reference = route.params.id;
dms.value.companyId = companyFk;
dms.value.warehouseId = warehouseFk;
});
watch([client, findOne], ([newClient, newFindOne]) => {
dms.value.description = t('clientFileDescription', {
dmsTypeName: newFindOne.name?.toUpperCase(),
clientName: newClient.name?.toUpperCase(),
clientId: newClient.id,
});
dms.value.dmsTypeId = newFindOne.id;
});
const saveData = async () => {
try {
const formData = new FormData();
const files = dms.value.files;
if (files && files.length > 0) {
for (let file of files) {
formData.append(file.name, file);
}
dms.value.hasFileAttached = true;
const url = `clients/${route.params.id}/uploadFile`;
await axios.post(url, formData, {
params: dms.value,
});
notify('globals.dataSaved', 'positive');
toCustomerFileManagement();
}
} catch (error) {
notify(error.message, 'negative');
}
};
const toCustomerFileManagement = () => {
router.push({ name: 'CustomerFileManagement' });
};
</script>
<template>
<FetchData
@on-fetch="(data) => (client = data)"
auto-load
:url="`Clients/${route.params.id}/getCard`"
/>
<FetchData
:filter="filterFindOne"
@on-fetch="(data) => (findOne = data)"
auto-load
url="DmsTypes/findOne"
/>
<FetchData
@on-fetch="(data) => (allowedContentTypes = data)"
auto-load
url="DmsContainers/allowedContentTypes"
/>
<FetchData
:filter="filterCompanies"
@on-fetch="(data) => (optionsCompanies = data)"
auto-load
url="Companies"
/>
<FetchData
:filter="filterWarehouses"
@on-fetch="(data) => (optionsWarehouses = data)"
auto-load
url="Warehouses"
/>
<FetchData
:filter="filterWarehouses"
@on-fetch="(data) => (optionsDmsTypes = data)"
auto-load
url="DmsTypes"
/>
<Teleport to="#st-actions">
<QBtnGroup push class="q-gutter-x-sm">
<QBtn
:disabled="isLoading"
:label="t('globals.cancel')"
:loading="isLoading"
@click="toCustomerFileManagement"
color="primary"
flat
icon="close"
/>
<QBtn
:disabled="isLoading"
:label="t('globals.save')"
:loading="isLoading"
@click.stop="saveData"
color="primary"
icon="save"
/>
</QBtnGroup>
</Teleport>
<QCard class="q-pa-lg">
<QCardSection>
<QForm>
<VnRow>
<div class="col">
<VnInput
:label="t('Reference')"
clearable
v-model="dms.reference"
/>
</div>
<div class="col">
<VnSelect
:label="t('Company')"
:options="optionsCompanies"
:rules="validate('entry.companyFk')"
option-label="code"
option-value="id"
v-model="dms.companyId"
/>
</div>
</VnRow>
<VnRow>
<div class="col">
<VnSelect
:label="t('Warehouse')"
:options="optionsWarehouses"
option-label="name"
option-value="id"
v-model="dms.warehouseId"
/>
</div>
<div class="col">
<VnSelect
:label="t('Type')"
:options="optionsDmsTypes"
option-label="name"
option-value="id"
v-model="dms.dmsTypeId"
/>
</div>
</VnRow>
<VnRow>
<div class="col">
<VnInput
:label="t('Description')"
:rules="validate('route.description')"
clearable
type="textarea"
v-model="dms.description"
/>
</div>
</VnRow>
<VnRow>
<div class="col">
<QFile
ref="inputFileRef"
class="required"
:label="t('File')"
v-model="dms.files"
multiple
:accept="allowedContentTypes.join(',')"
clearable
clear-icon="close"
>
<template #append>
<QBtn
icon="vn:attach"
flat
round
padding="xs"
@click="inputFileRef.pickFiles()"
>
<QTooltip>
{{ t('Select a file') }}
</QTooltip>
</QBtn>
<QBtn icon="info" flat round padding="xs">
<QTooltip max-width="30rem">
{{
`${t(
'Allowed content types'
)}: ${allowedContentTypes.join(', ')}`
}}
</QTooltip>
</QBtn>
</template>
</QFile>
</div>
</VnRow>
<QCheckbox
:label="t('Generate identifier for original file')"
v-model="dms.hasFile"
/>
</QForm>
</QCardSection>
</QCard>
</template>
<i18n>
en:
clientFileDescription: '{dmsTypeName} FROM CLIENT {clientName} ID {clientId}'
es:
Reference: Referencia
Company: Empresa
Warehouse: Almacén
Type: Tipo
Description: Descripción
clientFileDescription: '{dmsTypeName} DEL CLIENTE {clientName} ID {clientId}'
File: Fichero
Select a file: Selecciona un fichero
Allowed content types: Tipos de archivo permitidos
Generate identifier for original file: Generar identificador para archivo original
</i18n>

View File

@ -1,82 +0,0 @@
<script setup>
import { ref } from 'vue';
import { useI18n } from 'vue-i18n';
import { useDialogPluginComponent } from 'quasar';
import axios from 'axios';
import useNotify from 'src/composables/useNotify';
const $props = defineProps({
id: {
type: Number,
required: true,
},
promise: {
type: Function,
required: true,
},
});
const { dialogRef } = useDialogPluginComponent();
const { notify } = useNotify();
const { t } = useI18n();
const closeButton = ref(null);
const isLoading = ref(false);
const deleteDms = async () => {
isLoading.value = true;
try {
await axios.post(`ClientDms/${$props.id}/removeFile`);
if ($props.promise) await $props.promise();
notify('globals.dataDeleted', 'positive');
} catch (error) {
notify(error.message, 'negative');
} finally {
closeButton.value.click();
isLoading.value = false;
}
};
</script>
<template>
<QDialog ref="dialogRef">
<QCard class="q-pa-md q-mb-md">
<span ref="closeButton" class="row justify-end close-icon" v-close-popup>
<QIcon name="close" size="sm" />
</span>
<QCardSection>
<div class="mt-1 text-h6">{{ t('This file will be deleted') }}</div>
<div>{{ t('Are you sure you want to continue?') }}</div>
</QCardSection>
<QCardActions class="flex justify-end">
<QBtn
:disabled="isLoading"
:label="t('globals.cancel')"
:loading="isLoading"
class="q-mr-xl"
color="primary"
flat
v-close-popup
/>
<QBtn
:disabled="isLoading"
:label="t('globals.save')"
:loading="isLoading"
@click.stop="deleteDms"
color="primary"
/>
</QCardActions>
</QCard>
</QDialog>
</template>
<i18n>
es:
This file will be deleted: Este fichero va a ser borrado
Are you sure you want to continue?: ¿Seguro que quieres continuar?
</i18n>

View File

@ -1,237 +0,0 @@
<script setup>
import { ref } from 'vue';
import { useI18n } from 'vue-i18n';
import { useRoute, useRouter } from 'vue-router';
import axios from 'axios';
import { useValidator } from 'src/composables/useValidator';
import useNotify from 'src/composables/useNotify';
import FetchData from 'components/FetchData.vue';
import VnRow from 'components/ui/VnRow.vue';
import VnSelect from 'src/components/common/VnSelect.vue';
import VnInput from 'src/components/common/VnInput.vue';
const { notify } = useNotify();
const { t } = useI18n();
const { validate } = useValidator();
const route = useRoute();
const router = useRouter();
const filterCompanies = { order: ['code'] };
const filterWarehouses = { order: ['name'] };
const inputFileRef = ref();
const allowedContentTypes = ref([]);
const optionsCompanies = ref([]);
const optionsWarehouses = ref([]);
const optionsDmsTypes = ref([]);
const isLoading = ref(false);
const dms = ref({
hasFile: true,
});
const setCurrentDms = (data) => {
dms.value.reference = data.reference;
dms.value.companyId = data.companyFk;
dms.value.warehouseId = data.warehouseFk;
dms.value.dmsTypeId = data.dmsTypeFk;
dms.value.description = data.description;
};
const saveData = async () => {
try {
const formData = new FormData();
const files = dms.value.files;
if (files && files.length > 0) {
for (let file of files) {
formData.append(file.name, file);
}
dms.value.hasFileAttached = true;
const url = `dms/${route.params.dmsId}/updateFile`;
await axios.post(url, formData, {
params: dms.value,
});
notify('globals.dataSaved', 'positive');
toCustomerFileManagement();
}
} catch (error) {
notify(error.message, 'negative');
}
};
const toCustomerFileManagement = () => {
router.push({ name: 'CustomerFileManagement' });
};
</script>
<template>
<FetchData :url="`Dms/${route.params.dmsId}`" @on-fetch="setCurrentDms" auto-load />
<FetchData
@on-fetch="(data) => (allowedContentTypes = data)"
auto-load
url="DmsContainers/allowedContentTypes"
/>
<FetchData
:filter="filterCompanies"
@on-fetch="(data) => (optionsCompanies = data)"
auto-load
url="Companies"
/>
<FetchData
:filter="filterWarehouses"
@on-fetch="(data) => (optionsWarehouses = data)"
auto-load
url="Warehouses"
/>
<FetchData
:filter="filterWarehouses"
@on-fetch="(data) => (optionsDmsTypes = data)"
auto-load
url="DmsTypes"
/>
<Teleport to="#st-actions">
<QBtnGroup push class="q-gutter-x-sm">
<QBtn
:disabled="isLoading"
:label="t('globals.cancel')"
:loading="isLoading"
@click="toCustomerFileManagement"
color="primary"
flat
icon="close"
/>
<QBtn
:disabled="isLoading"
:label="t('globals.save')"
:loading="isLoading"
@click.stop="saveData"
color="primary"
icon="save"
/>
</QBtnGroup>
</Teleport>
<QCard class="q-pa-lg">
<QCardSection>
<QForm>
<VnRow>
<div class="col">
<VnInput
:label="t('Reference')"
clearable
v-model="dms.reference"
/>
</div>
<div class="col">
<VnSelect
:label="t('Company')"
:options="optionsCompanies"
:rules="validate('entry.companyFk')"
option-label="code"
option-value="id"
v-model="dms.companyId"
/>
</div>
</VnRow>
<VnRow>
<div class="col">
<VnSelect
:label="t('Warehouse')"
:options="optionsWarehouses"
option-label="name"
option-value="id"
v-model="dms.warehouseId"
/>
</div>
<div class="col">
<VnSelect
:label="t('Type')"
:options="optionsDmsTypes"
option-label="name"
option-value="id"
v-model="dms.dmsTypeId"
/>
</div>
</VnRow>
<VnRow>
<div class="col">
<VnInput
:label="t('Description')"
:rules="validate('route.description')"
clearable
type="textarea"
v-model="dms.description"
/>
</div>
</VnRow>
<VnRow>
<div class="col">
<QFile
ref="inputFileRef"
class="required"
:label="t('File')"
v-model="dms.files"
multiple
:accept="allowedContentTypes.join(',')"
clearable
clear-icon="close"
>
<template #append>
<QBtn
icon="vn:attach"
flat
round
padding="xs"
@click="inputFileRef.pickFiles()"
>
<QTooltip>
{{ t('Select a file') }}
</QTooltip>
</QBtn>
<QBtn icon="info" flat round padding="xs">
<QTooltip max-width="30rem">
{{
`${t(
'Allowed content types'
)}: ${allowedContentTypes.join(', ')}`
}}
</QTooltip>
</QBtn>
</template>
</QFile>
</div>
</VnRow>
<QCheckbox
:label="t('Generate identifier for original file')"
v-model="dms.hasFile"
disable
/>
</QForm>
</QCardSection>
</QCard>
</template>
<i18n>
en:
clientFileDescription: '{dmsTypeName} FROM CLIENT {clientName} ID {clientId}'
es:
Reference: Referencia
Company: Empresa
Warehouse: Almacén
Type: Tipo
Description: Descripción
clientFileDescription: '{dmsTypeName} DEL CLIENTE {clientName} ID {clientId}'
File: Fichero
Select a file: Selecciona un fichero
Allowed content types: Tipos de archivo permitidos
Generate identifier for original file: Generar identificador para archivo original
</i18n>

View File

@ -239,9 +239,9 @@ const customerCard = {
icon: 'vn:onlinepayment',
},
{
name: 'CustomerFileManagement',
title: 'fileManagement',
icon: 'Upload',
name: 'CustomerDms',
title: 'dms',
icon: 'cloud_upload',
},
{
name: 'CustomerUnpaid',
@ -313,47 +313,12 @@ const customerCard = {
import('src/pages/Customer/Card/CustomerWebPayment.vue'),
},
{
path: 'file-management',
name: 'CustomerFileManagement',
path: 'dms',
name: 'CustomerDms',
meta: {
title: 'fileManagement',
title: 'dms',
},
component: () =>
import('src/pages/Customer/Card/CustomerFileManagement.vue'),
},
{
path: 'file-management',
name: 'CustomerFileManagementCard',
redirect: { name: 'CustomerFileManagement' },
children: [
{
path: '',
name: 'CustomerFileManagement',
meta: {
title: 'fileManagement',
},
component: () =>
import(
'src/pages/Customer/Card/CustomerFileManagement.vue'
),
},
{
path: 'create',
name: 'CustomerFileManagementCreate',
component: () =>
import(
'src/pages/Customer/components/CustomerFileManagementCreate.vue'
),
},
{
path: ':dmsId/edit',
name: 'CustomerFileManagementEdit',
component: () =>
import(
'src/pages/Customer/components/CustomerFileManagementEdit.vue'
),
},
],
component: () => import('src/pages/Customer/Card/CustomerDms.vue'),
},
{
path: 'unpaid',