comma split
This commit is contained in:
parent
6fdf8f6436
commit
be855415d5
|
|
@ -2,38 +2,68 @@ import React, { useState } from 'react';
|
||||||
import { FiSlash, FiPlus, FiTrash2, FiShield } from 'react-icons/fi';
|
import { FiSlash, FiPlus, FiTrash2, FiShield } from 'react-icons/fi';
|
||||||
|
|
||||||
const BlockedSenders = ({ rule, onUpdate }) => {
|
const BlockedSenders = ({ rule, onUpdate }) => {
|
||||||
// 'rule' ist hier das Objekt { email_address, blocked_patterns: [] }
|
|
||||||
const [patterns, setPatterns] = useState(rule?.blocked_patterns || []);
|
const [patterns, setPatterns] = useState(rule?.blocked_patterns || []);
|
||||||
const [newPattern, setNewPattern] = useState('');
|
const [newPattern, setNewPattern] = useState('');
|
||||||
const [inputError, setInputError] = useState('');
|
const [inputError, setInputError] = useState('');
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
const validatePattern = (pattern) => {
|
const validatePattern = (pattern) => {
|
||||||
// Einfache Validierung: Muss mindestens 3 Zeichen haben und darf nicht leer sein.
|
// Einfache Validierung: Mindestens 3 Zeichen. Wildcards * sind erlaubt.
|
||||||
// Wildcards * sind erlaubt.
|
|
||||||
return pattern.length >= 3;
|
return pattern.length >= 3;
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleAddPattern = () => {
|
const handleAddPattern = () => {
|
||||||
const trimmedPattern = newPattern.trim();
|
if (!newPattern.trim()) {
|
||||||
if (!trimmedPattern) {
|
setInputError('Please enter a pattern');
|
||||||
setInputError('Pattern is required');
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!validatePattern(trimmedPattern)) {
|
// NEU: Splitten am Komma, bereinigen und leere Einträge filtern
|
||||||
setInputError('Pattern too short or invalid');
|
const potentialPatterns = newPattern
|
||||||
|
.split(',')
|
||||||
|
.map(p => p.trim())
|
||||||
|
.filter(p => p.length > 0);
|
||||||
|
|
||||||
|
const validNewPatterns = [];
|
||||||
|
let duplicateCount = 0;
|
||||||
|
let invalidCount = 0;
|
||||||
|
|
||||||
|
potentialPatterns.forEach(pattern => {
|
||||||
|
// Validierung prüfen
|
||||||
|
if (!validatePattern(pattern)) {
|
||||||
|
invalidCount++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Duplikate prüfen (sowohl in bestehender Liste als auch in der neuen Charge)
|
||||||
|
if (patterns.includes(pattern) || validNewPatterns.includes(pattern)) {
|
||||||
|
duplicateCount++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
validNewPatterns.push(pattern);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Fehlerbehandlung: Wenn gar nichts hinzugefügt werden kann
|
||||||
|
if (validNewPatterns.length === 0) {
|
||||||
|
if (invalidCount > 0 && potentialPatterns.length === invalidCount) {
|
||||||
|
setInputError('All entered patterns were invalid (too short).');
|
||||||
|
} else if (duplicateCount > 0) {
|
||||||
|
setInputError('All entered patterns are already in the list.');
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (patterns.includes(trimmedPattern)) {
|
// State aktualisieren
|
||||||
setInputError('This pattern is already in the list');
|
setPatterns([...patterns, ...validNewPatterns]);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setPatterns([...patterns, trimmedPattern]);
|
|
||||||
setNewPattern('');
|
setNewPattern('');
|
||||||
setInputError('');
|
|
||||||
|
// Optional: Feedback bei teilweisem Erfolg
|
||||||
|
if (invalidCount > 0 || duplicateCount > 0) {
|
||||||
|
setInputError(`Added ${validNewPatterns.length} patterns. (${invalidCount} invalid, ${duplicateCount} duplicates skipped)`);
|
||||||
|
} else {
|
||||||
|
setInputError('');
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleRemovePattern = (patternToRemove) => {
|
const handleRemovePattern = (patternToRemove) => {
|
||||||
|
|
@ -64,7 +94,7 @@ const BlockedSenders = ({ rule, onUpdate }) => {
|
||||||
{/* Add Pattern Form */}
|
{/* Add Pattern Form */}
|
||||||
<div>
|
<div>
|
||||||
<label htmlFor="block-pattern" className="block text-sm font-semibold text-gray-700 mb-2">
|
<label htmlFor="block-pattern" className="block text-sm font-semibold text-gray-700 mb-2">
|
||||||
Block Sender Pattern
|
Block Sender Pattern(s)
|
||||||
</label>
|
</label>
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
|
|
@ -74,14 +104,17 @@ const BlockedSenders = ({ rule, onUpdate }) => {
|
||||||
value={newPattern}
|
value={newPattern}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setNewPattern(e.target.value);
|
setNewPattern(e.target.value);
|
||||||
setInputError('');
|
// Fehler nur löschen, wenn User tippt und keine Erfolgsmeldung angezeigt wird
|
||||||
|
if (!inputError.startsWith('Added')) setInputError('');
|
||||||
}}
|
}}
|
||||||
onKeyPress={handleKeyPress}
|
onKeyPress={handleKeyPress}
|
||||||
placeholder="spam@*.com, *@badsite.org"
|
placeholder="spam@*.com, *@badsite.org (comma separated)"
|
||||||
className={`input-field ${inputError ? 'border-red-500 focus:ring-red-500' : ''}`}
|
className={`input-field ${inputError && !inputError.startsWith('Added') ? 'border-red-500 focus:ring-red-500' : ''}`}
|
||||||
/>
|
/>
|
||||||
{inputError && (
|
{inputError && (
|
||||||
<p className="mt-1 text-sm text-red-600">{inputError}</p>
|
<p className={`mt-1 text-sm ${inputError.startsWith('Added') ? 'text-green-600' : 'text-red-600'}`}>
|
||||||
|
{inputError}
|
||||||
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
|
|
@ -93,7 +126,7 @@ const BlockedSenders = ({ rule, onUpdate }) => {
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<p className="mt-2 text-xs text-gray-500">
|
<p className="mt-2 text-xs text-gray-500">
|
||||||
Supports wildcards (*). Examples: <code>marketing@spam.com</code>, <code>*@phishing.net</code>
|
Paste a comma-separated list to add multiple entries at once. Supports wildcards (*).
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -103,6 +136,14 @@ const BlockedSenders = ({ rule, onUpdate }) => {
|
||||||
<label className="block text-sm font-semibold text-gray-700">
|
<label className="block text-sm font-semibold text-gray-700">
|
||||||
Blocked Patterns ({patterns.length})
|
Blocked Patterns ({patterns.length})
|
||||||
</label>
|
</label>
|
||||||
|
{patterns.length > 0 && (
|
||||||
|
<button
|
||||||
|
onClick={() => setPatterns([])}
|
||||||
|
className="text-xs text-red-600 hover:text-red-800 hover:underline"
|
||||||
|
>
|
||||||
|
Clear all
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{patterns.length === 0 ? (
|
{patterns.length === 0 ? (
|
||||||
|
|
@ -112,10 +153,10 @@ const BlockedSenders = ({ rule, onUpdate }) => {
|
||||||
<p className="text-sm text-gray-500 mt-1">Add a pattern above to block incoming emails</p>
|
<p className="text-sm text-gray-500 mt-1">Add a pattern above to block incoming emails</p>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="space-y-2">
|
<div className="space-y-2 max-h-[400px] overflow-y-auto pr-2 custom-scrollbar">
|
||||||
{patterns.map((pattern, index) => (
|
{patterns.map((pattern, index) => (
|
||||||
<div
|
<div
|
||||||
key={index}
|
key={`${pattern}-${index}`}
|
||||||
className="flex items-center justify-between p-4 bg-white border border-gray-200 rounded-lg hover:border-red-300 transition-colors group"
|
className="flex items-center justify-between p-4 bg-white border border-gray-200 rounded-lg hover:border-red-300 transition-colors group"
|
||||||
>
|
>
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue