Skip to content

Commit b636d1b

Browse files
authored
Merge pull request #42 from Libertech-FR/fix-mailwrapper
FIX mailwrapper to setup mode
2 parents 5f79686 + b3d672c commit b636d1b

File tree

6 files changed

+291
-295
lines changed

6 files changed

+291
-295
lines changed

app/src/pages/mails.vue

Lines changed: 278 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,278 @@
1+
<template lang="pug">
2+
div
3+
q-card(flat)
4+
q-card-section(horizontal)
5+
q-card-section.full-width(:style="{maxWidth: '50vw', overflow: 'hidden'}")
6+
//v-model:selected="selected"
7+
// selection="multiple"
8+
q-table.tk-sticky-last-column-table(
9+
v-model:pagination="pagination"
10+
title="Mails"
11+
:rows="mails?.data"
12+
row-key="uid"
13+
@request="onRequest"
14+
:rows-per-page-options="[5, 10, 15]"
15+
:columns="columns"
16+
:loading="pending"
17+
rows-per-page-label="Lignes par page"
18+
no-data-label="Aucune donnée"
19+
loading-label="Chargement..."
20+
no-results-label="Aucun résultat"
21+
:pagination-label="(firstRowIndex, endRowIndex, totalRowsNumber) => `${firstRowIndex}-${endRowIndex} sur ${totalRowsNumber} lignes`"
22+
:selected-rows-label="(numberOfRows) => `${numberOfRows} Mails sélectionnées`"
23+
flat
24+
)
25+
template(#body-cell-actions="props")
26+
q-td(:props="props")
27+
q-btn-group(flat rounded)
28+
q-btn(icon="mdi-eye" color="primary" @click="goToMail(props.row)" size="sm" flat)
29+
q-tooltip.text-body2(transition-show="scale" transition-hide="scale") Afficher le ticket
30+
q-btn(icon="mdi-delete" color="primary" @click="deleteMail(props.row)" size="sm" flat)
31+
q-tooltip.text-body2(transition-show="scale" transition-hide="scale") Supprimer le ticket
32+
q-separator(vertical)
33+
q-card-section.full-width(:style="{maxWidth: '50vw', overflow: 'hidden'}")
34+
div.flex.items-center.full-height.justify-center(v-if='!target')
35+
p Selectionnez un email pour afficher son contenu...
36+
q-card(v-else)
37+
q-card-actions
38+
q-toolbar-title(v-text='target?.subject' style='flex: 100 1 0%')
39+
q-space
40+
q-btn(color="negative" icon='mdi-delete' @click="deleteMail(target)")
41+
q-btn(color="primary" icon='mdi-content-save' @click="importMail(target)")
42+
q-card-section.q-pa-xs
43+
q-tabs(v-model="tab" dense)
44+
q-tab(name="email" icon="mdi-mail" label="Email")
45+
q-tab(name="headers" icon="mdi-format-list-text" label="headers")
46+
q-tab(name="raw" icon="mdi-email-newsletter" label="Contenu")
47+
q-tab-panels(v-model="tab")
48+
q-tab-panel.no-padding(name="email")
49+
object.bg-white(:data='"http://localhost:7100/tickets/mails/" + target?.accountId + "/" + target?.seq + "/render?signature=" + target?.signature' style='width: 100%; height: 75vh;')
50+
p Impossible de charger le contenu du mail
51+
a(:href='"http://localhost:7100/tickets/mails/" + target?.accountId + "/" + target?.seq + "/render?signature=" + target?.signature' target='_blank') Lien direct
52+
q-tab-panel.no-padding(name="headers")
53+
q-table(
54+
:rows="target.headers"
55+
:pagination='{rowsPerPage: 12}'
56+
:pagination-label="(firstRowIndex, endRowIndex, totalRowsNumber) => `${firstRowIndex}-${endRowIndex} sur ${totalRowsNumber} lignes`"
57+
rows-per-page-label="Lignes par page"
58+
no-data-label="Aucune donnée"
59+
loading-label="Chargement..."
60+
no-results-label="Aucun résultat"
61+
flat
62+
)
63+
q-tab-panel.no-padding(name="raw")
64+
object.bg-white(:data='"http://localhost:7100/tickets/mails/" + target?.accountId + "/" + target?.seq + "/source?signature=" + target?.signature' style='width: 100%; height: 75vh;')
65+
p Impossible de charger le contenu du mail
66+
a(:href='"http://localhost:7100/tickets/mails/" + target?.accountId + "/" + target?.seq + "/source?signature=" + target?.signature' target='_blank') Lien direct
67+
</template>
68+
69+
<script lang="ts" setup>
70+
import { computed, useDayjs } from '#imports'
71+
import { useRoute, useRouter } from 'nuxt/app'
72+
import { ref } from 'vue'
73+
import type { QTableProps } from 'quasar'
74+
// import type { components } from '#build/types/service-api'
75+
import { omit } from 'radash'
76+
77+
type Mail = any
78+
// type Mail = components["schemas"]['TicketDto']
79+
const route = useRoute()
80+
const $q = useQuasar()
81+
82+
const selected = ref<Mail[]>([])
83+
const pagination = ref<QTableProps['pagination']>({
84+
page: 1,
85+
rowsPerPage: 10,
86+
rowsNumber: 10,
87+
})
88+
const tab = ref('')
89+
const target = ref<Mail | null>(null)
90+
const { data: mails, refresh, pending, error } = await useHttpApi('/tickets/mails', {
91+
method: 'get',
92+
query: computed(() => {
93+
return {
94+
...omit(route.query, ['accountId', 'seq']),
95+
}
96+
})
97+
})
98+
if (error.value) {
99+
console.error(error.value)
100+
}
101+
if (route.query.accountId && route.query.seq) {
102+
const { data } = await useHttpApi(`/tickets/mails/${route.query.accountId}/${route.query.seq}`, {
103+
method: 'get',
104+
})
105+
const mail = mails.value?.data.filter((mail: any) => mail.accountId === route.query.accountId && mail.seq === parseInt(`${route.query.seq}`, 10))[0]
106+
target.value = {
107+
...data.value?.data,
108+
...mail,
109+
}
110+
tab.value = 'email'
111+
}
112+
const daysjs = useDayjs()
113+
const columns = ref<QTableProps['columns']>([
114+
{
115+
name: 'uid',
116+
label: 'ID',
117+
field: 'uid',
118+
align: 'left',
119+
},
120+
{
121+
name: 'accountName',
122+
label: 'Compte',
123+
field: 'accountName',
124+
align: 'left',
125+
},
126+
{
127+
name: 'envelope.subject',
128+
label: 'Sujet',
129+
field: (row: Mail) => {
130+
const $q = useQuasar()
131+
const maxLength = ($q.screen.width / 2 / 10) - 30
132+
if (row.envelope.subject.length <= maxLength) {
133+
return row.envelope.subject
134+
}
135+
let truncated = row.envelope.subject.substring(0, maxLength)
136+
const re = new RegExp(/\s+\S*$/)
137+
const match = re.exec(truncated)
138+
truncated = truncated.substring(0, match?.index!)
139+
return `${truncated} ...`
140+
},
141+
align: 'left',
142+
},
143+
{
144+
name: 'envelope.date',
145+
label: 'Date de réception',
146+
field: (row: Mail) => row.envelope.date,
147+
format: (val: string) => daysjs(val).format('DD/MM/YYYY HH:mm'),
148+
align: 'left',
149+
},
150+
{
151+
name: 'actions',
152+
label: 'Actions',
153+
field: 'actions',
154+
align: 'left',
155+
},
156+
])
157+
158+
const deleteMail = async (mail: Mail) => {
159+
$q.dialog({
160+
title: 'Suppression',
161+
message: 'Vous êtes sur le point de supprimer un email, êtes-vous sûr ?',
162+
cancel: true,
163+
persistent: true,
164+
color: 'negative',
165+
}).onOk(async () => {
166+
const { error } = await useHttpApi(`/tickets/mails/${mail.accountId}/${mail.seq}`, {
167+
method: 'delete',
168+
})
169+
if (error.value) {
170+
$q.notify({
171+
color: 'negative',
172+
message: `Impossible de supprimer l'email: ${mail.uid}`,
173+
})
174+
return
175+
}
176+
$q.notify({
177+
color: 'positive',
178+
message: 'Email supprimé avec succès',
179+
})
180+
target.value = null
181+
await refresh()
182+
}).onCancel(() => target.value = null)
183+
}
184+
const importMail = async (mail: any) => {
185+
const { data, error } = await useHttpApi(`/tickets/mails/import`, {
186+
method: 'post',
187+
body: {
188+
account: mail.accountId,
189+
seq: mail.seq,
190+
uid: mail.uid,
191+
id: mail.id,
192+
},
193+
})
194+
if (error.value) {
195+
console.log()
196+
$q.notify({
197+
color: 'negative',
198+
message: `Impossible d\'importer l'email <${mail.uid}> ${error.value?.data?.message || error.value?.message}`,
199+
})
200+
return
201+
}
202+
$q.notify({
203+
color: 'positive',
204+
message: 'Email importé avec succès',
205+
})
206+
await refresh()
207+
}
208+
const goToMail = async (mail: Mail) => {
209+
const router = useRouter()
210+
router.replace({
211+
query: {
212+
...route.query,
213+
accountId: mail.accountId,
214+
seq: mail.seq,
215+
}
216+
})
217+
const { data } = await useHttpApi(`/tickets/mails/${mail.accountId}/${mail.seq}`, {
218+
method: 'get',
219+
})
220+
target.value = {
221+
...mail,
222+
...data.value?.data,
223+
}
224+
tab.value = 'email'
225+
}
226+
const onRequest = async (props: QTableProps) => {
227+
const { page, rowsPerPage, sortBy, descending } = props.pagination!
228+
pagination.value!.rowsNumber = mails.value?.total
229+
pagination.value!.page = page
230+
pagination.value!.rowsPerPage = rowsPerPage
231+
pagination.value!.sortBy = sortBy
232+
pagination.value!.descending = descending
233+
paginationQuery()
234+
}
235+
const paginationQuery = () => {
236+
const router = useRouter()
237+
const query = removeSortKey()
238+
const skip = `${(pagination.value?.page! - 1) * pagination.value?.rowsPerPage!}`
239+
const limit = `${pagination.value?.rowsPerPage!}`
240+
query['skip'] = skip
241+
query['limit'] = limit
242+
router.replace({
243+
query
244+
})
245+
}
246+
const removeSortKey = () => {
247+
const route = useRoute()
248+
const query = { ...route.query }
249+
for (const key in query) {
250+
if (key.startsWith('sort[')) {
251+
delete query[key]
252+
}
253+
}
254+
return query
255+
}
256+
257+
onMounted(async () => {
258+
const route = useRoute()
259+
pagination.value!.rowsNumber = mails.value?.total
260+
const query = { ...route.query }
261+
const limit = query.limit ?? 10
262+
const skip = query.skip ?? 0
263+
pagination.value!.rowsPerPage = parseInt(limit as string)
264+
pagination.value!.page = parseInt(skip as string) / parseInt(limit as string) + 1
265+
266+
let sortKey = 'metadata.lastUpdatedAt'
267+
let sortDirection = 'desc'
268+
for (const key in query) {
269+
if (key.startsWith('sort')) {
270+
sortKey = key.replace('sort[', '').replace(']', '')
271+
sortDirection = query[key] === 'desc' ? 'desc' : 'asc'
272+
}
273+
}
274+
pagination.value!.sortBy = sortKey
275+
pagination.value!.descending = sortDirection === 'desc'
276+
paginationQuery()
277+
})
278+
</script>

0 commit comments

Comments
 (0)