auto-assign filter priority (max+10) on create

New filter rules no longer default to priority 100. Server picks
max(priority)+10 per account when client sends priority=None (or 10
if the account has no rules yet), and the UI pre-fills the input
with the next value instead of a fixed 100. Avoids ambiguous ordering
when multiple rules end up with the same priority.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-31 10:46:52 +02:00
parent b77b192b56
commit 202920b9ef
3 changed files with 23 additions and 6 deletions
+12 -1
View File
@@ -1,4 +1,5 @@
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy import func
from sqlalchemy.orm import Session
import logging
@@ -52,10 +53,20 @@ def create_filter(data: FilterRuleCreate, db: Session = Depends(get_db)):
if not account:
raise HTTPException(404, "Konto nicht gefunden")
if data.priority is None:
# Ans Ende einsortieren: max(priority) + 10 für dieses Konto. Falls noch
# keine Regel existiert, starten wir bei 10.
current_max = db.query(func.max(FilterRule.priority)).filter(
FilterRule.account_id == data.account_id
).scalar()
priority = (current_max + 10) if current_max is not None else 10
else:
priority = data.priority
rule = FilterRule(
account_id=data.account_id,
name=data.name,
priority=data.priority,
priority=priority,
enabled=data.enabled,
stop_processing=data.stop_processing,
source_folder=data.source_folder,
+1 -1
View File
@@ -41,7 +41,7 @@ class FilterActionResponse(FilterActionCreate):
class FilterRuleCreate(BaseModel):
name: str
account_id: int
priority: int = 100
priority: int | None = None # None → automatisch ans Ende einsortieren (max+10)
enabled: bool = True
stop_processing: bool = False
source_folder: str = "INBOX"
+10 -4
View File
@@ -29,8 +29,8 @@
</label>
<div class="grid">
<label>
Priorität
<input type="number" id="filter-priority" value="100">
Priorität <small style="opacity:0.7;">(niedriger = früher)</small>
<input type="number" id="filter-priority" placeholder="auto">
</label>
<label>
Quellordner
@@ -179,6 +179,8 @@ const ACTION_TYPES = [
{value: 'mark_read', label: 'Als gelesen markieren', needsParam: false, needsFolder: false},
];
let currentFilters = [];
async function loadFilters() {
const accountId = document.getElementById('account-select').value;
const container = document.getElementById('filters-container');
@@ -188,6 +190,7 @@ async function loadFilters() {
}
const resp = await fetch(`/api/filters/account/${accountId}`);
const filters = await resp.json();
currentFilters = filters;
if (filters.length === 0) {
container.innerHTML = `
<p>Keine Filterregeln für dieses Konto.</p>
@@ -369,7 +372,8 @@ function openNewFilter() {
document.getElementById('dialog-title').textContent = 'Neue Filterregel';
document.getElementById('filter-id').value = '';
document.getElementById('filter-name').value = '';
document.getElementById('filter-priority').value = '100';
const maxPrio = currentFilters.reduce((m, f) => Math.max(m, f.priority), -Infinity);
document.getElementById('filter-priority').value = isFinite(maxPrio) ? (maxPrio + 10) : 10;
document.getElementById('filter-source-folder').value = 'INBOX';
document.getElementById('filter-stop-processing').checked = false;
document.getElementById('conditions-list').innerHTML = '';
@@ -432,10 +436,12 @@ function collectFormData() {
parameter: input ? (input.value || null) : null,
});
}
const prioRaw = document.getElementById('filter-priority').value.trim();
const prio = prioRaw === '' ? null : parseInt(prioRaw);
return {
account_id: parseInt(accountId),
name: document.getElementById('filter-name').value,
priority: parseInt(document.getElementById('filter-priority').value),
priority: prio,
source_folder: document.getElementById('filter-source-folder').value,
stop_processing: document.getElementById('filter-stop-processing').checked,
enabled: true,