feat: add email recipient history to user settings and implement management in InboxDetailPage
Build and Push Multi-Platform Images / build-and-push (push) Successful in 36s
Build and Push Multi-Platform Images / build-and-push (push) Successful in 36s
This commit is contained in:
@@ -10,6 +10,7 @@ export interface UserSettingsData {
|
||||
smtpFromName: string | null;
|
||||
mailSignatureHtml: string | null;
|
||||
defaultLabelTemplateId: number | null;
|
||||
emailRecipientHistory: string[] | null;
|
||||
}
|
||||
|
||||
export interface SenderOption {
|
||||
|
||||
@@ -659,6 +659,7 @@ function SendEmailDialog({ open, fileId, fileName, documents, thumbUrls, onClose
|
||||
const [filenames, setFilenames] = useState<string[]>([]);
|
||||
const [senders, setSenders] = useState<SenderOption[]>([]);
|
||||
const [selectedSender, setSelectedSender] = useState<string>('default');
|
||||
const [recipientHistory, setRecipientHistory] = useState<string[]>([]);
|
||||
const editorRef = useRef<WysiwygEditorHandle>(null);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -672,6 +673,7 @@ function SendEmailDialog({ open, fileId, fileName, documents, thumbUrls, onClose
|
||||
);
|
||||
userSettingsApi.get().then((settings) => {
|
||||
editorRef.current?.setContent(settings.mailSignatureHtml ?? '');
|
||||
setRecipientHistory(settings.emailRecipientHistory ?? []);
|
||||
}).catch(() => {});
|
||||
userSettingsApi.getSenders().then((s) => {
|
||||
setSenders(s);
|
||||
@@ -679,12 +681,21 @@ function SendEmailDialog({ open, fileId, fileName, documents, thumbUrls, onClose
|
||||
}).catch(() => setSenders([]));
|
||||
}, [open, documents, fileName, form]);
|
||||
|
||||
const removeRecipient = (addr: string, e: React.MouseEvent) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
const updated = recipientHistory.filter((a) => a !== addr);
|
||||
setRecipientHistory(updated);
|
||||
userSettingsApi.update({ emailRecipientHistory: updated }).catch(() => {});
|
||||
};
|
||||
|
||||
const handleOk = async () => {
|
||||
try {
|
||||
const values = await form.validateFields();
|
||||
setSubmitting(true);
|
||||
const addresses: string[] = values.to ?? [];
|
||||
await inboxApi.sendEmail(fileId, {
|
||||
to: values.to,
|
||||
to: addresses.join(', '),
|
||||
subject: values.subject,
|
||||
body: editorRef.current?.getText() ?? '',
|
||||
html: editorRef.current?.getHTML(),
|
||||
@@ -694,6 +705,12 @@ function SendEmailDialog({ open, fileId, fileName, documents, thumbUrls, onClose
|
||||
})),
|
||||
sender: senders.length > 1 ? selectedSender : undefined,
|
||||
});
|
||||
const updated = [
|
||||
...addresses,
|
||||
...recipientHistory.filter((a) => !addresses.includes(a)),
|
||||
].slice(0, 20);
|
||||
setRecipientHistory(updated);
|
||||
userSettingsApi.update({ emailRecipientHistory: updated }).catch(() => {});
|
||||
message.success('E-Mail wurde gesendet');
|
||||
onClose();
|
||||
} catch (err: any) {
|
||||
@@ -726,8 +743,36 @@ function SendEmailDialog({ open, fileId, fileName, documents, thumbUrls, onClose
|
||||
/>
|
||||
</Form.Item>
|
||||
)}
|
||||
<Form.Item name="to" label="Empfänger" rules={[{ required: true, message: 'Bitte Empfänger angeben' }, { type: 'email', message: 'Ungültige E-Mail-Adresse' }]}>
|
||||
<Input placeholder="empfaenger@beispiel.de" />
|
||||
<Form.Item
|
||||
name="to"
|
||||
label="Empfänger"
|
||||
rules={[{
|
||||
validator: (_: unknown, value: string[]) => {
|
||||
if (!value?.length) return Promise.reject('Bitte mindestens einen Empfänger angeben');
|
||||
const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
const bad = value.find((v) => !re.test(v));
|
||||
return bad ? Promise.reject(`Ungültige Adresse: ${bad}`) : Promise.resolve();
|
||||
},
|
||||
}]}
|
||||
>
|
||||
<Select
|
||||
mode="tags"
|
||||
placeholder="empfaenger@beispiel.de"
|
||||
tokenSeparators={[',', ';']}
|
||||
options={recipientHistory.map((addr) => ({ value: addr, label: addr }))}
|
||||
optionRender={(option) => (
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 8 }}>
|
||||
<span>{option.label}</span>
|
||||
<Button
|
||||
type="text"
|
||||
size="small"
|
||||
icon={<DeleteOutlined />}
|
||||
onClick={(e) => removeRecipient(option.value as string, e)}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
notFoundContent={<span style={{ color: '#999', fontSize: 12 }}>Kein Verlauf vorhanden</span>}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item name="subject" label="Betreff" rules={[{ required: true, message: 'Bitte Betreff angeben' }]}>
|
||||
<Input />
|
||||
|
||||
Reference in New Issue
Block a user