Skip to content

Commit 1a2ccda

Browse files
committed
feat: implement new filter components and refactor existing filter logic
1 parent f1f7c4a commit 1a2ccda

File tree

7 files changed

+220
-185
lines changed

7 files changed

+220
-185
lines changed

apps/web/src/components/pages/identities/filters.vue renamed to apps/web/src/components/core/edit-filters.vue

Lines changed: 65 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<template lang="pug">
2-
q-card(style='min-width: 500px;')
2+
q-card(style='min-width: 40vw;')
33
q-toolbar.bg-primary.text-white(dense flat style='height: 32px;')
44
q-toolbar-title(v-text='title')
55
q-btn(
@@ -12,6 +12,7 @@ q-card(style='min-width: 500px;')
1212
q-card-section.q-pb-sm
1313
.flex.q-col-gutter-md
1414
q-select.col(
15+
style='min-width: 180px; max-width: 220px'
1516
v-model='filter.key'
1617
:readonly='!!initialFilter?.field'
1718
:options='columns'
@@ -24,10 +25,11 @@ q-card(style='min-width: 500px;')
2425
map-options
2526
emit-value
2627
)
27-
q-select.col(
28+
q-select.col-1(
29+
style='min-width: 130px'
2830
v-model='filter.operator'
2931
label='Opérateur'
30-
:options='comparatorTypes'
32+
:options='availableComparators'
3133
option-value='value'
3234
option-label='label'
3335
dense
@@ -46,15 +48,37 @@ q-card(style='min-width: 500px;')
4648
q-item-label
4749
span {{ scope.opt.label }}
4850
q-input.col(
51+
style='min-width: 300px'
4952
v-show="!comparator?.multiplefields"
5053
v-model='filter.value'
5154
label='Valeur'
5255
:prefix="comparator?.prefix"
5356
:suffix="comparator?.suffix"
57+
:type='searchInputType'
5458
@keydown.enter.prevent="writeFilter(filter)"
5559
dense
5660
outlined
5761
)
62+
q-input.col(
63+
style='min-width: 200px'
64+
v-show="comparator?.multiplefields"
65+
v-model="filter.min"
66+
:type='searchInputType'
67+
label="Minimum"
68+
clearable
69+
dense
70+
outlined
71+
)
72+
q-input.col(
73+
style='min-width: 200px'
74+
v-show="comparator?.multiplefields"
75+
v-model="filter.max"
76+
:type='searchInputType'
77+
label="Maximum"
78+
clearable
79+
dense
80+
outlined
81+
)
5882
q-card-actions
5983
q-space
6084
q-btn(
@@ -75,6 +99,9 @@ type Filter = {
7599
key: string
76100
operator: string
77101
value: string
102+
103+
min: string
104+
max: string
78105
}
79106
80107
type InitialFilter = {
@@ -87,7 +114,7 @@ type InitialFilter = {
87114
}
88115
89116
export default defineNuxtComponent({
90-
name: 'PagesIdentitiesFiltersComponent',
117+
name: 'CoreEditFiltersComponent',
91118
props: {
92119
title: {
93120
type: String,
@@ -97,20 +124,33 @@ export default defineNuxtComponent({
97124
type: Array as () => QTableProps['columns'] & { type: string }[],
98125
default: () => [],
99126
},
127+
columnsType: {
128+
type: Array as PropType<{ name: string; type: string }[]>,
129+
required: false,
130+
default: () => [],
131+
},
100132
initialFilter: {
101133
type: Object as () => InitialFilter,
102134
default: () => ({}),
103135
},
104136
},
105137
watch: {
138+
'filter.key': {
139+
handler() {
140+
this.fieldType = this.columnsType.find((col) => col.name === this.filter.key)?.type || 'text'
141+
this.filter.operator = ''
142+
},
143+
},
106144
'filter.operator': {
107145
handler() {
108146
this.filter.value = ''
147+
this.filter.min = ''
148+
this.filter.max = ''
109149
},
110150
},
111151
},
112152
setup({ columns, initialFilter }) {
113-
const { comparatorTypes, writeFilter } = useFiltersQuery(ref(columns))
153+
const { fieldTypes, comparatorTypes, writeFilter } = useFiltersQuery(ref(columns))
114154
115155
const detectInitialOperator = () => {
116156
if (!initialFilter || !initialFilter.querySign) return ''
@@ -166,22 +206,41 @@ export default defineNuxtComponent({
166206
return val
167207
}
168208
209+
const fieldType = ref<string>()
169210
const filter = ref<Filter>({
170211
key: initialFilter?.field || '',
171212
operator: detectInitialOperator(),
172213
value: stripPrefixSuffix(initialFilter?.value) || '',
214+
215+
min: '',
216+
max: '',
173217
})
174218
175219
return {
176220
filter,
221+
fieldType,
222+
fieldTypes,
177223
comparatorTypes,
178224
writeFilter,
179225
}
180226
},
181227
computed: {
182-
comparator() {
228+
comparator(): { label: string; value: string; prefix?: string; suffix?: string; multiplefields?: boolean } | undefined {
183229
return this.comparatorTypes.find((comp) => comp.value === this.filter.operator)
184230
},
231+
searchInputType(): string {
232+
if (this.fieldType === undefined || this.fieldType === null) return 'text'
233+
return this.fieldType
234+
},
235+
availableComparators(): { label: string; value: string; prefix?: string; suffix?: string; multiplefields?: boolean }[] {
236+
if (this.fieldType === undefined || this.fieldType === null) return []
237+
return this.comparatorTypes.filter((comparator) => {
238+
return comparator.type.includes(this.fieldType!)
239+
})
240+
},
241+
},
242+
mounted() {
243+
this.fieldType = this.columnsType.find((col) => col.name === this.filter.key)?.type || 'text'
185244
},
186245
})
187246
</script>
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
<template lang="pug">
2+
q-toolbar(dense flat)
3+
.column.fit
4+
.flex.q-mt-sm
5+
//- pre(v-html='JSON.stringify(columnsType)')
6+
q-input.col(
7+
v-if='mode === "simple" || mode === "complex"'
8+
v-model='search'
9+
label='Recherche'
10+
:placeholder='placeholder'
11+
clear-icon='mdi-close'
12+
:debounce='300'
13+
dense
14+
outlined
15+
clearable
16+
autofocus
17+
stacked-label
18+
)
19+
q-space(v-if='mode === "advanced"')
20+
q-btn.q-ml-sm(
21+
v-if='mode === "complex" || mode === "advanced"'
22+
color='primary'
23+
icon='mdi-filter-variant'
24+
flat
25+
dense
26+
)
27+
span(v-text='mode === "advanced" ? "Ajouter un nouveau filtre" : ""')
28+
q-badge.text-black(
29+
v-if='countFilters > 0'
30+
color='warning'
31+
floating
32+
) {{ countFilters }}
33+
q-popup-proxy(
34+
anchor='bottom left'
35+
self='top middle'
36+
transition-show='scale'
37+
transition-hide='scale'
38+
)
39+
sesame-core-edit-filters(
40+
title='Ajouter un filtre'
41+
:columns='columns'
42+
:columns-type='columnsType'
43+
)
44+
.flex.q-mt-sm(v-show='hasFilters')
45+
template(v-for='(filter, i) in getFilters' :key='filter.field')
46+
//- pre(v-html='JSON.stringify(filter)')
47+
q-chip(
48+
@remove="removeFilter(filter)"
49+
:color="$q.dark.isActive ? 'grey-9' : 'grey-3'"
50+
removable
51+
clickable
52+
dense
53+
)
54+
| {{ filter.label }}
55+
q-separator.q-mx-xs(vertical)
56+
| {{ filter.comparator }}
57+
q-separator.q-mx-xs(vertical)
58+
| "{{ filter.search }}"
59+
q-popup-proxy(
60+
anchor='bottom left'
61+
self='top middle'
62+
transition-show='scale'
63+
transition-hide='scale'
64+
)
65+
sesame-core-edit-filters(
66+
:title='"Modifier le filtre (" + (filter.label || filter.field || "") + ")"'
67+
:initial-filter='filter'
68+
:columns='columns'
69+
:columns-type='columnsType'
70+
)
71+
span.content-center(v-if='i < countFilters - 1') &amp;gt;
72+
</template>
73+
74+
<script lang="ts">
75+
import type { QTableProps } from 'quasar'
76+
import type { LocationQueryValue } from 'vue-router'
77+
78+
export default defineComponent({
79+
name: 'CorePanFiltersComponent',
80+
props: {
81+
mode: {
82+
type: String as PropType<'simple' | 'complex' | 'advanced'>,
83+
required: false,
84+
default: 'simple',
85+
},
86+
placeholder: {
87+
type: String,
88+
required: false,
89+
default: 'Rechercher par ...',
90+
},
91+
columns: {
92+
type: Array as PropType<QTableProps['columns'] & { type: string }[]>,
93+
required: true,
94+
},
95+
columnsType: {
96+
type: Array as PropType<{ name: string; type: string }[]>,
97+
required: false,
98+
default: () => [],
99+
},
100+
},
101+
setup({ columns }) {
102+
const { countFilters, hasFilters, getFilters, removeFilter } = useFiltersQuery(ref(columns))
103+
104+
return {
105+
countFilters,
106+
hasFilters,
107+
getFilters,
108+
removeFilter,
109+
}
110+
},
111+
computed: {
112+
search: {
113+
get(): LocationQueryValue[] | string {
114+
const v = this.$route.query['search'] || ''
115+
116+
return `${v}`.replace(/^\*|\*$/g, '')
117+
},
118+
set(v: string): void {
119+
this.$router.replace({
120+
query: {
121+
...this.$route.query,
122+
search: v ? `${v}` : undefined,
123+
},
124+
})
125+
},
126+
},
127+
},
128+
})
129+
</script>

apps/web/src/composables/useColumnsIdentities.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ export function useColumnsIdentites(): useColumnsIdentitesReturnType {
5656
const dayjs = useDayjs()
5757
const config = useAppConfig()
5858

59-
const columns = ref<QTableProps['columns']>([
59+
const columns = ref<QTableProps['columns'] & { type: string }[]>([
6060
{
6161
name: 'states',
6262
label: 'États',

apps/web/src/composables/useFiltersQuery.ts

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
1-
import dayjs from "dayjs"
21
import type { QTableProps } from "quasar"
32
import type { LocationQueryValue } from "vue-router"
43

5-
// const fieldTypes = ref<
6-
// {
7-
// label: string
8-
// value: string
9-
// }[]
10-
// >([
11-
// { label: 'Texte', value: 'text' },
12-
// { label: 'Nombre', value: 'number' },
13-
// { label: 'Date', value: 'date' },
14-
// ])
4+
const fieldTypes = ref<
5+
{
6+
label: string
7+
value: string
8+
}[]
9+
>([
10+
{ label: 'Texte', value: 'text' },
11+
{ label: 'Nombre', value: 'number' },
12+
{ label: 'Date', value: 'date' },
13+
])
1514

1615
export const FILTER_BRACES = ['[', ']']
1716
export const FILTER_PREFIX = 'filters['
@@ -99,16 +98,16 @@ const comparatorTypes = ref<ComparatorType[]>([
9998
prefix: '',
10099
suffix: '',
101100
},
102-
{
103-
label: 'entre',
104-
querySign: '<<',
105-
value: 'between',
106-
icon: 'mdi-arrow-expand-horizontal',
107-
type: ['number', 'date'],
108-
multiplefields: true,
109-
prefix: '',
110-
suffix: '',
111-
},
101+
// {
102+
// label: 'entre',
103+
// querySign: '<<',
104+
// value: 'between',
105+
// icon: 'mdi-arrow-expand-horizontal',
106+
// type: ['number', 'date'],
107+
// multiplefields: true,
108+
// prefix: '',
109+
// suffix: '',
110+
// },
112111
{
113112
label: 'Contient',
114113
querySign: '^',
@@ -343,7 +342,7 @@ export function useFiltersQuery(columns: Ref<QTableProps['columns'] & { type: st
343342
})
344343
}
345344

346-
const writeFilter = (filter: { key: string; operator: string; value: string }) => {
345+
const writeFilter = (filter: { key: string; operator: string; value: string, min?: string, max?: string }) => {
347346
const router = useRouter()
348347
const query = { ...$route.query }
349348
const comparator = comparatorTypes.value.find((comp) => comp.value === filter.operator)
@@ -376,5 +375,6 @@ export function useFiltersQuery(columns: Ref<QTableProps['columns'] & { type: st
376375
removeFilter,
377376
writeFilter,
378377
comparatorTypes,
378+
fieldTypes,
379379
}
380380
}

0 commit comments

Comments
 (0)