Skip to content

Commit 22cf687

Browse files
authored
Merge pull request #38 from Libertech-FR/mails
WIP Mails + fix dto
2 parents 87ba687 + bfe2c1e commit 22cf687

File tree

38 files changed

+1021
-318
lines changed

38 files changed

+1021
-318
lines changed

app/nuxt.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ export default defineNuxtConfig({
8282
iconSet: 'mdi-v5',
8383
plugins: ['Notify'],
8484
config: {
85+
dark: 'auto',
8586
notify: {
8687
timeout: 2500,
8788
position: 'top-right',

app/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@
2323
"bson-objectid": "^2.0.4",
2424
"cookie": "^0.5.0",
2525
"pinia": "^2.1.6",
26-
"quasar": "^2.12.6"
26+
"quasar": "^2.12.6",
27+
"sass": "^1.68.0"
2728
},
2829
"devDependencies": {
2930
"@nuxt/devtools": "latest",

app/src/components/appbar/Menu.vue

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,17 @@ const apps: {
7979
},
8080
to: `/tickets?filters[@lifestep][]=1&${baseFilter}`
8181
},
82+
{
83+
title: {
84+
name: 'Mails',
85+
color: 'secondary'
86+
},
87+
icon: {
88+
name: 'mdi-mail',
89+
color: 'primary'
90+
},
91+
to: `/mails`
92+
},
8293
// {
8394
// title: {
8495
// name: 'Profil',

app/src/pages/mails/index.vue

Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
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+
q-table.my-sticky-last-column-table(
7+
v-model:selected="selected"
8+
v-model:pagination="pagination"
9+
title="Mails"
10+
:rows="tickets.data"
11+
row-key="uid"
12+
@request="onRequest"
13+
:rows-per-page-options="[5, 10, 15]"
14+
:columns="columns"
15+
:loading="pending"
16+
rows-per-page-label="Lignes par page"
17+
no-data-label="Aucune donnée"
18+
loading-label="Chargement..."
19+
no-results-label="Aucun résultat"
20+
selection="multiple"
21+
:pagination-label="(firstRowIndex, endRowIndex, totalRowsNumber) => `${firstRowIndex}-${endRowIndex} sur ${totalRowsNumber} lignes`"
22+
:selected-rows-label="(numberOfRows) => `${numberOfRows} tickets 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="" 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+
q-card
35+
q-card-actions
36+
q-toolbar-title(v-text='target?.subject' style='flex: 100 1 0%')
37+
q-space
38+
q-btn(color="negative" icon='mdi-delete' @click="")
39+
q-btn(color="info" icon='mdi-email-arrow-right-outline' @click="")
40+
q-btn(color="primary" icon='mdi-content-save' @click="")
41+
q-card-section.q-pa-xs
42+
q-tabs(v-model="tab" dense)
43+
q-tab(name="mails" icon="mdi-mail" label="Mails")
44+
q-tab(name="raw" icon="mdi-square" label="raw")
45+
q-tab-panels(v-model="tab")
46+
q-tab-panel.no-padding(name="mails")
47+
object(:data='"http://localhost:7100/tickets/mails/" + target?.uid + "/source"' style='width: 100%; height: 75vh;')
48+
q-tab-panel.no-padding(name="raw")
49+
q-table(
50+
:rows="target.headers"
51+
:pagination='{rowsPerPage: 12}'
52+
:pagination-label="(firstRowIndex, endRowIndex, totalRowsNumber) => `${firstRowIndex}-${endRowIndex} sur ${totalRowsNumber} lignes`"
53+
rows-per-page-label="Lignes par page"
54+
no-data-label="Aucune donnée"
55+
loading-label="Chargement..."
56+
no-results-label="Aucun résultat"
57+
flat
58+
)
59+
</template>
60+
61+
<script lang="ts">
62+
import { computed, useDayjs } from '#imports'
63+
import { useRoute, useRouter } from 'nuxt/app'
64+
import { ref } from 'vue'
65+
import type { QTableProps } from 'quasar'
66+
import type { components } from '#build/types/service-api'
67+
68+
type Ticket = components["schemas"]['TicketDto']
69+
70+
export default defineNuxtComponent({
71+
data: () => ({
72+
tab: ref(''),
73+
selected: ref<Ticket[]>([]),
74+
target: ref<Ticket | null>(null),
75+
pagination: ref<QTableProps['pagination']>({
76+
page: 1,
77+
rowsPerPage: 10,
78+
rowsNumber: 10,
79+
}),
80+
}),
81+
async setup() {
82+
const route = useRoute()
83+
const { data: tickets, pending, refresh, error } = await useHttpApi('/tickets/mails', {
84+
method: 'get',
85+
query: computed(() => {
86+
return {
87+
...route.query,
88+
}
89+
})
90+
})
91+
const daysjs = useDayjs()
92+
const columns = ref<QTableProps['columns']>([
93+
{
94+
name: 'uid',
95+
label: 'ID',
96+
field: 'uid',
97+
align: 'left',
98+
},
99+
{
100+
name: 'envelope.subject',
101+
label: 'Sujet',
102+
field: (row: Ticket) => {
103+
const $q = useQuasar()
104+
const maxLength = ($q.screen.width / 2 / 10) - 30
105+
if (row.envelope.subject.length <= maxLength) {
106+
return row.envelope.subject
107+
}
108+
let truncated = row.envelope.subject.substring(0, maxLength)
109+
const re = new RegExp(/\s+\S*$/)
110+
const match = re.exec(truncated)
111+
truncated = truncated.substring(0, match?.index!)
112+
return `${truncated} ...`
113+
},
114+
align: 'left',
115+
},
116+
{
117+
name: 'envelope.date',
118+
label: 'Date de réception',
119+
field: (row: Ticket) => row.envelope.date,
120+
format: (val: string) => daysjs(val).format('DD/MM/YYYY HH:mm'),
121+
align: 'left',
122+
},
123+
{
124+
name: 'actions',
125+
label: 'Actions',
126+
field: 'actions',
127+
align: 'left',
128+
},
129+
])
130+
return {
131+
columns,
132+
tickets,
133+
pending,
134+
refresh,
135+
error,
136+
}
137+
},
138+
methods: {
139+
async goToMail(ticket: Ticket) {
140+
const route = useRoute()
141+
const router = useRouter()
142+
router.replace({
143+
query: {
144+
...route.query,
145+
uid: ticket.uid,
146+
}
147+
})
148+
const { data: mail, pending, refresh, error } = await useHttpApi(`/tickets/mails/${ticket.uid}`, {
149+
method: 'get',
150+
query: computed(() => {
151+
return {
152+
...route.query,
153+
}
154+
})
155+
})
156+
this.target = mail.value?.data
157+
this.tab = 'mails'
158+
},
159+
async onRequest(props: QTableProps) {
160+
const { page, rowsPerPage, sortBy, descending } = props.pagination
161+
this.pagination!.rowsNumber = this.tickets?.total
162+
this.pagination!.page = page
163+
this.pagination!.rowsPerPage = rowsPerPage
164+
this.pagination!.sortBy = sortBy
165+
this.pagination!.descending = descending
166+
this.paginationQuery()
167+
},
168+
paginationQuery() {
169+
const router = useRouter()
170+
const query = this.removeSortKey()
171+
const skip = `${(this.pagination?.page! - 1) * this.pagination?.rowsPerPage!}`
172+
const limit = `${this.pagination?.rowsPerPage!}`
173+
query['skip'] = skip
174+
query['limit'] = limit
175+
router.replace({
176+
query
177+
})
178+
},
179+
removeSortKey() {
180+
const route = useRoute()
181+
const query = { ...route.query }
182+
for (const key in query) {
183+
if (key.startsWith('sort[')) {
184+
delete query[key]
185+
}
186+
}
187+
return query
188+
},
189+
},
190+
async mounted() {
191+
const route = useRoute()
192+
this.pagination!.rowsNumber = this.tickets?.total
193+
const query = { ...route.query }
194+
const limit = query.limit ?? 10
195+
const skip = query.skip ?? 0
196+
this.pagination!.rowsPerPage = parseInt(limit as string)
197+
this.pagination!.page = parseInt(skip as string) / parseInt(limit as string) + 1
198+
199+
let sortKey = 'metadata.lastUpdatedAt'
200+
let sortDirection = 'desc'
201+
for (const key in query) {
202+
if (key.startsWith('sort')) {
203+
sortKey = key.replace('sort[', '').replace(']', '')
204+
sortDirection = query[key] === 'desc' ? 'desc' : 'asc'
205+
}
206+
}
207+
this.pagination!.sortBy = sortKey
208+
this.pagination!.descending = sortDirection === 'desc'
209+
this.paginationQuery()
210+
},
211+
})
212+
</script>
213+
<style lang="sass">
214+
@import "quasar/src/css/variables.sass"
215+
.my-sticky-last-column-table
216+
thead tr:last-child th:last-child
217+
background-color: $menu-background
218+
td:last-child
219+
background-color: $menu-background
220+
th:last-child,
221+
td:last-child
222+
position: sticky
223+
right: -1px
224+
z-index: 1
225+
</style>

0 commit comments

Comments
 (0)