/** * WooCow – My Account frontend JavaScript */ (function ($) { 'use strict'; if (!$('#woocow-account').length) return; const ajax = (action, data) => $.post(woocowAcct.ajax_url, { action, nonce: woocowAcct.nonce, ...data }); const notice = (msg, type = 'success') => { const $n = $('#woocow-acct-notices'); $n.html(`
${msg}
`); setTimeout(() => $n.find('> div').fadeOut(400, function () { $(this).remove(); }), 5000); }; function esc(str) { return String(str).replace(/[&<>"']/g, m => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' })[m]); } function formatMB(bytes) { if (!bytes) return '0 MB'; const mb = bytes / 1024 / 1024; return mb >= 1024 ? (mb / 1024).toFixed(1) + ' GB' : mb.toFixed(0) + ' MB'; } // ── Load Mailboxes ──────────────────────────────────────────────────────── $(document).on('click', '.woocow-load-mailboxes', function () { const $panel = $(this).closest('.woocow-domain-panel'); const sid = $panel.data('server-id'); const domain = $panel.data('domain'); const $wrap = $panel.find('.woocow-mailboxes-wrap'); const $list = $panel.find('.woocow-mailboxes-list'); $(this).prop('disabled', true).text('Loading…'); $wrap.show(); $list.html('

Fetching mailboxes…

'); ajax('woocow_acct_mailboxes', { server_id: sid, domain }).done(res => { $(this).prop('disabled', false).text('Refresh'); if (!res.success) { $list.html(`

${esc(res.data)}

`); return; } const boxes = res.data.mailboxes || []; const webmail = res.data.webmail_url; if (!boxes.length) { $list.html('

No mailboxes yet. Create one below.

'); return; } let html = ''; boxes.forEach(m => { const unlimited = (m.quota === 0 || m.quota === '0'); const pct = unlimited ? 0 : parseFloat(m.percent_in_use || 0); const used = formatMB(m.quota_used); const max = unlimited ? '∞' : formatMB(m.quota); const col = pct > 85 ? '#e74c3c' : pct > 60 ? '#f39c12' : '#27ae60'; html += `
${esc(m.username)} ${m.name ? `(${esc(m.name)})` : ''}
${used} / ${max} (${pct}%)
↗ Webmail
`; }); $list.html(html); }); }); // ── Aliases ─────────────────────────────────────────────────────────────── $(document).on('click', '.wc-toggle-aliases', function () { const $row = $(this).closest('.woocow-mailbox-row'); const $wrap = $row.find('.woocow-aliases-wrap'); const sid = $(this).data('server'); const domain = $(this).data('domain'); if ($wrap.is(':visible')) { $wrap.slideUp(); return; } const $list = $row.find('.woocow-aliases-list').html('

Loading aliases…

'); $wrap.slideDown(); ajax('woocow_acct_aliases', { server_id: sid, domain }).done(res => { if (!res.success) { $list.html(`

${esc(res.data)}

`); return; } const aliases = res.data; if (!aliases.length) { $list.html('

No aliases for this domain yet.

'); return; } let html = ''; $list.html(html); }); }); $(document).on('click', '.wc-alias-add-btn', function () { $(this).closest('.woocow-aliases-wrap').find('.woocow-alias-create-form').slideToggle(); }); $(document).on('click', '.wc-alias-cancel', function () { $(this).closest('.woocow-alias-create-form').slideUp(); }); $(document).on('click', '.wc-alias-save', function () { const $form = $(this).closest('.woocow-alias-create-form'); const sid = $(this).data('server'); const domain = $(this).data('domain'); const addr = $form.find('.wc-alias-addr').val().trim(); const goto_ = $form.find('.wc-alias-goto').val().trim(); if (!addr || !goto_) { alert('Both alias and destination are required.'); return; } ajax('woocow_acct_alias_create', { server_id: sid, domain, address: addr, goto: goto_ }).done(res => { if (res.success) { // Refresh alias list $(this).closest('.woocow-mailbox-row').find('.wc-toggle-aliases').trigger('click'); setTimeout(() => { $(this).closest('.woocow-mailbox-row').find('.wc-toggle-aliases').trigger('click'); }, 300); $form.slideUp(); } else { alert('Error: ' + res.data); } }); }); $(document).on('click', '.wc-alias-del', function () { if (!confirm('Delete this alias?')) return; const $li = $(this).closest('li'); const sid = $(this).data('server'); const domain = $(this).data('domain'); const id = $(this).data('id'); ajax('woocow_acct_alias_delete', { server_id: sid, domain, alias_id: id }).done(res => { if (res.success) $li.fadeOut(300, function () { $(this).remove(); }); else alert('Delete failed: ' + res.data); }); }); // ── Create Mailbox ──────────────────────────────────────────────────────── $(document).on('click', '.woocow-create-mbox-btn', function () { const $panel = $(this).closest('.woocow-domain-panel'); $panel.find('.woocow-create-mbox-form').slideToggle(); }); $(document).on('click', '.wc-mbox-cancel', function () { $(this).closest('.woocow-create-mbox-form').slideUp(); }); $(document).on('click', '.wc-mbox-submit', function () { const $panel = $(this).closest('.woocow-domain-panel'); const sid = $panel.data('server-id'); const domain = $panel.data('domain'); const $form = $(this).closest('.woocow-create-mbox-form'); const $note = $form.find('.wc-mbox-notice'); const local = $form.find('.wc-mbox-local').val().trim(); const name = $form.find('.wc-mbox-name').val().trim(); const pass = $form.find('.wc-mbox-pass').val(); const pass2 = $form.find('.wc-mbox-pass2').val(); const quota = $form.find('.wc-mbox-quota').val(); if (!local || !pass) { $note.html('Username and password required.'); return; } if (pass !== pass2) { $note.html('Passwords do not match.'); return; } $note.text('Creating…'); ajax('woocow_acct_mailbox_create', { server_id: sid, domain, local_part: local, name, password: pass, password2: pass2, quota }).done(res => { if (res.success) { $note.html('✓ Mailbox created!'); $form.slideUp(); // Refresh mailbox list $panel.find('.woocow-load-mailboxes').trigger('click'); } else { $note.html(`${esc(res.data)}`); } }); }); // ── Change Password Modal ───────────────────────────────────────────────── $(document).on('click', '.wc-change-pw', function () { const sid = $(this).data('server'); const domain = $(this).data('domain'); const email = $(this).data('email'); $('#woocow-pw-server-id').val(sid); $('#woocow-pw-mailbox').val(email); $('#woocow-pw-email').text(email); $('#woocow-pw-new, #woocow-pw-new2').val(''); $('#woocow-pw-notice').text(''); $('#woocow-pw-modal').fadeIn(200); // Store domain on modal for verification $('#woocow-pw-modal').data('domain', domain); }); $('#woocow-pw-cancel').on('click', () => $('#woocow-pw-modal').fadeOut(200)); $(document).on('click', '#woocow-pw-modal', function (e) { if ($(e.target).is('#woocow-pw-modal')) $(this).fadeOut(200); }); $('#woocow-pw-save').on('click', function () { const sid = $('#woocow-pw-server-id').val(); const email = $('#woocow-pw-mailbox').val(); const domain = $('#woocow-pw-modal').data('domain'); const pass = $('#woocow-pw-new').val(); const pass2 = $('#woocow-pw-new2').val(); const $note = $('#woocow-pw-notice'); if (!pass || pass !== pass2) { $note.html('Passwords do not match or are empty.'); return; } $note.text('Updating…'); ajax('woocow_acct_mailbox_password', { server_id: sid, domain, email, password: pass, password2: pass2 }).done(res => { if (res.success) { $note.html('✓ Password updated!'); setTimeout(() => $('#woocow-pw-modal').fadeOut(200), 1500); } else { $note.html(`${esc(res.data)}`); } }); }); // ── Quarantine ──────────────────────────────────────────────────────────── $(document).on('click', '.woocow-load-quarantine', function () { const $panel = $(this).closest('.woocow-domain-panel'); const $wrap = $panel.find('.woocow-quarantine-wrap'); const $list = $panel.find('.woocow-quarantine-list'); const sid = $panel.data('server-id'); const domain = $panel.data('domain'); if ($wrap.is(':visible')) { $wrap.slideUp(); return; } $list.html('

Loading quarantine…

'); $wrap.slideDown(); ajax('woocow_acct_quarantine', { server_id: sid, domain }).done(res => { if (!res.success) { $list.html(`

${esc(res.data)}

`); return; } const msgs = res.data; if (!msgs.length) { $list.html('

No quarantined messages for this domain.

'); return; } let html = ``; msgs.forEach(m => { const date = new Date(m.created * 1000).toLocaleString(); const score = parseFloat(m.score).toFixed(1); const virus = m.virus_flag == 1 ? ' 🦠' : ''; html += ``; }); html += '
FromToSubjectScoreDate
${esc(m.sender)} ${esc(m.rcpt)} ${esc(m.subject)}${virus} ${score} ${esc(date)}
'; html += '

To release a message to your inbox, use the link in your quarantine notification email or via Webmail.

'; $list.html(html); }); }); $(document).on('click', '.wc-q-del', function () { if (!confirm('Permanently delete this quarantined message?')) return; const $row = $(this).closest('tr'); ajax('woocow_acct_quarantine_delete', { server_id: $(this).data('server'), domain: $(this).data('domain'), qid: $(this).data('id'), }).done(res => { if (res.success) $row.fadeOut(300, function () { $(this).remove(); }); else alert('Delete failed: ' + res.data); }); }); // ── Spam Score ──────────────────────────────────────────────────────────── $(document).on('click', '.wc-spam-score-btn', function () { const $row = $(this).closest('.woocow-mailbox-row'); const sid = $(this).data('server'); const domain = $(this).data('domain'); const email = $(this).data('email'); const score = $(this).data('score'); const $existing = $row.find('.woocow-spam-panel'); if ($existing.length) { $existing.slideToggle(); return; } $row.append(`
Spam Filter Threshold

Lower = stricter. Default is 5. Emails above this score go to spam/quarantine.

${parseFloat(score).toFixed(1)}
`); $row.find('.wc-spam-slider').on('input', function () { $row.find('.wc-spam-val').text(parseFloat($(this).val()).toFixed(1)); }); }); $(document).on('click', '.wc-spam-save', function () { const $panel = $(this).closest('.woocow-spam-panel'); const $note = $panel.find('.wc-spam-notice'); const score = $panel.find('.wc-spam-slider').val(); $note.text('Saving…'); ajax('woocow_acct_spam_score', { server_id: $(this).data('server'), domain: $(this).data('domain'), email: $(this).data('email'), spam_score: score, }).done(res => { if (res.success) $note.html('✓ Saved'); else $note.html(`${esc(res.data)}`); }); }); })(jQuery);