Implement database migration, notification logs, and one-click Mailcow setup
This commit is contained in:
@@ -19,6 +19,13 @@ interface Domain {
|
||||
domain_name: string;
|
||||
}
|
||||
|
||||
interface User {
|
||||
id: string;
|
||||
name: string;
|
||||
email: string;
|
||||
telegramId?: string;
|
||||
}
|
||||
|
||||
export default function MailboxesPage() {
|
||||
const { data: session } = useSession();
|
||||
const [domains, setDomains] = useState<Domain[]>([]);
|
||||
@@ -30,12 +37,14 @@ export default function MailboxesPage() {
|
||||
const [showInfoModal, setShowInfoModal] = useState<string | null>(null);
|
||||
const [isPending, startTransition] = useTransition();
|
||||
const [search, setSearch] = useState("");
|
||||
const [createForm, setCreateForm] = useState({ local_part: "", name: "", password: "", quota: 3072 });
|
||||
const [users, setUsers] = useState<User[]>([]);
|
||||
const [createForm, setCreateForm] = useState({ local_part: "", name: "", password: "", quota: 3072, notifyUserId: "" });
|
||||
const [newPassword, setNewPassword] = useState("");
|
||||
const [formError, setFormError] = useState("");
|
||||
const dict = useDictionary();
|
||||
|
||||
useEffect(() => {
|
||||
// Fetch domains
|
||||
fetch("/api/domains")
|
||||
.then((r) => r.json())
|
||||
.then((data: Domain[]) => {
|
||||
@@ -44,6 +53,13 @@ export default function MailboxesPage() {
|
||||
setSelectedDomain(data[0].domain_name);
|
||||
}
|
||||
});
|
||||
|
||||
// Fetch users for mapping selection
|
||||
fetch("/api/users")
|
||||
.then((r) => r.json())
|
||||
.then((data) => {
|
||||
if (Array.isArray(data)) setUsers(data);
|
||||
});
|
||||
}, []);
|
||||
|
||||
const fetchMailboxes = useCallback(async (domain: string) => {
|
||||
@@ -63,21 +79,46 @@ export default function MailboxesPage() {
|
||||
e.preventDefault();
|
||||
setFormError("");
|
||||
startTransition(async () => {
|
||||
const res = await fetch("/api/mailboxes", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ ...createForm, domain: selectedDomain }),
|
||||
});
|
||||
const data = await res.json();
|
||||
if (res.ok) {
|
||||
setShowCreateModal(false);
|
||||
setCreateForm({ local_part: "", name: "", password: "", quota: 3072 });
|
||||
fetchMailboxes(selectedDomain);
|
||||
} else {
|
||||
const msg = Array.isArray(data)
|
||||
? data.map((d: { msg?: unknown }) => JSON.stringify(d.msg)).join(", ")
|
||||
: (data?.error ?? "Mailcow bağlantısını kontrol edin");
|
||||
setFormError(String(msg));
|
||||
try {
|
||||
const res = await fetch("/api/mailboxes", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ ...createForm, domain: selectedDomain }),
|
||||
});
|
||||
|
||||
let data: any = {};
|
||||
try {
|
||||
data = await res.json();
|
||||
} catch (e) {
|
||||
data = { error: "Sunucudan geçersiz yanıt geldi (JSON hatası)." };
|
||||
}
|
||||
|
||||
if (res.ok) {
|
||||
// If a notification user is selected, create the mapping
|
||||
if (createForm.notifyUserId) {
|
||||
const fullEmail = `${createForm.local_part}@${selectedDomain}`;
|
||||
await fetch("/api/mappings", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
email: fullEmail,
|
||||
userId: createForm.notifyUserId,
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
setShowCreateModal(false);
|
||||
setCreateForm({ local_part: "", name: "", password: "", quota: 3072, notifyUserId: "" });
|
||||
fetchMailboxes(selectedDomain);
|
||||
} else {
|
||||
const msg = Array.isArray(data)
|
||||
? data.map((d: { msg?: unknown }) => JSON.stringify(d.msg)).join(", ")
|
||||
: (data?.error ?? "Mailcow bağlantısını veya veritabanını kontrol edin");
|
||||
setFormError(String(msg));
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error("Mailbox creation failed:", error);
|
||||
setFormError(error.message);
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -333,6 +374,21 @@ export default function MailboxesPage() {
|
||||
<input type="number" className="input" value={createForm.quota} min={100} max={102400}
|
||||
onChange={(e) => setCreateForm({ ...createForm, quota: parseInt(e.target.value) || 3072 })} />
|
||||
</div>
|
||||
<div>
|
||||
<label className="label">{dict.mailboxes.notifyUser || "Bildirim Gidecek Kullanıcı (TG)"}</label>
|
||||
<select
|
||||
className="input"
|
||||
value={createForm.notifyUserId}
|
||||
onChange={(e) => setCreateForm({ ...createForm, notifyUserId: e.target.value })}
|
||||
>
|
||||
<option value="">-- {dict.mailboxes.noNotify || "Bildirim Gönderme"} --</option>
|
||||
{users.map((u) => (
|
||||
<option key={u.id} value={u.id}>
|
||||
{u.name || u.email} {u.telegramId ? `(TG: ${u.telegramId})` : ""}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-footer">
|
||||
<button type="button" className="btn btn-ghost" onClick={() => setShowCreateModal(false)}>{dict.mailboxes.cancel || "İptal"}</button>
|
||||
|
||||
Reference in New Issue
Block a user