Add global music player, invoicing/payment system, account subpages, mail account admin, and the qualityiron.vegas Jet 2.0 port
Jet interpreter (Tag.cpp, __call.cpp, __imap*.cpp/h, __smtpsend.cpp/h, __imapemptyfolder.cpp/h - new): assorted parser/tag fixes found across this work - a stray literal-tag-in-comment and backslash-quote parser corruption class, a dangling-pointer fix, a __call.cpp fd leak, IMAP folder-management tags, multi-account/per-host IMAP support, and a smtpsend Message-ID fix. barant.com site (jetc/barant-site/): - A site-wide persistent music player (header band, playlist/queue, stereo FFT EQ, session-persisted state) fed by new library/ ianslibrary/music song-list subpages. - /account split into info/phones/invoices subpages; a full invoicing and Square payment system (create/edit/copy/pay/email invoice); admin invoice management and mail-account management subpages. - /services split into overview/hosting/siptrunking/documents subpages, retiring the old standalone pages. - SIPPHONE.tag: a Jet 2.0 WebRTC softphone tag. - main.css/spa.js/email.js: the SPA loading indicator, the music player band styling, and assorted fixes accumulated alongside this work. qualityiron-site/: the qualityiron.vegas job/contractor/customer/ document management app, ported from its original Jet 1.4 codebase to Jet 2.0 as barant.coms APIServers second multi-tenant site. wcwc/wcwc.jet: the WCWC site Jet source (wcwc.jtc build output not included). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
905fbafa5a
commit
b8f7793773
406 files changed
+15803
-587
No files matched your search
@@ -0,0 +1,46 @@
|
||||
<include file="invoice.method">
|
||||
<br>
|
||||
<linkbutton page="editinvoice"><div class="button">Edit Invoice</div></linkbutton>
|
||||
<div style="margin-top: 10px; display: flex; align-items: center; gap: 6px;">
|
||||
<input type="email" id="mail_invoice_email" placeholder="recipient@example.com" style="width: 220px;">
|
||||
<button type="button" id="mail_invoice_btn" class="button">Mail Invoice</button>
|
||||
<span id="mail_invoice_status" style="font-size: 12px; color: var(--bond-text-dim);"></span>
|
||||
</div>
|
||||
<script>
|
||||
(function() {
|
||||
var btn = document.getElementById('mail_invoice_btn');
|
||||
var input = document.getElementById('mail_invoice_email');
|
||||
var status = document.getElementById('mail_invoice_status');
|
||||
if (!btn || !input || !status) return;
|
||||
btn.addEventListener('click', function() {
|
||||
var email = input.value.trim();
|
||||
if (!email) {
|
||||
status.textContent = 'Enter an e-mail address first.';
|
||||
status.style.color = '#a13a3a';
|
||||
return;
|
||||
}
|
||||
btn.disabled = true;
|
||||
status.textContent = 'Sending…';
|
||||
status.style.color = 'var(--bond-text-dim)';
|
||||
fetch('/admin/mail-invoice', {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin',
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
body: new URLSearchParams({ email: email }).toString()
|
||||
}).then(function(r) { return r.json(); }).then(function(res) {
|
||||
btn.disabled = false;
|
||||
if (res.ok) {
|
||||
status.textContent = 'Invoice emailed to ' + email + '.';
|
||||
status.style.color = '#6fb8c9';
|
||||
} else {
|
||||
status.textContent = res.error || 'Could not send the invoice.';
|
||||
status.style.color = '#a13a3a';
|
||||
}
|
||||
}).catch(function() {
|
||||
btn.disabled = false;
|
||||
status.textContent = 'Request failed. Please try again.';
|
||||
status.style.color = '#a13a3a';
|
||||
});
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
Reference in new issue
Block a user