Skip to content

Commit 5f79686

Browse files
RICHARD-QuentinGithub Actiontacxou
authored
App developement (#40)
* fix populate builds and script * fix emit * remove from field * fix queries * Update release.yml (#26) * Update release.yml * Update release.yml (#27) * Update release.yml (#28) * v0.0.2 * Update release.yml * Update Dockerfile * v0.0.3 * Update release.yml (#29) * Update Dockerfile * Update Dockerfile * Update Dockerfile (#30) * v0.0.4 * Update jwt.strategy.ts * Fix build (#31) * change dockerfile * change release * v0.0.5 * Fix build (#32) * change dockerfile * change release * fix skip build * v0.0.6 * Fix build (#33) * change dockerfile * change release * fix skip build * fix env values * v0.0.7 * Fix build (#34) * change dockerfile * change release * fix skip build * fix env values * fix envs * v0.0.8 * Fix build (#35) * change dockerfile * change release * fix skip build * fix env values * fix envs * change envs * v0.0.9 * Fix build (#36) * change dockerfile * change release * fix skip build * fix env values * fix envs * change envs * checkout code in build part * v0.0.10 * Fix build (#37) * change dockerfile * change release * fix skip build * fix env values * fix envs * change envs * checkout code in build part * fix dockerfiles * v0.0.11 * WIP Mails + fix dto * Reecriture option api (#39) * change lifesteps * daysjs clear * change inject types searchfilters * fix types in right select * Reorganise code in threads * fix mail button size + type iframe ref * type refs * correct api call * fix type + refactor api calls * types fixs * refactoring ticket page * WIP Mails + fix dto --------- Co-authored-by: Tacx <12997062+tacxou@users.noreply.github.com> * fix queries * fix api required fields * add lint config --------- Co-authored-by: Github Action <github@action.com> Co-authored-by: Tacx <12997062+tacxou@users.noreply.github.com>
1 parent 0b807be commit 5f79686

File tree

14 files changed

+138
-76
lines changed

14 files changed

+138
-76
lines changed

.eslintrc.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
module.exports = {
2-
parser: '@typescript-eslint/parser',
2+
parser: 'vue-eslint-parser',
33
parserOptions: {
44
project: 'tsconfig.json',
55
tsconfigRootDir: __dirname,
66
sourceType: 'module',
7+
extraFileExtensions: ['.vue'],
8+
parser: '@typescript-eslint/parser',
79
},
810
plugins: ['@typescript-eslint/eslint-plugin'],
911
extends: [
@@ -25,5 +27,6 @@ module.exports = {
2527
'@typescript-eslint/no-inferrable-types': 'off',
2628
'@typescript-eslint/no-explicit-any': 'error',
2729
'@typescript-eslint/no-var-requires': 'off',
30+
"@typescript-eslint/no-unused-vars": "off"
2831
},
2932
}

app/package.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
"generate": "nuxt generate",
1010
"preview": "nuxt preview",
1111
"generate:api": "openapi-typescript http://localhost:7100/swagger/json -o ./.nuxt/types/service-api.d.ts",
12-
"upgrade:packages": "npx npm-check-updates -u --reject @types/node"
12+
"upgrade:packages": "npx npm-check-updates -u --reject @types/node",
13+
"lint": "eslint --ext .ts,.js,.vue --ignore-path .gitignore .",
14+
"lint:fix": "eslint --ext .ts,.js,.vue --ignore-path .gitignore . --fix"
1315
},
1416
"dependencies": {
1517
"@nuxt-alt/auth": "^2.6.1",
@@ -24,7 +26,8 @@
2426
"cookie": "^0.5.0",
2527
"pinia": "^2.1.6",
2628
"quasar": "^2.12.6",
27-
"sass": "^1.68.0"
29+
"sass": "^1.68.0",
30+
"vue-eslint-parser": "^9.3.2"
2831
},
2932
"devDependencies": {
3033
"@nuxt/devtools": "latest",

app/src/components/searchfilters/RightSelect.vue

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ q-select(
1010
)
1111
template(v-slot:option="{ index, itemProps, opt, selected, toggleOption }")
1212
q-item-label(v-bind="itemProps" v-if="opt.header" header) {{ opt.label }}
13-
q-item(v-bind="itemProps" v-else @click.capture='addFilter({index, value: opt})')
13+
q-item(v-bind="itemProps" v-else @click.capture='addFilter(opt)')
1414
q-item-section(side)
1515
q-icon(:name="opt.icon" :color="opt.color" size="xs")
1616
q-item-section
@@ -52,12 +52,13 @@ onMounted(() => {
5252
})
5353
5454
watch(() => route.query, () => {
55-
filters.value = []
5655
getFilters()
5756
})
5857
5958
const filters = ref<Option[]>([])
6059
const getFilters = () => {
60+
filters.value = []
61+
6162
// Use destructuring assignment to clone the route.query object
6263
const query = { ...route.query };
6364
@@ -67,24 +68,29 @@ const getFilters = () => {
6768
.filter(([key, value]) => key.startsWith('filters[@') && value !== null)
6869
.map(([key, value]) => {
6970
group = key.replace('filters[@', '').replace(']', '').replace('[]', '')
70-
return Array.isArray(value) ? value : [value]
71+
if (Array.isArray(value)) {
72+
return value.map((val: string) => {
73+
return {
74+
value: val,
75+
group
76+
}
77+
})
78+
} else {
79+
return {
80+
value,
81+
group
82+
}
83+
}
84+
7185
})
7286
.flat()
73-
.map(value => options.value.find(option => option.value?.toString() === value?.toString() && option.group === group))
74-
.filter(option => option !== undefined) as Option[]
87+
.map(filter => options.value.find(option => option.value?.toString() === filter.value?.toString() && option.group === filter.group))
88+
.filter(option => option !== undefined);
7589
filters.value = filteredOptions;
7690
}
7791
7892
7993
const options = computed(() => {
80-
// const categories: Option[] = categoriesData.value.data.map((category: Category) => {
81-
// return {
82-
// label: category.name,
83-
// value: category._id,
84-
// group: 'categories'
85-
// }
86-
// }) ?? []
87-
// categories.unshift({ label: 'Catégories', header: true })
8894
const ticketTypeOptions: Option[] = ticketType.map((type) => {
8995
return {
9096
label: type.label,
@@ -104,6 +110,14 @@ const options = computed(() => {
104110
color: state.color ?? ''
105111
}
106112
}) ?? []
113+
const categories: Option[] = categoriesData.value.data.map((category: Category) => {
114+
return {
115+
label: category.name,
116+
value: category._id,
117+
group: 'categories'
118+
}
119+
}) ?? []
120+
if (!categories.find(category => category.header)) categories.unshift({ label: 'Catégories', header: true })
107121
if (!states.find(state => state.header)) states.unshift({ label: 'États', header: true })
108122
if (!lifeSteps.find(lifestep => lifestep.header)) lifeSteps.unshift({ label: 'Étapes de vie', header: true })
109123
return [
@@ -114,6 +128,7 @@ const options = computed(() => {
114128
]
115129
})
116130
131+
// Regroup the filters by key
117132
const regroupFilters = async () => {
118133
return filters.value.reduce((acc: any, filter: Option) => {
119134
const key = `filters[@${filter.group}]`
@@ -126,22 +141,32 @@ const regroupFilters = async () => {
126141
}
127142
128143
const pushQueries = async () => {
144+
// Regroup the filters by key
129145
const regroupedFilters = await regroupFilters();
146+
147+
// Push the filters to the url
130148
for (const key in regroupedFilters) {
131149
const values = regroupedFilters[key];
132150
for (const value of values) {
133-
pushQuery({ value, key, multiple: true })
151+
pushQuery({ value, key, multiple: true, pagination: { limit: 10, skip: 0 } })
134152
}
135153
}
136154
};
137155
138-
const addFilter = (option: { index: number, value: Option }) => {
139-
const index = filters.value.findIndex(filter => filter.value?.toString() === option.value.toString() && filter.group === option.value.group)
156+
const addFilter = (option: Option) => {
157+
// Find the index of the option in the filters array
158+
const index = filters.value.findIndex(filter => {
159+
return filter.group === option.group && filter.value === option.value
160+
161+
})
162+
console.log('index', index)
163+
// If the option is not in the filters array, add it else remove it
140164
if (index === -1) {
141-
filters.value.push(option.value)
165+
filters.value.push(option)
142166
} else {
143167
filters.value.splice(index, 1)
144168
}
169+
// Push the new filters to the url
145170
pushQueries()
146171
}
147172

app/src/components/searchfilters/index.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ const removeFilter = (filter: Filter) => {
4646
...route.query,
4747
}
4848
delete query[key]
49-
router.push({
49+
router.replace({
5050
query
5151
})
5252
}

app/src/components/threads/Editor.vue

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
q-dialog(v-model="isFullscreen")
3737
q-card
3838
q-card-section.bg-grey-2
39-
q-input(dense label="From" v-model="mailInfo.from" :disable="isDisabledTicket")
39+
//- q-input(dense label="From" v-model="mailInfo.from" :disable="isDisabledTicket")
4040
q-input(dense label="To" v-model="mailInfo.to" :disable="isDisabledTicket")
4141
q-input(dense label="Copy" v-model="mailInfo.cc" :disable="isDisabledTicket")
4242
q-input(dense label="Subject" v-model="mailInfo.subject" :disable="isDisabledTicket")
@@ -186,25 +186,26 @@ const emailReponse = (data: MailinfoPartDto) => {
186186
const threadType = ref(threadTypes[0])
187187
const message = ref('')
188188
async function sendMessage(type: ThreadType = ThreadType.OUTGOING) {
189+
const body: components["schemas"]["ThreadCreateDto"] & { _id: string } = {
190+
_id: currentThreadId.value?.toHexString() || '',
191+
attachments: attachements.value,
192+
ticketId: generateStringMongoId(route.params.id.toString()),
193+
fragments: [{
194+
id: generateStringMongoId(),
195+
disposition: 'raw',
196+
message: message.value
197+
}] as components["schemas"]["FragmentPartDto"][],
198+
metadata: {
199+
createdBy: user.username,
200+
createdAt: dayjs().toISOString(),
201+
lastUpdatedAt: dayjs().toISOString(),
202+
lastUpdatedBy: user.username
203+
},
204+
type
205+
}
189206
const { data: thread, error } = await useHttpApi(`/tickets/thread`, {
190207
method: 'post',
191-
body: {
192-
_id: currentThreadId.value?.toHexString(),
193-
attachments: attachements.value,
194-
ticketId: generateStringMongoId(route.params.id.toString()),
195-
fragments: [{
196-
id: generateStringMongoId(),
197-
disposition: 'raw',
198-
message: message.value
199-
}],
200-
metadata: {
201-
createdBy: user.username,
202-
createdAt: dayjs().toISOString(),
203-
lastUpdatedAt: dayjs().toISOString(),
204-
lastUpdatedBy: user.username
205-
},
206-
type
207-
}
208+
body
208209
})
209210
210211
console.log('thread', thread.value)

app/src/components/threads/List.vue

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,16 @@ q-scroll-area(ref="chatScroll")
1010

1111
div(v-for="(message, index) in value" :id="message._id" :key='index').q-mx-md
1212
component(
13+
v-if="getThreadHookName(message.type) === 'tk-threadsTypesMail'"
1314
:is="getThreadHookName(message.type)"
1415
:data="message"
1516
@email:response="emailReponse($event)"
1617
)
18+
component(
19+
v-else
20+
:is="getThreadHookName(message.type)"
21+
:data="message"
22+
)
1723
</template>
1824

1925
<script lang="ts" setup>

app/src/components/threads/types/mail.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ div
1818
q-separator.q-my-xs(v-if="props.data.attachments.length > 0")
1919
q-chip(v-for='(attachment, key) in props.data.attachments' :key='key' icon="mdi-paperclip" text-color="white" color="primary" dense size='md' :label="attachment.name")
2020
.col.flex.justify-center.items-center.q-pa-sm.column.q-gutter-sm
21-
q-btn(fab size="sm" icon="mdi-share" color="primary" @click="emailReponse(props.data.mailinfo)")
22-
q-btn(fab size="sm" icon="mdi-dots-vertical" color="primary")
21+
q-btn(fab size="xs" icon="mdi-share" color="primary" @click="emailReponse(props.data.mailinfo)")
22+
q-btn(fab size="xs" icon="mdi-dots-vertical" color="primary")
2323
</template>
2424

2525
<script lang="ts" setup>

app/src/components/tickets/table/top-right.vue

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ q-btn-group(rounded flat)
1313

1414
<script lang="ts" setup>
1515
import type { PropType } from 'vue'
16-
import { defineProps } from 'vue'
17-
1816
const props = defineProps({
1917
columns: {
2018
type: Array as PropType<{ name: string, label: string, value: string }[]>,

app/src/composables/pushQuery.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
import { useRouter, useRoute } from 'nuxt/app'
2-
export async function pushQuery(payload: { value: any; key: string; multiple?: boolean }) {
2+
export async function pushQuery(payload: { value: any; key: string; multiple?: boolean; pagination?: { skip: number; limit: number } }) {
33
const route = useRoute()
44
const router = useRouter()
5-
const { value, key, multiple } = payload
5+
const { value, key, multiple, pagination } = payload
66
const query = { ...route.query }
7+
if (pagination) {
8+
query.skip = pagination.skip.toString()
9+
query.limit = pagination.limit.toString()
10+
}
11+
712
if (!multiple) {
813
query[key] = value
914
} else {

app/src/pages/tickets.vue

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -21,31 +21,31 @@ q-page
2121
template(v-slot:body-cell-states="props")
2222
tk-tickets-table-state-col(:ticket="props.row")
2323

24-
template(v-slot:body-cell-envelope.senders.name="props")
25-
q-td(:props="props")
26-
span.q-ml-sm {{ props.row.envelope.senders.length === 0 ? "Pas d'appelant" : props.row.envelope.senders[0].name }}
27-
span(v-if="props.row.envelope.senders.length > 1") , {{ props.row.envelope.senders.length -1 }} autre{{ props.row.envelope.senders.length === 2 ? '' : 's' }}...
28-
q-tooltip.text-body2(transition-show="scale" transition-hide="scale") ...{{ [...props.row.envelope.senders].slice(1).map(s => s.name).join(', ') }}
24+
template(v-slot:body-cell-envelope.senders.name="props")
25+
q-td(:props="props")
26+
span.q-ml-sm {{ props.row.envelope.senders.length === 0 ? "Pas d'appelant" : props.row.envelope.senders[0].name }}
27+
span(v-if="props.row.envelope.senders.length > 1") , {{ props.row.envelope.senders.length -1 }} autre{{ props.row.envelope.senders.length === 2 ? '' : 's' }}...
28+
q-tooltip.text-body2(transition-show="scale" transition-hide="scale") ...{{ [...props.row.envelope.senders].slice(1).map(s => s.name).join(', ') }}
2929

30-
template(v-slot:body-cell-envelope.observers.name="props")
31-
q-td(:props="props")
32-
span.q-ml-sm {{ props.row.envelope.observers.length === 0 ? "Pas de concerné" : props.row.envelope.observers[0].name }}
33-
span(v-if="props.row.envelope.observers.length > 1") , {{ props.row.envelope.observers.length -1 }} autre{{ props.row.envelope.observers.length === 2 ? '' : 's' }}...
34-
q-tooltip.text-body2(transition-show="scale" transition-hide="scale") ...{{ [...props.row.envelope.observers].slice(1).map(s => s.name).join(', ') }}
30+
template(v-slot:body-cell-envelope.observers.name="props")
31+
q-td(:props="props")
32+
span.q-ml-sm {{ props.row.envelope.observers.length === 0 ? "Pas de concerné" : props.row.envelope.observers[0].name }}
33+
span(v-if="props.row.envelope.observers.length > 1") , {{ props.row.envelope.observers.length -1 }} autre{{ props.row.envelope.observers.length === 2 ? '' : 's' }}...
34+
q-tooltip.text-body2(transition-show="scale" transition-hide="scale") ...{{ [...props.row.envelope.observers].slice(1).map(s => s.name).join(', ') }}
3535

36-
template(v-slot:body-cell-envelope.assigned.name="props")
37-
q-td(:props="props")
38-
span.q-ml-sm {{ props.row.envelope.assigned.length === 0 ? "Pas d'assigné" : props.row.envelope.assigned[0].name }}
39-
span(v-if="props.row.envelope.assigned.length > 1") , {{ props.row.envelope.assigned.length -1 }} autre{{ props.row.envelope.assigned.length === 2 ? '' : 's' }}...
40-
q-tooltip.text-body2(transition-show="scale" transition-hide="scale") ...{{ [...props.row.envelope.assigned].slice(1).map(s => s.name).join(', ') }}
36+
template(v-slot:body-cell-envelope.assigned.name="props")
37+
q-td(:props="props")
38+
span.q-ml-sm {{ props.row.envelope.assigned.length === 0 ? "Pas d'assigné" : props.row.envelope.assigned[0].name }}
39+
span(v-if="props.row.envelope.assigned.length > 1") , {{ props.row.envelope.assigned.length -1 }} autre{{ props.row.envelope.assigned.length === 2 ? '' : 's' }}...
40+
q-tooltip.text-body2(transition-show="scale" transition-hide="scale") ...{{ [...props.row.envelope.assigned].slice(1).map(s => s.name).join(', ') }}
4141

4242
tk-tickets-closeDialog(v-model="closeTicketsDialog" :selected="selected" @refresh="refresh")
4343
</template>
4444

4545
<script lang="ts" setup>
46-
import { ref, provide } from "vue";
46+
import { ref, provide, watch, computed } from "vue";
4747
import { useHttpApi } from "~/composables/useHttpApi";
48-
import { computed, useDayjs, onMounted } from "#imports";
48+
import { useDayjs, onMounted } from "#imports";
4949
import { useRoute, useRouter } from "nuxt/app";
5050
import { useQuasar } from "quasar";
5151
import type { QTableProps } from "quasar";
@@ -77,7 +77,10 @@ if (error.value) {
7777
}
7878
7979
const { data: categories, pending: categoriesPending, refresh: categoriesRefresh, error: categoriesError } = await useHttpApi('/core/categories', {
80-
method: 'get'
80+
method: 'get',
81+
query: {
82+
"limit": 999,
83+
}
8184
})
8285
8386
if (categoriesError.value) {
@@ -87,7 +90,10 @@ if (categoriesError.value) {
8790
})
8891
}
8992
const { data: states, pending: statesPending, refresh: statesRefresh, error: statesError } = await useHttpApi('/tickets/state', {
90-
method: 'get'
93+
method: 'get',
94+
query: {
95+
"limit": 999,
96+
}
9197
})
9298
9399
if (statesError.value) {

0 commit comments

Comments
 (0)