Skip to content

Commit f2e0e71

Browse files
fixs filters
1 parent 159639c commit f2e0e71

File tree

7 files changed

+274
-122
lines changed

7 files changed

+274
-122
lines changed

app/src/components/searchfilters/RightSelect.vue

Lines changed: 49 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,16 @@
11
<template lang="pug">
22
q-select(
33
:options="options"
4-
multiple
5-
emit-value
6-
map-options
4+
multiple hide-selected
5+
emit-value use-chips
6+
options-dense map-options
77
:model-value="filters"
88
:option-value="(item) => item"
99
:label="`Etats: ${filters.length} filtre(s) appliqué(s)`"
10-
options-dense
11-
use-chips
12-
hide-selected
13-
@add="addFilter($event)"
14-
@remove="removeFilter($event)"
1510
)
1611
template(v-slot:option="{ index, itemProps, opt, selected, toggleOption }")
1712
q-item-label(v-bind="itemProps" v-if="opt.header" header) {{ opt.label }}
18-
//@click.capture='addFilter({index, value: opt})'
19-
q-item(v-bind="itemProps" v-else)
13+
q-item(v-bind="itemProps" v-else @click.capture='addFilter({index, value: opt})')
2014
q-item-section(side)
2115
q-icon(:name="opt.icon" :color="opt.color" size="xs")
2216
q-item-section
@@ -60,26 +54,44 @@ watch(() => route.query, () => {
6054
getFilters()
6155
})
6256
57+
// const getFilters = () => {
58+
// const query = { ...route.query }
59+
// for (const key in query) {
60+
// if (key.startsWith('filters[@') && query[key] !== null) {
61+
// const values = query[key]
62+
// if (Array.isArray(values)) {
63+
// for (const value of values) {
64+
// const option = options.value.find(option => option.value === value)
65+
// if (option) {
66+
// filters.value.push(option)
67+
// }
68+
// }
69+
// } else {
70+
// const option = options.value.find(option => option.value === values)
71+
// if (option) {
72+
// filters.value.push(option)
73+
// }
74+
// }
75+
// }
76+
// }
77+
// }
78+
6379
const getFilters = () => {
64-
const query = { ...route.query }
65-
for (const key in query) {
66-
if (key.startsWith('filters[@') && query[key] !== null) {
67-
const values = query[key]
68-
if (Array.isArray(values)) {
69-
for (const value of values) {
70-
const option = options.value.find(option => option.value === value)
71-
if (option) {
72-
filters.value.push(option)
73-
}
74-
}
75-
} else {
76-
const option = options.value.find(option => option.value === values)
77-
if (option) {
78-
filters.value.push(option)
79-
}
80-
}
81-
}
82-
}
80+
// Use destructuring assignment to clone the route.query object
81+
const query = { ...route.query };
82+
83+
// Use a functional approach with filter and map for better readability
84+
let group: string
85+
const filteredOptions = Object.entries(query)
86+
.filter(([key, value]) => key.startsWith('filters[@') && value !== null)
87+
.map(([key, value]) => {
88+
group = key.replace('filters[@', '').replace(']', '').replace('[]', '')
89+
return Array.isArray(value) ? value : [value]
90+
})
91+
.flat()
92+
.map(value => options.value.find(option => option.value?.toString() === value?.toString() && option.group === group))
93+
.filter(option => option !== undefined);
94+
filters.value = filteredOptions;
8395
}
8496
8597
@@ -112,8 +124,8 @@ const options = computed(() => {
112124
color: state.color ?? ''
113125
}
114126
}) ?? []
115-
states.unshift({ label: 'États', header: true })
116-
lifeSteps.unshift({ label: 'Étapes de vie', header: true })
127+
if (!states.find(state => state.header)) states.unshift({ label: 'États', header: true })
128+
if (!lifeSteps.find(lifestepstep => lifestepstep.header)) lifeSteps.unshift({ label: 'Étapes de vie', header: true })
117129
return [
118130
...lifeSteps,
119131
...ticketTypeOptions,
@@ -170,7 +182,6 @@ const regroupFilters = async () => {
170182
171183
const pushQueries = async () => {
172184
const regroupedFilters = await regroupFilters();
173-
174185
for (const key in regroupedFilters) {
175186
const values = regroupedFilters[key];
176187
for (const value of values) {
@@ -180,13 +191,12 @@ const pushQueries = async () => {
180191
};
181192
182193
const addFilter = (option: { index: number, value: Option }) => {
183-
filters.value.push(option.value)
184-
pushQueries()
185-
}
186-
187-
188-
const removeFilter = (option: { index: number, value: Option }) => {
189-
filters.value.splice(option.index, 1)
194+
const index = filters.value.findIndex(filter => filter.value?.toString() === option.value.toString() && filter.group === option.value.group)
195+
if (index === -1) {
196+
filters.value.push(option.value)
197+
} else {
198+
filters.value.splice(index, 1)
199+
}
190200
pushQueries()
191201
}
192202

app/src/components/searchfilters/index.vue

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
<template lang="pug" @keypress.enter="addFilter">
22
.q-ma-sm
3-
tk-SearchfiltersMain(ref="mainData")
4-
//Filters chips
5-
.row.q-gutter-sm.items-center.q-mt-sm
6-
q-chip(
7-
v-for="filter in filterArray" :key="filter.field"
8-
removable @remove="removeFilter(filter)"
9-
) {{ filter.label }} {{ filter.comparator }} {{ filter.search }}
3+
tk-SearchfiltersMain(ref="mainData")
4+
//Filters chips
5+
.row.q-gutter-sm.items-center.q-mt-sm
6+
q-chip(
7+
v-for="filter in filterArray" :key="filter.field"
8+
removable @remove="removeFilter(filter)"
9+
) {{ filter.label }} {{ filter.comparator }} {{ filter.search }}
1010
</template>
1111

1212
<script lang="ts" setup>
@@ -98,6 +98,7 @@ const getLabelByName = (name: string) => {
9898
return field.name.replace('[]', '')
9999
}
100100
101+
// Return the label for a comparator based on the comparator's query sign
101102
const getComparatorLabel = (comparator: string) => {
102103
const comparatorObj = mainData.value?.comparatorTypes.find(comparatorObj => comparatorObj.querySign === comparator)
103104
if (!comparatorObj) return comparator
@@ -124,6 +125,9 @@ const getSearchString = (search: LocationQueryValue | LocationQueryValue[], fiel
124125
return sanitizeSearchString(search!.toString())
125126
}
126127
128+
// This function sanitizes a search string by removing all prefixes and suffixes from the search string.
129+
130+
// The function takes a search string and returns a sanitized search string.
127131
const sanitizeSearchString = (search: string) => {
128132
const allPrefixAndSuffixPattern = getAllPrefixAndSuffixPattern.value
129133
for (const pattern of allPrefixAndSuffixPattern) {
@@ -132,7 +136,13 @@ const sanitizeSearchString = (search: string) => {
132136
return search
133137
}
134138
135-
const exctractComparator = (key: string): {
139+
/**
140+
* This function extracts the comparator and field from a key.
141+
* @param {string} key - The key to extract the comparator and field from.
142+
* @returns {object} The extracted comparator and field, or null if the key does not start with a comparator.
143+
*/
144+
145+
const extractComparator = (key: string): {
136146
comparator: string
137147
field: string
138148
} | null => {
@@ -146,21 +156,21 @@ const exctractComparator = (key: string): {
146156
}
147157
}
148158
159+
// This code extracts the filters from the route query and returns them as a computed object
160+
149161
const filterArray = computed(() => {
150162
const queries = { ...route.query }
151163
const filters: Record<string, { label: string, field: string, comparator: string, querySign: string, search: string }> = {};
152-
153-
// Iterate through the keys and values in the input object
154164
for (const key in queries) {
155165
if (queries.hasOwnProperty(key) && key.includes("filter")) {
156-
157-
// Extract the key without the "filter[" and "]" parts
158166
const filteredKey = key.replace("filters[", "").replace("]", "");
159-
const exctract = exctractComparator(filteredKey)
160-
if (!exctract) continue
161-
const { comparator, field } = exctract
167+
const extract = extractComparator(filteredKey)
168+
if (!extract) continue
169+
const { comparator, field } = extract
170+
const label = getLabelByName(field)
171+
const search = getSearchString(queries[key], field)
172+
if (!label || !search || search === '') continue
162173
163-
// Assign the value to the extracted key in the filter array
164174
filters[key] = {
165175
label: getLabelByName(field),
166176
field,

app/src/components/ticket/mainPanel.vue

Lines changed: 48 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,21 @@ q-card(style="height: 100%").column
2626
div(v-for='raw in message.fragments.raw' v-html="raw.message")
2727
tk-SearchfiltersThreads
2828
q-editor(
29-
v-model="message" placeholder="Votre message ..." v-model:fullscreen="isFullscreen"
29+
v-model="message" placeholder="Votre message ..."
3030
:definitions="editorDefinitions" ref="dropZoneRef"
31-
:toolbar="[['left','center','right','justify'],['bold','italic','underline','strike'],['undo','redo'],['attach','send'],['fullscreen']]"
31+
:toolbar="[['left','center','right','justify'],['bold','italic','underline','strike'],['undo','redo'],['send'],['fullscreen']]"
3232
).col
33+
q-dialog(v-model="isFullscreen")
34+
q-card
35+
q-card-section
36+
q-editor(
37+
min-height="50vh" min-width="50vw"
38+
v-model="message" placeholder="Votre message ..."
39+
:definitions="editorDefinitions" ref="dropZoneRef"
40+
:toolbar="[['left','center','right','justify'],['bold','italic','underline','strike'],['undo','redo'],['send'],['fullscreen']]" class="q-pa-none"
41+
:disable="disabled"
42+
)
43+
3344
//- .col-1(ref="dropZoneRef").bg-grey-3.items-center.justify-center.q-pa-md
3445
//- q-icon(name="mdi-paperclip" size="md" :class="isOverDropZone ? 'text-primary' : 'text-grey-5'")
3546
//- span.q-ml-md(:class="isOverDropZone ? 'text-primary' : 'text-grey-5'") Déposer un fichier
@@ -45,7 +56,7 @@ import { generateMongoId } from '~/utils';
4556
import type { Fragments, Threads } from '~/types';
4657
import type { components } from '#build/types/service-api'
4758
import { ThreadType, threadTypes } from '~/utils';
48-
import { useDropZone } from '@vueuse/core'
59+
import { useDropZone, useResizeObserver } from '@vueuse/core'
4960
5061
type ThreadDto = components['schemas']['ThreadDto']
5162
type FragmentPartDto = components["schemas"]["FragmentPartDto"]
@@ -63,6 +74,10 @@ const props = defineProps({
6374
subject: {
6475
type: String,
6576
required: true
77+
},
78+
disabled: {
79+
type: Boolean,
80+
default: false
6681
}
6782
})
6883
@@ -80,6 +95,7 @@ const baseQuery = ref({
8095
const isFullscreen = ref(false)
8196
const message = ref('')
8297
const dropZoneRef = ref<HTMLDivElement>()
98+
const editorDialog = ref()
8399
const { data: threads } = await useHttpApi(`tickets/thread`, {
84100
method: 'get',
85101
query: computed(() => {
@@ -97,6 +113,11 @@ const onDrop = (files: File[] | null) => {
97113
}
98114
const { isOverDropZone } = useDropZone(dropZoneRef, onDrop)
99115
116+
// useResizeObserver(editorDialog, (entries) => {
117+
// const entry = entries[0]
118+
// const { width, height } = entry.contentRect
119+
// })
120+
100121
const getTimeFrom = (time: string) => {
101122
return dayjs().to(dayjs(time))
102123
}
@@ -146,30 +167,31 @@ const sendMessage = async () => {
146167
scroll()
147168
}
148169
149-
const editorDefinitions = ref({
150-
send: {
151-
tip: 'Envoyer',
152-
icon: 'mdi-send',
153-
label: 'Envoyer',
154-
handler: sendMessage
155-
},
156-
attach: {
157-
tip: 'Joindre un fichier',
158-
icon: 'mdi-paperclip',
159-
label: 'Joindre un fichier',
160-
handler: () => {
161-
console.log('joindre')
162-
}
163-
},
164-
fullscreen: {
165-
tip: 'Plein écran',
166-
icon: 'mdi-fullscreen',
167-
label: 'Plein écran',
168-
handler: () => {
169-
isFullscreen.value = !isFullscreen.value
170+
const editorDefinitions = computed(() => (
171+
{
172+
send: {
173+
tip: 'Envoyer',
174+
icon: 'mdi-send',
175+
label: 'Envoyer',
176+
handler: sendMessage
177+
},
178+
attach: {
179+
tip: 'Joindre un fichier',
180+
icon: 'mdi-paperclip',
181+
label: 'Joindre un fichier',
182+
handler: () => {
183+
console.log('joindre')
184+
}
185+
},
186+
fullscreen: {
187+
tip: 'Plein écran',
188+
icon: isFullscreen.value ? 'mdi-fullscreen-exit' : 'mdi-fullscreen',
189+
label: isFullscreen.value ? 'Quitter le plein écran' : 'Plein écran',
190+
handler: () => {
191+
isFullscreen.value = !isFullscreen.value
192+
}
170193
}
171-
}
172-
})
194+
}))
173195
174196
const getMessageByDay = computed((): Threads => {
175197
return threads.value?.data.reduce((acc: Threads, thread: ThreadDto) => {

0 commit comments

Comments
 (0)