Skip to content

Commit 5c231d4

Browse files
PavelKopeckyMartinKolarik
authored andcommitted
feat: add probe type admin filter (#153)
1 parent f93c472 commit 5c231d4

File tree

3 files changed

+56
-20
lines changed

3 files changed

+56
-20
lines changed

app/components/probe/ProbeFilters/AdminFilterSettings.vue

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,43 @@
11
<template>
2-
<div class="flex flex-col gap-2">
3-
<span class="flex items-center font-bold">Adoption status:</span>
4-
<Select
5-
v-model="usedFilter.adoption"
6-
:options="ADOPTION_OPTIONS"
7-
class="min-w-48"
8-
@change="onChange"
9-
>
10-
<template #value="{value}">
11-
{{ value[0].toUpperCase() + value.slice(1) }}
12-
</template>
13-
<template #option="{option}">
14-
{{ option[0].toUpperCase() + option.slice(1) }}
15-
</template>
16-
</Select>
2+
<div class="flex flex-col gap-4">
3+
<div class="flex flex-col gap-2">
4+
<span class="flex items-center font-bold">Adoption status:</span>
5+
<Select
6+
v-model="usedFilter.adoption"
7+
:options="ADOPTION_OPTIONS"
8+
class="min-w-48"
9+
@change="onChange"
10+
>
11+
<template #value="{value}">
12+
{{upperFirst(value)}}
13+
</template>
14+
<template #option="{option}">
15+
{{upperFirst(option)}}
16+
</template>
17+
</Select>
18+
</div>
19+
<div class="flex flex-col gap-2">
20+
<span class="flex items-center font-bold">Probe type:</span>
21+
<Select
22+
v-model="usedFilter.probeType"
23+
:options="PROBE_TYPE_OPTIONS"
24+
class="min-w-48"
25+
@change="onChange"
26+
>
27+
<template #value="{value}">
28+
{{upperFirst(value)}}
29+
</template>
30+
<template #option="{option}">
31+
{{upperFirst(option)}}
32+
</template>
33+
</Select>
34+
</div>
1735
</div>
1836
</template>
1937

2038
<script setup lang="ts">
21-
import { useProbeFilters, ADOPTION_OPTIONS, type Filter } from '~/composables/useProbeFilters';
39+
import upperFirst from 'lodash/upperFirst';
40+
import { useProbeFilters, ADOPTION_OPTIONS, type Filter, PROBE_TYPE_OPTIONS } from '~/composables/useProbeFilters';
2241
2342
const filter = defineModel('filter', { required: false, type: Object as PropType<Filter> });
2443

app/components/probe/ProbeFilters/ProbeListFilters.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
text
5252
@click="adminOptsRef.toggle($event)">
5353
<i class="pi pi-sliders-h"/>
54-
<i v-if="!isDefault('adoption')" class="pi pi-circle-fill absolute right-2 top-2 text-[0.4rem] text-primary"/>
54+
<i v-if="anyAdminFilterApplied" class="pi pi-circle-fill absolute right-2 top-2 text-[0.4rem] text-primary"/>
5555
</Button>
5656

5757
<Popover ref="adminOptsRef" class="w-fit gap-4 p-4 [&>*]:border-none" role="dialog">
@@ -73,7 +73,7 @@
7373
const { $directus } = useNuxtApp();
7474
7575
const active = ref(true);
76-
const { filter, onParamChange, onFilterChange, getDirectusFilter, isDefault } = useProbeFilters({ active });
76+
const { filter, onParamChange, onFilterChange, getDirectusFilter, anyAdminFilterApplied } = useProbeFilters({ active });
7777
const searchInput = ref(filter.value.search);
7878
const onFilterChangeDebounced = debounce(() => onFilterChange(searchInput.value), 500);
7979
const filterDeps = computed(() => ({ ...filter.value }));

app/composables/useProbeFilters.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { useAuth } from '~/store/auth';
77

88
export type StatusCode = 'all' | 'online' | 'ping-test-failed' | 'offline' | 'online-outdated';
99
export type AdoptionOption = 'all' | 'adopted' | 'non-adopted';
10+
export type ProbeTypeOption = 'all' | 'hardware' | 'software';
1011

1112
type StatusOption = {
1213
name: string;
@@ -20,9 +21,10 @@ export interface Filter {
2021
by: string;
2122
desc: boolean;
2223
adoption: AdoptionOption;
24+
probeType: ProbeTypeOption;
2325
}
2426

25-
const DEFAULT_FILTER: Filter = { search: '', status: 'all', by: 'name', desc: false, adoption: 'all' } as const;
27+
const DEFAULT_FILTER: Filter = { search: '', status: 'all', by: 'name', desc: false, adoption: 'all', probeType: 'all' } as const;
2628

2729
export const SORTABLE_FIELDS: string[] = [ 'name', 'location', 'tags' ] as const;
2830

@@ -35,6 +37,8 @@ export const STATUS_MAP: Record<StatusCode, StatusOption> = {
3537
} as const;
3638

3739
export const ADOPTION_OPTIONS: string[] = [ 'all', 'adopted', 'non-adopted' ] as const;
40+
export const PROBE_TYPE_OPTIONS: string[] = [ 'all', 'hardware', 'software' ] as const;
41+
const ADMIN_FILTERS: (keyof Filter)[] = [ 'adoption', 'probeType' ] as const;
3842

3943
interface ProbeFiltersOptions {
4044
active?: MaybeRefOrGetter<boolean>;
@@ -47,6 +51,7 @@ export const useProbeFilters = ({ active = () => true }: ProbeFiltersOptions = {
4751

4852
const filter = ref<Filter>({ ...DEFAULT_FILTER });
4953
const anyFilterApplied = computed(() => (Object.keys(DEFAULT_FILTER) as Array<keyof Filter>).some(key => filter.value[key] !== DEFAULT_FILTER[key]));
54+
const anyAdminFilterApplied = computed(() => ADMIN_FILTERS.some(key => !isDefault(key)));
5055

5156
const onSortChange = (event: DataTableSortEvent) => {
5257
const { sortField = '', sortOrder = 1 } = event;
@@ -78,6 +83,7 @@ export const useProbeFilters = ({ active = () => true }: ProbeFiltersOptions = {
7883
...filter.value.desc && { desc: 'true' },
7984
...!isDefault('status') && { status: filter.value.status },
8085
...auth.isAdmin && !isDefault('adoption') && { adoption: filter.value.adoption },
86+
...auth.isAdmin && !isDefault('probeType') && { type: filter.value.probeType },
8187
});
8288

8389
const onParamChange = () => {
@@ -120,6 +126,9 @@ export const useProbeFilters = ({ active = () => true }: ProbeFiltersOptions = {
120126
...!ignoredFields.includes('adoption') && auth.isAdmin && !isDefault('adoption', filter) && {
121127
userId: filterValue.adoption === 'adopted' ? { _neq: null } : { _eq: null },
122128
},
129+
...!ignoredFields.includes('probeType') && auth.isAdmin && !isDefault('probeType', filter) && {
130+
hardwareDevice: filterValue.probeType === 'hardware' ? { _neq: null } : { _eq: null },
131+
},
123132
};
124133
};
125134

@@ -133,7 +142,8 @@ export const useProbeFilters = ({ active = () => true }: ProbeFiltersOptions = {
133142
() => route.query.desc,
134143
() => route.query.status,
135144
() => route.query.adoption,
136-
], async ([ search, by, desc, status, adoption ]) => {
145+
() => route.query.type,
146+
], async ([ search, by, desc, status, adoption, probeType ]) => {
137147
if (!toValue(active)) {
138148
return;
139149
}
@@ -167,12 +177,19 @@ export const useProbeFilters = ({ active = () => true }: ProbeFiltersOptions = {
167177
} else {
168178
filter.value.adoption = DEFAULT_FILTER.adoption;
169179
}
180+
181+
if (typeof probeType === 'string' && PROBE_TYPE_OPTIONS.includes(probeType) && auth.isAdmin) {
182+
filter.value.probeType = probeType as ProbeTypeOption;
183+
} else {
184+
filter.value.probeType = DEFAULT_FILTER.probeType;
185+
}
170186
}, { immediate: true });
171187

172188
return {
173189
// state
174190
filter,
175191
anyFilterApplied,
192+
anyAdminFilterApplied,
176193
// handlers
177194
onSortChange,
178195
onFilterChange,

0 commit comments

Comments
 (0)