3
0

Add option to remove user defined filter presets

This commit is contained in:
Jože Fortun
2023-09-19 18:40:20 +02:00
parent baf8b10282
commit a052906a4f
7 changed files with 267 additions and 221 deletions
@@ -230,8 +230,7 @@
<div
v-for="(m,i) in metrics"
:key="i"
class="rounded border border-light p-3 mb-3"
style="background-color: #F9FAFB;"
class="metric rounded border border-light p-3 mb-3"
>
<h5
v-if="metrics.length > 1"
@@ -690,3 +689,11 @@ export default {
},
}
</script>
<style lang="scss" scoped>
.metrics {
.metric {
background-color: $body-bg;
}
}
</style>
@@ -80,37 +80,36 @@
@export="onExport"
/>
<template v-if="filterPresets.length">
<b-button
:id="`${uniqueID}-filter-preset`"
variant="light"
size="lg"
class="mr-1"
<b-dropdown
v-if="filterPresets.length"
variant="light"
right
size="lg"
menu-class="shadow-sm"
boundary="viewport"
class="mr-1"
:text="$t('recordList.filter.filters.label')"
>
<li
v-for="(f, idx) in filterPresets"
:key="idx"
class="d-flex align-items-center justify-content-between"
>
{{ $t('recordList.filter.filters.label') }}
</b-button>
<button
class="dropdown-item"
:disabled="activeFilters.includes(f.name)"
@click="updateFilter(f.filter, f.name)"
>
{{ f.name }}
</button>
<b-popover
:target="`${uniqueID}-filter-preset`"
triggers="click blur"
placement="bottom"
>
<ul class="list-style-none">
<li
v-for="(f, idx) in filterPresets"
:key="idx"
>
<button
class="dropdown-item"
:disabled="activeFilters.includes(f.name)"
@click="updateFilter(f.filter, f.name)"
>
{{ f.name }}
</button>
</li>
</ul>
</b-popover>
</template>
<c-input-confirm
v-if="!f.roles"
class="mr-1"
@confirmed="removeStorageRecordListFilterPreset(f.name)"
/>
</li>
</b-dropdown>
<column-picker
v-if="!options.hideConfigureFieldsButton"
@@ -153,7 +152,7 @@
variant="secondary"
pill
class="ml-2"
@remove="removeFilter(title)"
@remove="removeFilter(i)"
/>
</b-form-tags>
</div>
@@ -987,7 +986,7 @@ export default {
filterPresets () {
return [
...this.options.filterPresets.filter(({ name }) => name),
...this.options.filterPresets.filter(({ name, roles }) => name && this.isUserRoleMember(roles)),
...this.customPresetFilters,
]
},
@@ -1696,6 +1695,16 @@ export default {
}
},
removeStorageRecordListFilterPreset (name) {
this.customPresetFilters = this.customPresetFilters.filter(f => f.name !== name)
try {
setItem(`record-list-preset-${this.uniqueID}`, this.customPresetFilters)
} catch (e) {
console.warn(this.$t('notification:record-list.corrupted-filter'))
}
},
onImportSuccessful () {
this.refresh(true)
},
@@ -250,117 +250,128 @@
</b-col>
</b-row>
<hr>
<b-row>
<b-col>
<b-form-group
:label="$t('recordList.filter.presets')"
:label="$t('recordList.record.setCustomFilterPresets')"
label-class="text-primary"
>
<b-table-simple
v-if="recordListModule"
borderless
small
responsive="lg"
class="mb-1"
>
<b-thead>
<b-tr>
<b-th
class="text-primary"
style="min-width: 300px;"
>
{{ $t('recordList.filter.name.label') }}
</b-th>
<b-th
class="text-primary"
style="width: 45%; min-width: 250px;"
>
{{ $t('recordList.filter.role.label') }}
</b-th>
<b-th
style="width: 100px;"
/>
</b-tr>
</b-thead>
<b-tbody>
<b-tr
v-for="(filter, index) in options.filterPresets"
:key="index"
>
<b-td>
<b-input-group>
<b-form-input
v-model="filter.name"
:placeholder="$t('recordList.filter.name.placeholder')"
/>
<b-input-group-append class="border-0">
<record-list-filter
class="d-print-none"
:target="`record-filter-${index}`"
:namespace="namespace"
:module="recordListModule"
:selected-field="recordListModule.fields[0]"
:record-list-filter="filter.filter"
variant="primary"
button-class="px-2 pt-2 text-white"
button-style="padding-bottom: calc(0.5rem - 2px);"
@filter="(filter) => onFilter(filter, index)"
/>
</b-input-group-append>
</b-input-group>
</b-td>
<b-td>
<vue-select
v-model="filter.roles"
:options="roleOptions"
:get-option-label="getRoleLabel"
:get-option-key="getOptionKey"
:placeholder="$t('recordList.filter.role.placeholder')"
:reduce="role => role.roleID"
:calculate-position="calculateDropdownPosition"
append-to-body
multiple
class="bg-white"
/>
</b-td>
<b-td
class="text-center align-middle pr-2"
>
<c-input-confirm
@confirmed="options.filterPresets.splice(index, 1)"
/>
</b-td>
</b-tr>
</b-tbody>
</b-table-simple>
<b-button
variant="primary"
size="sm"
class="ml-1"
@click="addFilterPreset"
>
{{ $t('recordList.filter.addFilter') }}
</b-button>
<c-input-checkbox
v-model="options.customFilterPresets"
switch
:labels="checkboxLabel"
/>
</b-form-group>
</b-col>
</b-row>
<b-row class="mb-3">
<b-col>
<b-form-group
:label="$t('recordList.record.setCustomFilterPresets')"
label-class="text-primary"
<b-row>
<b-col>
<div class="list-background rounded border border-light p-1">
<b-form-group
:label="$t('recordList.filter.presets')"
label-class="text-primary"
class="mb-0"
>
<b-table-simple
v-if="recordListModule"
borderless
small
responsive="lg"
class="mb-0"
>
<c-input-checkbox
v-model="options.customFilterPresets"
switch
:labels="checkboxLabel"
<draggable
:list.sync="options.filterPresets"
group="sort"
handle=".grab"
tag="tbody"
>
<b-tr
v-for="(filter, index) in options.filterPresets"
:key="index"
>
<b-td
class="grab text-center align-middle"
style="width: 40px;"
>
<font-awesome-icon
:icon="['fas', 'bars']"
/>
</b-td>
<b-td
class="align-middle"
style="min-width: 150px;"
>
<b-input-group>
<b-form-input
v-model="filter.name"
:placeholder="$t('recordList.filter.name.placeholder')"
/>
<b-input-group-append class="border-0">
<record-list-filter
class="d-print-none"
:target="`record-filter-${index}`"
:namespace="namespace"
:module="recordListModule"
:selected-field="recordListModule.fields[0]"
:record-list-filter="filter.filter"
variant="light"
button-class="px-2 pt-2"
button-style="padding-bottom: calc(0.5rem - 2px);"
@filter="(filter) => onFilter(filter, index)"
/>
</b-input-group-append>
</b-input-group>
</b-td>
<b-td
class="text-center align-middle"
style="min-width: 200px;"
>
<vue-select
v-model="filter.roles"
:options="roleOptions"
:get-option-label="getRoleLabel"
:get-option-key="getOptionKey"
:placeholder="$t('recordList.filter.role.placeholder')"
:reduce="role => role.roleID"
:calculate-position="calculateDropdownPosition"
append-to-body
multiple
class="bg-white"
/>
</b-td>
<b-td
class="text-right align-middle"
style="min-width: 80px; width: 80px;"
>
<c-input-confirm
@confirmed="options.filterPresets.splice(index, 1)"
/>
</b-td>
</b-tr>
</draggable>
</b-table-simple>
<b-button
variant="primary"
size="sm"
class="mt-1"
@click="addFilterPreset"
>
<font-awesome-icon
:icon="['fas', 'plus']"
class="mr-1"
/>
</b-form-group>
</b-col>
</b-row>
{{ $t('general:label.add') }}
</b-button>
</b-form-group>
</div>
</b-col>
</b-row>
</div>
@@ -373,7 +384,8 @@
<h5 class="mb-3">
{{ $t('recordList.record.presortLabel') }}
</h5>
<b-row class="mb-3">
<b-row>
<b-col>
<b-form-group
:label="$t('recordList.record.presortHideSort')"
@@ -391,26 +403,28 @@
<b-row>
<b-col>
<b-form-group
:label="$t('recordList.record.presortInputLabel')"
label-class="text-primary"
>
<c-input-presort
v-model="options.presort"
:fields="recordListModuleFields"
:labels="{
add: $t('general:label.add'),
ascending: $t('general:label.ascending'),
descending: $t('general:label.descending'),
none: $t('general:label.none'),
placeholder: $t('recordList.record.presortPlaceholder'),
footnote: $t('recordList.record.presortFootnote'),
toggleInput: $t('recordList.record.presortToggleInput'),
}"
allow-text-input
class="mb-2"
/>
</b-form-group>
<div class="list-background rounded border border-light p-1">
<b-form-group
:label="$t('recordList.record.presortInputLabel')"
label-class="text-primary"
class="mb-0"
>
<c-input-presort
v-model="options.presort"
:fields="recordListModuleFields"
:labels="{
add: $t('general:label.add'),
ascending: $t('general:label.ascending'),
descending: $t('general:label.descending'),
none: $t('general:label.none'),
placeholder: $t('recordList.record.presortPlaceholder'),
footnote: $t('recordList.record.presortFootnote'),
toggleInput: $t('recordList.record.presortToggleInput'),
}"
allow-text-input
/>
</b-form-group>
</div>
</b-col>
</b-row>
</div>
@@ -739,6 +753,7 @@
import { mapGetters } from 'vuex'
import { NoID } from '@cortezaproject/corteza-js'
import { VueSelect } from 'vue-select'
import Draggable from 'vuedraggable'
import base from './base'
import AutomationTab from './Shared/AutomationTab'
import FieldPicker from 'corteza-webapp-compose/src/components/Common/FieldPicker'
@@ -759,6 +774,7 @@ export default {
CInputPresort,
RecordListFilter,
VueSelect,
Draggable,
},
extends: base,
@@ -958,3 +974,9 @@ export default {
width: fit-content;
}
</style>
<style lang="scss" scoped>
.list-background {
background-color: $body-bg;
}
</style>
@@ -2,7 +2,7 @@
<div class="h-100">
<b-card
no-body
class="d-flex flex-column h-100 shadow overflow-hidden"
class="d-flex flex-column h-100 shadow overflow-hidden position-static"
:class="[blockClass, cardClass]"
>
<b-card-header
@@ -1,7 +1,7 @@
<template>
<div class="h-100">
<div
class="d-flex flex-column card bg-transparent h-100 overflow-hidden"
class="d-flex flex-column card bg-transparent h-100 overflow-hidden position-static"
:class="[blockClass, cardClass]"
>
<div
+69 -60
View File
@@ -1,67 +1,77 @@
<template>
<div>
<draggable
<b-table-simple
v-if="!textInput"
:list.sync="items"
group="sort"
handle=".grab"
borderless
small
responsive="lg"
class="mb-0"
>
<b-form-row
v-for="(column, index) in items"
:key="index"
class="mb-1"
<draggable
:list.sync="items"
group="sort"
handle=".grab"
tag="tbody"
>
<b-col
cols="1"
class="d-flex align-items-center justify-content-center"
<tr
v-for="(column, index) in items"
:key="index"
>
<font-awesome-icon
:icon="['fas', 'bars']"
class="grab text-grey"
/>
</b-col>
<b-col
cols="5"
>
<b-form-select
v-model="column.field"
:options="availableFields"
text-field="label"
value-field="name"
class="rounded"
<td
class="grab text-center align-middle"
style="width: 40px;"
>
<template #first>
<b-form-select-option
:value="undefined"
disabled
>
{{ labels.none }}
</b-form-select-option>
</template>
</b-form-select>
</b-col>
<font-awesome-icon
:icon="['fas', 'bars']"
/>
</td>
<b-col
cols="6"
class="d-flex align-items-center justify-content-around"
>
<b-form-radio-group
v-model="column.descending"
:options="sortDirections"
buttons
size="sm"
button-variant="outline-primary"
/>
<c-input-confirm
variant="link"
size="lg"
button-class="text-dark px-0"
@confirmed="items.splice(index, 1)"
/>
</b-col>
</b-form-row>
</draggable>
<td
class="align-middle"
style="min-width: 250px;"
>
<b-form-select
v-model="column.field"
:options="availableFields"
text-field="label"
value-field="name"
class="rounded"
>
<template #first>
<b-form-select-option
:value="undefined"
disabled
>
{{ labels.none }}
</b-form-select-option>
</template>
</b-form-select>
</td>
<td
class="text-center align-middle"
style="min-width: 200px;"
>
<b-form-radio-group
v-model="column.descending"
:options="sortDirections"
buttons
button-variant="outline-primary"
class="bg-white"
/>
</td>
<td
class="align-middle text-right"
style="min-width: 80px; width: 80px;"
>
<c-input-confirm
@confirmed="items.splice(index, 1)"
/>
</td>
</tr>
</draggable>
</b-table-simple>
<div
v-else
@@ -76,17 +86,16 @@
</div>
<div
class="d-flex align-items-center"
class="d-flex align-items-center mt-1"
>
<b-button
v-if="!textInput"
variant="link"
class="d-flex align-items-center px-0 text-decoration-none"
variant="primary"
size="sm"
@click="items.push({ field: undefined, descending: false })"
>
<font-awesome-icon
:icon="['fas', 'plus']"
size="sm"
class="mr-1"
/>
{{ labels.add }}
+1 -2
View File
@@ -329,7 +329,6 @@ recordList:
fields: Module fields
filter:
addField: Add new filter field
addFilter: + Add filter
byValue: Filter records based on field value
addFilterToPreset: Save as preset
conditions:
@@ -368,7 +367,7 @@ recordList:
placeholder: Filter name
role:
label: Role(s)
placeholder: Select role(s) to apply filter to
placeholder: Select role(s) that will be able to use preset
hideRecordCloneButton: Hide clone record button
hideRecordEditButton: Hide edit record button
hideRecordPermissionsButton: Hide record permissions button