Skip to content

Commit a9a9be5

Browse files
authored
Merge pull request #164 from devforth/filter-singleselect
fix: add option to turn enum and foreign resource filter into singleselect
2 parents e2e565a + d264dab commit a9a9be5

File tree

4 files changed

+61
-8
lines changed

4 files changed

+61
-8
lines changed

adminforth/documentation/docs/tutorial/03-Customization/13-standardPagesTuning.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -704,3 +704,29 @@ export default {
704704
```
705705
`debounceTimeMs` field dictates how long (in milliseconds) to wait between inputs to send updated data request. By increasing this value, you can reduce the amount of requests set to backend. Default value for this field is set to 10ms.
706706
`substringSearch` sets what comparison operator to use for text field. By default this field is set to `true`, which results in using case-insensitive `ILIKE` operator, that will look for records that have filter string anywhere inside field value. Setting this `substringSearch` to `false` will result in using more strict `EQ` operator, that will look for exact full-string matches.
707+
708+
You can also disabled multiselect on filter page for enumerator columns or foreign resource columns by adding `multiselect` field:
709+
710+
```typescript title="./resources/adminuser.ts"
711+
export default {
712+
name: 'adminuser',
713+
columns: [
714+
...
715+
{
716+
name: "parentUserId",
717+
foreignResource: {
718+
resourceId: "users",
719+
},
720+
//diff-add
721+
filterOptions: {
722+
//diff-add
723+
multiselect: false,
724+
//diff-add
725+
},
726+
},
727+
],
728+
},
729+
...
730+
],
731+
```
732+
This way, multiselect field displayed on filter page will be replaced with a default select field allowing only only value to be selected.

adminforth/modules/configValidator.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,9 @@ export default class ConfigValidator implements IConfigValidator {
454454
debounceTimeMs: 10,
455455
substringSearch: true,
456456
};
457+
if (col.enum || col.foreignResource) {
458+
col.filterOptions.multiselect = true;
459+
}
457460
} else {
458461
if (col.filterOptions.debounceTimeMs !== undefined) {
459462
if (typeof col.filterOptions.debounceTimeMs !== 'number') {
@@ -470,6 +473,18 @@ export default class ConfigValidator implements IConfigValidator {
470473
} else {
471474
col.filterOptions.substringSearch = true;
472475
}
476+
477+
if (col.filterOptions.multiselect !== undefined) {
478+
if (typeof col.filterOptions.multiselect !== 'boolean') {
479+
errors.push(`Resource "${res.resourceId}" column "${col.name}" has multiselectFilter in filterOptions that is not boolean`);
480+
}
481+
482+
if (!col.enum && !col.foreignResource) {
483+
errors.push(`Resource "${res.resourceId}" column "${col.name}" multiselectFilter in filterOptions should be set only for enum or foreign resource columns`);
484+
}
485+
} else if (col.enum || col.foreignResource) {
486+
col.filterOptions.multiselect = true;
487+
}
473488
}
474489

475490
col.showIn = this.validateAndNormalizeShowIn(resInput, inCol, errors, warnings);

adminforth/spa/src/components/Filters.vue

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@
2424

2525
<Select
2626
v-if="c.foreignResource"
27-
multiple
27+
:multiple="c.filterOptions.multiselect"
2828
class="w-full"
2929
:options="columnOptions[c.name] || []"
30-
@update:modelValue="onFilterInput[c.name]({ column: c, operator: 'in', value: $event.length ? $event : undefined })"
31-
:modelValue="filtersStore.filters.find(f => f.field === c.name && f.operator === 'in')?.value || []"
30+
@update:modelValue="onFilterInput[c.name]({ column: c, operator: c.filterOptions.multiselect ? 'in' : 'eq', value: c.filterOptions.multiselect ? ($event.length ? $event : undefined) : $event || undefined })"
31+
:modelValue="filtersStore.filters.find(f => f.field === c.name && f.operator === (c.filterOptions.multiselect ? 'in' : 'eq'))?.value || []"
3232
/>
3333
<Select
3434
multiple
@@ -44,13 +44,13 @@
4444
:modelValue="filtersStore.filters.find(f => f.field === c.name && f.operator === 'in')?.value || []"
4545
/>
4646

47-
<Select
48-
multiple
47+
<Select
48+
:multiple="c.filterOptions.multiselect"
4949
class="w-full"
5050
v-else-if="c.enum"
5151
:options="c.enum"
52-
@update:modelValue="onFilterInput[c.name]({ column: c, operator: 'in', value: $event.length ? $event : undefined })"
53-
:modelValue="filtersStore.filters.find(f => f.field === c.name && f.operator === 'in')?.value || []"
52+
@update:modelValue="onFilterInput[c.name]({ column: c, operator: c.filterOptions.multiselect ? 'in' : 'eq', value: c.filterOptions.multiselect ? ($event.length ? $event : undefined) : $event || undefined })"
53+
:modelValue="filtersStore.filters.find(f => f.field === c.name && f.operator === (c.filterOptions.multiselect ? 'in' : 'eq'))?.value || []"
5454
/>
5555

5656
<Input
@@ -118,7 +118,8 @@
118118
</template>
119119

120120
<script setup>
121-
import { watch, computed } from 'vue'
121+
import { watch, computed } from 'vue';
122+
import { useI18n } from 'vue-i18n';
122123
import CustomDateRangePicker from '@/components/CustomDateRangePicker.vue';
123124
import { callAdminForthApi } from '@/utils';
124125
import { useRouter } from 'vue-router';
@@ -130,6 +131,7 @@ import Select from '@/afcl/Select.vue';
130131
import debounce from 'debounce';
131132
132133
const filtersStore = useFiltersStore();
134+
const { t } = useI18n();
133135
134136
135137
// props: columns
@@ -163,6 +165,12 @@ const columnOptions = computedAsync(async () => {
163165
},
164166
});
165167
ret[column.name] = list.items;
168+
if (!column.filterOptions.multiselect) {
169+
ret[column.name].push({
170+
label: t('Unset'),
171+
value: '',
172+
});
173+
}
166174
}
167175
})
168176
);

adminforth/types/Common.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -815,6 +815,10 @@ export interface AdminForthResourceColumnInputCommon {
815815
* If false - will force EQ operator for filter instead of ILIKE.
816816
*/
817817
substringSearch?: boolean,
818+
/**
819+
* Boolean value that determines what select input type to display on filter page.
820+
*/
821+
multiselect?: boolean,
818822
},
819823

820824
/**

0 commit comments

Comments
 (0)