refs #6336 feat(claim): improvements
gitea/salix-front/pipeline/pr-dev This commit looks good
Details
gitea/salix-front/pipeline/pr-dev This commit looks good
Details
This commit is contained in:
parent
32382622e4
commit
4efe09722f
|
@ -24,6 +24,10 @@ const $props = defineProps({
|
||||||
type: String,
|
type: String,
|
||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
|
limit: {
|
||||||
|
type: Number,
|
||||||
|
default: 20,
|
||||||
|
},
|
||||||
saveUrl: {
|
saveUrl: {
|
||||||
type: String,
|
type: String,
|
||||||
default: null,
|
default: null,
|
||||||
|
@ -76,6 +80,7 @@ defineExpose({
|
||||||
reset,
|
reset,
|
||||||
hasChanges,
|
hasChanges,
|
||||||
saveChanges,
|
saveChanges,
|
||||||
|
getChanges,
|
||||||
});
|
});
|
||||||
|
|
||||||
async function fetch(data) {
|
async function fetch(data) {
|
||||||
|
@ -260,6 +265,7 @@ watch(formUrl, async () => {
|
||||||
<template>
|
<template>
|
||||||
<VnPaginate
|
<VnPaginate
|
||||||
:url="url"
|
:url="url"
|
||||||
|
:limit="limit"
|
||||||
v-bind="$attrs"
|
v-bind="$attrs"
|
||||||
@on-fetch="fetch"
|
@on-fetch="fetch"
|
||||||
:skeleton="false"
|
:skeleton="false"
|
||||||
|
|
|
@ -75,7 +75,7 @@ async function insert() {
|
||||||
<QPageSticky position="bottom-right" :offset="[25, 25]" v-if="addNote">
|
<QPageSticky position="bottom-right" :offset="[25, 25]" v-if="addNote">
|
||||||
<QBtn color="primary" icon="add" size="lg" round @click="noteModal = true" />
|
<QBtn color="primary" icon="add" size="lg" round @click="noteModal = true" />
|
||||||
</QPageSticky>
|
</QPageSticky>
|
||||||
<QDialog v-model="noteModal" @hide="newNote = ''">
|
<QDialog v-model="noteModal" @hide="newNote = ''" persistent>
|
||||||
<QCard>
|
<QCard>
|
||||||
<QCardSection>
|
<QCardSection>
|
||||||
<QItem class="q-px-none">
|
<QItem class="q-px-none">
|
||||||
|
|
|
@ -96,8 +96,7 @@ export function useArrayData(key, userOptions) {
|
||||||
});
|
});
|
||||||
|
|
||||||
const { limit } = filter;
|
const { limit } = filter;
|
||||||
|
hasMoreData.value = limit && response.data.length >= limit;
|
||||||
hasMoreData.value = response.data.length >= limit;
|
|
||||||
|
|
||||||
if (append) {
|
if (append) {
|
||||||
if (!store.data) store.data = [];
|
if (!store.data) store.data = [];
|
||||||
|
|
|
@ -121,11 +121,6 @@ async function fetchMana() {
|
||||||
mana.value = response.data;
|
mana.value = response.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function updateQuantity({ id, quantity }) {
|
|
||||||
if (!id) return;
|
|
||||||
await axios.patch(`ClaimBeginnings/${id}`, { quantity });
|
|
||||||
}
|
|
||||||
|
|
||||||
async function updateDiscount({ saleFk, discount, canceller }) {
|
async function updateDiscount({ saleFk, discount, canceller }) {
|
||||||
const body = { salesIds: [saleFk], newDiscount: discount };
|
const body = { salesIds: [saleFk], newDiscount: discount };
|
||||||
const claimId = claim.value.ticketFk;
|
const claimId = claim.value.ticketFk;
|
||||||
|
@ -155,6 +150,10 @@ function showImportDialog() {
|
||||||
})
|
})
|
||||||
.onOk(() => claimLinesForm.value.reload());
|
.onOk(() => claimLinesForm.value.reload());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function saveWhenHasChanges() {
|
||||||
|
claimLinesForm.value.getChanges().updates && claimLinesForm.value.onSubmit();
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<Teleport to="#st-data" v-if="stateStore.isSubToolbarShown()">
|
<Teleport to="#st-data" v-if="stateStore.isSubToolbarShown()">
|
||||||
|
@ -181,161 +180,135 @@ function showImportDialog() {
|
||||||
@on-fetch="onFetchClaim"
|
@on-fetch="onFetchClaim"
|
||||||
auto-load
|
auto-load
|
||||||
/>
|
/>
|
||||||
<div class="column items-center">
|
<div class="q-pa-md">
|
||||||
<div class="list">
|
<CrudModel
|
||||||
<CrudModel
|
data-key="ClaimLines"
|
||||||
data-key="ClaimLines"
|
ref="claimLinesForm"
|
||||||
ref="claimLinesForm"
|
:url="`Claims/${route.params.id}/lines`"
|
||||||
:url="`Claims/${route.params.id}/lines`"
|
save-url="ClaimBeginnings/crud"
|
||||||
save-url="ClaimBeginnings/crud"
|
:filter="linesFilter"
|
||||||
:filter="linesFilter"
|
@on-fetch="onFetch"
|
||||||
@on-fetch="onFetch"
|
@save-changes="onFetch"
|
||||||
@save-changes="onFetch"
|
v-model:selected="selected"
|
||||||
v-model:selected="selected"
|
:default-save="false"
|
||||||
:default-save="false"
|
:default-reset="false"
|
||||||
:default-reset="false"
|
auto-load
|
||||||
auto-load
|
:limit="0"
|
||||||
>
|
>
|
||||||
<template #body="{ rows }">
|
<template #body="{ rows }">
|
||||||
<QTable
|
<QTable
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
:rows="rows"
|
:rows="rows"
|
||||||
:dense="$q.screen.lt.md"
|
:dense="$q.screen.lt.md"
|
||||||
row-key="id"
|
row-key="id"
|
||||||
selection="multiple"
|
selection="multiple"
|
||||||
v-model:selected="selected"
|
v-model:selected="selected"
|
||||||
:grid="$q.screen.lt.md"
|
:grid="$q.screen.lt.md"
|
||||||
>
|
>
|
||||||
<template #body-cell-claimed="{ row, value }">
|
<template #body-cell-claimed="{ row }">
|
||||||
<QTd auto-width align="right" class="text-primary">
|
<QTd auto-width align="right" class="text-primary">
|
||||||
<span>{{ value }}</span>
|
<QInput
|
||||||
|
v-model="row.quantity"
|
||||||
<QPopupEdit
|
type="number"
|
||||||
v-model="row.quantity"
|
dense
|
||||||
v-slot="scope"
|
@keyup.enter="saveWhenHasChanges()"
|
||||||
:title="t('Claimed quantity')"
|
@blur="saveWhenHasChanges()"
|
||||||
@update:model-value="updateQuantity(row)"
|
/>
|
||||||
buttons
|
</QTd>
|
||||||
>
|
</template>
|
||||||
<QInput
|
<template #body-cell-description="{ row, value }">
|
||||||
v-model="scope.value"
|
<QTd auto-width align="right" class="text-primary">
|
||||||
type="number"
|
{{ value }}
|
||||||
dense
|
<ItemDescriptorProxy
|
||||||
autofocus
|
:id="row.sale.itemFk"
|
||||||
@keyup.enter="scope.set"
|
></ItemDescriptorProxy>
|
||||||
@focus="($event) => $event.target.select()"
|
</QTd>
|
||||||
/>
|
</template>
|
||||||
</QPopupEdit>
|
<template #body-cell-discount="{ row, value, rowIndex }">
|
||||||
</QTd>
|
<QTd auto-width align="right" class="text-primary">
|
||||||
</template>
|
{{ value }}
|
||||||
<template #body-cell-description="{ row, value }">
|
<VnDiscount
|
||||||
<QTd auto-width align="right" class="text-primary">
|
:quantity="row.quantity"
|
||||||
{{ value }}
|
:price="row.sale.price"
|
||||||
<ItemDescriptorProxy
|
:discount="row.sale.discount"
|
||||||
:id="row.sale.itemFk"
|
:mana="mana"
|
||||||
></ItemDescriptorProxy>
|
:promise="updateDiscount"
|
||||||
</QTd>
|
:data="{ saleFk: row.sale.id, rowIndex: rowIndex }"
|
||||||
</template>
|
@on-update="onUpdateDiscount"
|
||||||
<template #body-cell-discount="{ row, value, rowIndex }">
|
/>
|
||||||
<QTd auto-width align="right" class="text-primary">
|
</QTd>
|
||||||
{{ value }}
|
</template>
|
||||||
<VnDiscount
|
<!-- View for grid mode -->
|
||||||
:quantity="row.quantity"
|
<template #item="props">
|
||||||
:price="row.sale.price"
|
<div
|
||||||
:discount="row.sale.discount"
|
class="q-mb-md col-12 grid-style-transition"
|
||||||
:mana="mana"
|
:style="props.selected ? 'transform: scale(0.95);' : ''"
|
||||||
:promise="updateDiscount"
|
>
|
||||||
:data="{ saleFk: row.sale.id, rowIndex: rowIndex }"
|
<QCard>
|
||||||
@on-update="onUpdateDiscount"
|
<QCardSection>
|
||||||
/>
|
<QCheckbox v-model="props.selected" />
|
||||||
</QTd>
|
</QCardSection>
|
||||||
</template>
|
<QSeparator inset />
|
||||||
<!-- View for grid mode -->
|
<QList dense>
|
||||||
<template #item="props">
|
<QItem
|
||||||
<div
|
v-for="column of props.cols"
|
||||||
class="q-mb-md col-12 grid-style-transition"
|
:key="column.name"
|
||||||
:style="props.selected ? 'transform: scale(0.95);' : ''"
|
>
|
||||||
>
|
<QItemSection>
|
||||||
<QCard>
|
<QItemLabel caption>
|
||||||
<QCardSection>
|
{{ column.label }}
|
||||||
<QCheckbox v-model="props.selected" />
|
</QItemLabel>
|
||||||
</QCardSection>
|
</QItemSection>
|
||||||
<QSeparator inset />
|
<QItemSection side>
|
||||||
<QList dense>
|
<template v-if="column.name === 'claimed'">
|
||||||
<QItem
|
<QItemLabel class="text-primary">
|
||||||
v-for="column of props.cols"
|
<QInput
|
||||||
:key="column.name"
|
v-model="props.row.quantity"
|
||||||
>
|
type="number"
|
||||||
<QItemSection>
|
dense
|
||||||
<QItemLabel caption>
|
autofocus
|
||||||
{{ column.label }}
|
@keyup.enter="
|
||||||
|
saveWhenHasChanges()
|
||||||
|
"
|
||||||
|
@blur="saveWhenHasChanges()"
|
||||||
|
/>
|
||||||
</QItemLabel>
|
</QItemLabel>
|
||||||
</QItemSection>
|
</template>
|
||||||
<QItemSection side>
|
<template
|
||||||
<template
|
v-else-if="column.name === 'discount'"
|
||||||
v-if="column.name === 'claimed'"
|
>
|
||||||
>
|
<QItemLabel class="text-primary">
|
||||||
<QItemLabel class="text-primary">
|
{{ column.value }}
|
||||||
{{ column.value }}
|
<VnDiscount
|
||||||
<QPopupEdit
|
:quantity="props.row.quantity"
|
||||||
v-model="props.row.quantity"
|
:price="props.row.sale.price"
|
||||||
v-slot="scope"
|
:discount="
|
||||||
:title="t('Claimed quantity')"
|
props.row.sale.discount
|
||||||
@update:model-value="
|
"
|
||||||
updateQuantity(props.row)
|
:mana="mana"
|
||||||
"
|
:promise="updateDiscount"
|
||||||
buttons
|
:data="{
|
||||||
>
|
saleFk: props.row.sale.id,
|
||||||
<QInput
|
rowIndex: props.rowIndex,
|
||||||
v-model="scope.value"
|
}"
|
||||||
type="number"
|
@on-update="onUpdateDiscount"
|
||||||
dense
|
/>
|
||||||
autofocus
|
</QItemLabel>
|
||||||
@keyup.enter="scope.set"
|
</template>
|
||||||
@focus="
|
<template v-else>
|
||||||
($event) =>
|
<QItemLabel>
|
||||||
$event.target.select()
|
{{ column.value }}
|
||||||
"
|
</QItemLabel>
|
||||||
/>
|
</template>
|
||||||
</QPopupEdit>
|
</QItemSection>
|
||||||
</QItemLabel>
|
</QItem>
|
||||||
</template>
|
</QList>
|
||||||
<template
|
</QCard>
|
||||||
v-else-if="column.name === 'discount'"
|
</div>
|
||||||
>
|
</template>
|
||||||
<QItemLabel class="text-primary">
|
</QTable>
|
||||||
{{ column.value }}
|
</template>
|
||||||
<VnDiscount
|
</CrudModel>
|
||||||
:quantity="props.row.quantity"
|
|
||||||
:price="props.row.sale.price"
|
|
||||||
:discount="
|
|
||||||
props.row.sale.discount
|
|
||||||
"
|
|
||||||
:mana="mana"
|
|
||||||
:promise="updateDiscount"
|
|
||||||
:data="{
|
|
||||||
saleFk: props.row.sale.id,
|
|
||||||
rowIndex: props.rowIndex,
|
|
||||||
}"
|
|
||||||
@on-update="onUpdateDiscount"
|
|
||||||
/>
|
|
||||||
</QItemLabel>
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
<QItemLabel>
|
|
||||||
{{ column.value }}
|
|
||||||
</QItemLabel>
|
|
||||||
</template>
|
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
</QList>
|
|
||||||
</QCard>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</QTable>
|
|
||||||
</template>
|
|
||||||
</CrudModel>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<QPageSticky position="bottom-right" :offset="[25, 25]">
|
<QPageSticky position="bottom-right" :offset="[25, 25]">
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { useI18n } from 'vue-i18n';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import FetchData from 'components/FetchData.vue';
|
import FetchData from 'components/FetchData.vue';
|
||||||
import { toDate, toCurrency, toPercentage } from 'filters/index';
|
import { toDate, toCurrency, toPercentage } from 'filters/index';
|
||||||
|
import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
|
||||||
defineEmits([...useDialogPluginComponent.emits]);
|
defineEmits([...useDialogPluginComponent.emits]);
|
||||||
|
@ -118,7 +119,6 @@ function cancel() {
|
||||||
<QBtn icon="close" flat round dense v-close-popup />
|
<QBtn icon="close" flat round dense v-close-popup />
|
||||||
</QCardSection>
|
</QCardSection>
|
||||||
<QTable
|
<QTable
|
||||||
class="my-sticky-header-table"
|
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
:rows="claimableSales"
|
:rows="claimableSales"
|
||||||
row-key="saleFk"
|
row-key="saleFk"
|
||||||
|
@ -126,7 +126,14 @@ function cancel() {
|
||||||
v-model:selected="selected"
|
v-model:selected="selected"
|
||||||
square
|
square
|
||||||
flat
|
flat
|
||||||
/>
|
>
|
||||||
|
<template #body-cell-description="{ row, value }">
|
||||||
|
<QTd auto-width align="right" class="link">
|
||||||
|
{{ value }}
|
||||||
|
<ItemDescriptorProxy :id="row.itemFk"></ItemDescriptorProxy>
|
||||||
|
</QTd>
|
||||||
|
</template>
|
||||||
|
</QTable>
|
||||||
<QSeparator />
|
<QSeparator />
|
||||||
<QCardActions align="right">
|
<QCardActions align="right">
|
||||||
<QBtn :label="t('globals.cancel')" color="primary" flat @click="cancel" />
|
<QBtn :label="t('globals.cancel')" color="primary" flat @click="cancel" />
|
||||||
|
@ -148,33 +155,6 @@ function cancel() {
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
.my-sticky-header-table {
|
|
||||||
height: 400px;
|
|
||||||
|
|
||||||
thead tr th {
|
|
||||||
position: sticky;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
thead tr:first-child th {
|
|
||||||
/* this is when the loading indicator appears */
|
|
||||||
top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.q-table--loading thead tr:last-child th {
|
|
||||||
/* height of all previous header rows */
|
|
||||||
top: 48px;
|
|
||||||
}
|
|
||||||
|
|
||||||
// /* prevent scrolling behind sticky top row on focus */
|
|
||||||
tbody {
|
|
||||||
/* height of all previous header rows */
|
|
||||||
scroll-margin-top: 48px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<i18n>
|
<i18n>
|
||||||
es:
|
es:
|
||||||
Available sales lines: Líneas de venta disponibles
|
Available sales lines: Líneas de venta disponibles
|
||||||
|
|
|
@ -222,23 +222,11 @@ function openDialog(dmsId) {
|
||||||
</template>
|
</template>
|
||||||
</VnLv>
|
</VnLv>
|
||||||
<VnLv
|
<VnLv
|
||||||
:label="t('claim.summary.pickup')"
|
:label="t('claim.basicData.pickup')"
|
||||||
:value="t(`claim.summary.${claim.pickup}`)"
|
:value="t(`claim.basicData.${claim.pickup}`)"
|
||||||
/>
|
/>
|
||||||
</QCard>
|
</QCard>
|
||||||
<QCard class="vn-three">
|
<QCard class="vn-three" v-if="salesClaimed.length > 0">
|
||||||
<VnTitle
|
|
||||||
:url="`#/claim/${entityId}/notes`"
|
|
||||||
:text="t('claim.summary.notes')"
|
|
||||||
/>
|
|
||||||
<ClaimNotes
|
|
||||||
:id="entityId"
|
|
||||||
:add-note="false"
|
|
||||||
style="max-height: 300px"
|
|
||||||
order="created ASC"
|
|
||||||
/>
|
|
||||||
</QCard>
|
|
||||||
<QCard class="vn-two" v-if="salesClaimed.length > 0">
|
|
||||||
<VnTitle
|
<VnTitle
|
||||||
:url="`#/claim/${entityId}/lines`"
|
:url="`#/claim/${entityId}/lines`"
|
||||||
:text="t('claim.summary.details')"
|
:text="t('claim.summary.details')"
|
||||||
|
@ -280,6 +268,60 @@ function openDialog(dmsId) {
|
||||||
</template>
|
</template>
|
||||||
</QTable>
|
</QTable>
|
||||||
</QCard>
|
</QCard>
|
||||||
|
<QCard class="vn-two">
|
||||||
|
<VnTitle
|
||||||
|
:url="`#/claim/${entityId}/notes`"
|
||||||
|
:text="t('claim.summary.notes')"
|
||||||
|
/>
|
||||||
|
<ClaimNotes
|
||||||
|
:id="entityId"
|
||||||
|
:add-note="false"
|
||||||
|
style="max-height: 300px"
|
||||||
|
order="created ASC"
|
||||||
|
/>
|
||||||
|
</QCard>
|
||||||
|
<QCard class="vn-two" v-if="claimDms.length > 0">
|
||||||
|
<VnTitle
|
||||||
|
:url="`#/claim/${entityId}/photos`"
|
||||||
|
:text="t('claim.summary.photos')"
|
||||||
|
/>
|
||||||
|
<div class="container">
|
||||||
|
<div
|
||||||
|
class="multimedia-container"
|
||||||
|
v-for="(media, index) of claimDms"
|
||||||
|
:key="index"
|
||||||
|
>
|
||||||
|
<div class="relative-position">
|
||||||
|
<QIcon
|
||||||
|
name="play_circle"
|
||||||
|
color="primary"
|
||||||
|
size="xl"
|
||||||
|
class="absolute-center zindex"
|
||||||
|
v-if="media.isVideo"
|
||||||
|
@click.stop="openDialog(media.dmsFk)"
|
||||||
|
>
|
||||||
|
<QTooltip>Video</QTooltip>
|
||||||
|
</QIcon>
|
||||||
|
<QCard class="multimedia relative-position">
|
||||||
|
<QImg
|
||||||
|
:src="media.url"
|
||||||
|
class="rounded-borders cursor-pointer fit"
|
||||||
|
@click="openDialog(media.dmsFk)"
|
||||||
|
v-if="!media.isVideo"
|
||||||
|
>
|
||||||
|
</QImg>
|
||||||
|
<video
|
||||||
|
:src="media.url"
|
||||||
|
class="rounded-borders cursor-pointer fit"
|
||||||
|
muted="muted"
|
||||||
|
v-if="media.isVideo"
|
||||||
|
@click="openDialog(media.dmsFk)"
|
||||||
|
/>
|
||||||
|
</QCard>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</QCard>
|
||||||
<QCard class="vn-two" v-if="developments.length > 0">
|
<QCard class="vn-two" v-if="developments.length > 0">
|
||||||
<VnTitle
|
<VnTitle
|
||||||
:url="claimUrl + 'development'"
|
:url="claimUrl + 'development'"
|
||||||
|
@ -302,49 +344,6 @@ function openDialog(dmsId) {
|
||||||
</template>
|
</template>
|
||||||
</QTable>
|
</QTable>
|
||||||
</QCard>
|
</QCard>
|
||||||
<QCard class="vn-max" v-if="claimDms.length > 0">
|
|
||||||
<VnTitle
|
|
||||||
:url="`#/claim/${entityId}/photos`"
|
|
||||||
:text="t('claim.summary.photos')"
|
|
||||||
/>
|
|
||||||
<div class="container">
|
|
||||||
<div
|
|
||||||
class="multimedia-container"
|
|
||||||
v-for="(media, index) of claimDms"
|
|
||||||
:key="index"
|
|
||||||
>
|
|
||||||
<div class="relative-position">
|
|
||||||
<QIcon
|
|
||||||
name="play_circle"
|
|
||||||
color="primary"
|
|
||||||
size="xl"
|
|
||||||
class="absolute-center zindex"
|
|
||||||
v-if="media.isVideo"
|
|
||||||
@click.stop="openDialog(media.dmsFk)"
|
|
||||||
>
|
|
||||||
<QTooltip>Video</QTooltip>header
|
|
||||||
</QIcon>
|
|
||||||
<QCard class="multimedia relative-position">
|
|
||||||
<QImg
|
|
||||||
:src="media.url"
|
|
||||||
class="rounded-borders cursor-pointer fit"
|
|
||||||
@click="openDialog(media.dmsFk)"
|
|
||||||
v-if="!media.isVideo"
|
|
||||||
>
|
|
||||||
</QImg>
|
|
||||||
<video
|
|
||||||
:src="media.url"
|
|
||||||
class="rounded-borders cursor-pointer fit"
|
|
||||||
muted="muted"
|
|
||||||
v-if="media.isVideo"
|
|
||||||
@click="openDialog(media.dmsFk)"
|
|
||||||
/>
|
|
||||||
</QCard>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</QCard>
|
|
||||||
|
|
||||||
<QCard class="vn-max">
|
<QCard class="vn-max">
|
||||||
<VnTitle :url="claimUrl + 'action'" :text="t('claim.summary.actions')" />
|
<VnTitle :url="claimUrl + 'action'" :text="t('claim.summary.actions')" />
|
||||||
<div id="slider-container" class="q-px-xl q-py-md">
|
<div id="slider-container" class="q-px-xl q-py-md">
|
||||||
|
|
Loading…
Reference in New Issue