Improved UI

This commit is contained in:
Antoine Nguyen
2024-06-22 19:44:47 +02:00
committed by Spitfireap
parent 39720bb44a
commit 6f6edecb93
5 changed files with 113 additions and 62 deletions
+55 -48
View File
@@ -31,55 +31,57 @@
value="all"
/>
</v-radio-group>
<div v-for="(condition, index) in form.conditions" class="d-flex align-center">
<v-select
v-model="condition.name"
:label="$gettext('Choose a header')"
:items="conditionTemplates"
item-title="label"
item-value="name"
variant="outlined"
density="compact"
:rules="[rules.required]"
@update:model-value=""
/>
<v-select
v-model="condition.operator"
:label="$gettext('Choose an operator')"
:items="getConditionOperators(condition.name)"
item-title="label"
item-value="name"
variant="outlined"
class="ml-2"
density="compact"
:rules="[rules.required]"
/>
<v-text-field
v-model="condition.value"
:label="$gettext('Value')"
variant="outlined"
class="ml-2"
density="compact"
:type="getConditionType(index)"
:rules="[rules.required]"
/>
<v-btn
v-if="index === 0"
icon="mdi-plus"
variant="text"
:title="$gettext('Add condition')"
color="primary"
@click="addCondition"
/>
<v-btn
v-else
icon="mdi-trash-can"
variant="text"
:title="$gettext('Remove condition')"
color="error"
@click="removeCondition(index)"
<template v-if="form.match_type !== 'all'">
<div v-for="(condition, index) in form.conditions" class="d-flex align-center">
<v-select
v-model="condition.name"
:label="$gettext('Choose a header')"
:items="conditionTemplates"
item-title="label"
item-value="name"
variant="outlined"
density="compact"
:rules="[rules.required]"
@update:model-value=""
/>
</div>
<v-select
v-model="condition.operator"
:label="$gettext('Choose an operator')"
:items="getConditionOperators(condition.name)"
item-title="label"
item-value="name"
variant="outlined"
class="ml-2"
density="compact"
:rules="[rules.required]"
/>
<v-text-field
v-model="condition.value"
:label="$gettext('Value')"
variant="outlined"
class="ml-2"
density="compact"
:type="getConditionType(index)"
:rules="[rules.required]"
/>
<v-btn
v-if="index === 0"
icon="mdi-plus"
variant="text"
:title="$gettext('Add condition')"
color="primary"
@click="addCondition"
/>
<v-btn
v-else
icon="mdi-trash-can"
variant="text"
:title="$gettext('Remove condition')"
color="error"
@click="removeCondition(index)"
/>
</div>
</template>
</div>
<div>
<h4>{{ $gettext('Actions') }}</h4>
@@ -143,6 +145,7 @@
<v-btn
color="primary"
:text="submitLabel"
:loading="working"
@click="submit"
></v-btn>
</v-card-actions>
@@ -175,6 +178,7 @@ const conditionTemplates = ref([])
const actionTemplates = ref([])
const formRef = ref()
const form = ref(getInitialFormContent())
const working = ref(false)
const title = computed(() => {
return (props.filter) ? $gettext('Edit filter') : $gettext('New filter')
@@ -266,6 +270,7 @@ async function submit() {
if (!valid) {
return
}
working.value = true
let msg
const data = JSON.parse(JSON.stringify(form.value))
for (const action of data.actions) {
@@ -288,6 +293,8 @@ async function submit() {
busStore.displayNotification({ msg: err.response.data.error, type: 'error' })
}
return
} finally {
working.value = false
}
busStore.displayNotification({ msg })
close()
@@ -36,13 +36,18 @@
<script setup>
import { ref } from 'vue'
import { useBusStore } from '@/stores'
import { useGettext } from 'vue3-gettext'
import rules from '@/plugins/rules'
import accountApi from '@/api/account'
const { $gettext } = useGettext()
const emit = defineEmits(['close'])
const busStore = useBusStore()
const form = ref({})
const formRef = ref()
const working = ref(false)
function close() {
formRef.value.reset()
@@ -55,8 +60,13 @@ async function submit() {
if (!valid) {
return
}
accountApi.createFilterSet(form.value).then(() => {
working.value = true
try {
await accountApi.createFilterSet(form.value)
busStore.displayNotification({ msg: $gettext('Filter set created') })
close()
})
} finally {
working.value = false
}
}
</script>
+1 -1
View File
@@ -257,7 +257,7 @@ const routes = [
},
children: [
{
path: 'filters',
path: 'filters/:filterset?',
name: 'AccountFilters',
component: () => import('@/views/account/FiltersView.vue'),
meta: {
+43 -10
View File
@@ -8,7 +8,7 @@
v-model="currentFilterSet"
:label="$gettext('Select a filter set')"
:items="filterSets"
item-title="name"
:item-title="getFilterSetName"
return-object
variant="outlined"
hide-details
@@ -35,7 +35,7 @@
</v-btn>
</template>
<MenuItems
:items="filterSetActions"
:items="getFilterSetActions()"
:obj="currentFilterSet"
/>
</v-menu>
@@ -103,6 +103,7 @@
<script setup>
import { ref, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { useGettext } from 'vue3-gettext'
import { useBusStore } from '@/stores'
import accountApi from '@/api/account'
@@ -110,6 +111,8 @@ import FilterSetForm from '@/components/account/FilterSetForm.vue'
import FilterForm from '@/components/account/FilterForm.vue'
import MenuItems from '@/components/tools/MenuItems.vue'
const router = useRouter()
const route = useRoute()
const busStore = useBusStore()
const { $gettext } = useGettext()
@@ -129,9 +132,24 @@ const headers = [
watch(currentFilterSet, (value) => {
if (value) {
fetchFilters(value.name)
if (route.params.filterset !== value.name) {
router.push({
name: 'AccountFilters', params: { filterset: value.name }
})
}
} else {
router.push({ name: 'AccountFilters' })
}
})
function getFilterSetName(filterSet) {
let result = filterSet.name
if (filterSet.active) {
result += ' (' + $gettext('active') + ')'
}
return result
}
function closeFilterSetForm() {
showFilterSetForm.value = false
fetchFilterSets()
@@ -146,6 +164,14 @@ function closeFilterForm() {
function fetchFilterSets() {
accountApi.getFilterSets().then(resp => {
filterSets.value = resp.data
if (!currentFilterSet.value && route.params.filterset) {
for (const filterSet of filterSets.value) {
if (filterSet.name === route.params.filterset) {
currentFilterSet.value = filterSet
break
}
}
}
})
}
@@ -237,13 +263,7 @@ function getFilterActions(filter) {
return result
}
const filterSetActions = ref([
{
label: $gettext('Activate filter set'),
color: 'success',
icon: 'mdi-check',
onClick: activateFilterSet
},
const filterSetActions = [
{
label: $gettext('Download filter set'),
icon: 'mdi-download',
@@ -255,7 +275,20 @@ const filterSetActions = ref([
icon: 'mdi-trash-can',
onClick: deleteFilterSet
}
])
]
function getFilterSetActions() {
const result = []
if (!currentFilterSet.value.active) {
result.push({
label: $gettext('Activate filter set'),
color: 'success',
icon: 'mdi-check',
onClick: activateFilterSet
})
}
return result.concat(filterSetActions)
}
fetchFilterSets()
</script>
+2 -1
View File
@@ -3,6 +3,7 @@
from typing import List, Tuple
from sievelib import commands
from sievelib.factory import Filter
from rest_framework import serializers
@@ -37,7 +38,7 @@ class FilterSerializer(serializers.Serializer):
actions = ActionSerializer(many=True)
@staticmethod
def from_filters(filters) -> "FilterSerializer":
def from_filters(filters: List[Filter]) -> "FilterSerializer":
result = []
for fobj in filters:
test = (