// Actually defined by templating in admin.html, this is just to avoid errors from tsc. var notifications_enabled: any; interface Invite { code?: string; expiresIn?: string; empty: boolean; remainingUses?: string; email?: string; usedBy?: Array>; created?: string; notifyExpiry?: boolean; notifyCreation?: boolean; profile?: string; } const emptyInvite = (): Invite => { return { code: "None", empty: true } as Invite; } function parseInvite(invite: Object): Invite { let inv: Invite = { code: invite["code"], empty: false, }; if (invite["email"]) { inv.email = invite["email"]; } let time = "" const f = ["days", "hours", "minutes"]; for (const i in f) { if (invite[f[i]] != 0) { time += `${invite[f[i]]}${f[i][0]} `; } } inv.expiresIn = `Expires in ${time.slice(0, -1)}`; if (invite["no-limit"]) { inv.remainingUses = "∞"; } else if ("remaining-uses" in invite) { inv.remainingUses = invite["remaining-uses"]; } if ("used-by" in invite) { inv.usedBy = invite["used-by"]; } if ("created" in invite) { inv.created = invite["created"]; } if ("notify-expiry" in invite) { inv.notifyExpiry = invite["notify-expiry"]; } if ("notify-creation" in invite) { inv.notifyCreation = invite["notify-creation"]; } if ("profile" in invite) { inv.profile = invite["profile"]; } return inv; } function setNotify(el: HTMLElement): void { let send = {}; let code: string; let notifyType: string; if (el.id.includes("Expiry")) { code = el.id.replace("_notifyExpiry", ""); notifyType = "notify-expiry"; } else if (el.id.includes("Creation")) { code = el.id.replace("_notifyCreation", ""); notifyType = "notify-creation"; } send[code] = {}; send[code][notifyType] = (el as HTMLInputElement).checked; _post("/setNotify", send, function (): void { if (this.readyState == 4 && this.status != 200) { (el as HTMLInputElement).checked = !(el as HTMLInputElement).checked; } }); } function genUsedBy(usedBy: Array>): string { let uB = ""; if (usedBy && usedBy.length != 0) { uB = ` Users created: `; for (const i in usedBy) { uB += ` ${usedBy[i][0]} ${usedBy[i][1]} `; } uB += `` } return uB; } function addItem(invite: Invite): void { const links = document.getElementById('invites'); const container = document.createElement('div') as HTMLDivElement; container.id = invite.code; const item = document.createElement('div') as HTMLDivElement; item.classList.add('list-group-item', 'd-flex', 'justify-content-between', 'd-inline-block'); let link = ""; let innerHTML = `None`; if (invite.empty) { item.innerHTML = ` ${innerHTML} `; container.appendChild(item); links.appendChild(container); return; } link = window.location.href.split('#')[0] + "invite/" + invite.code; innerHTML = ` ${invite.code.replace(/-/g, '-')} `; if (invite.email) { let email = invite.email; if (!invite.email.includes("Failed to send to")) { email = `Sent to ${email}`; } innerHTML += ` ${email} `; } innerHTML += ` ${invite.expiresIn} Delete `; item.innerHTML = innerHTML; container.appendChild(item); let profiles = ` Profile: `; let match = false; for (const i in availableProfiles) { let selected = ""; if (availableProfiles[i] == invite.profile) { selected = "selected"; match = true; } profiles += `${availableProfiles[i]}`; } if (!match) { profiles += ``; } profiles += ``; let dateCreated: string; if (invite.created) { dateCreated = `Created: ${invite.created}`; } let middle: string; if (notifications_enabled) { middle = ` Notify on: Expiry User creation `; } let right: string = genUsedBy(invite.usedBy) const dropdown = document.createElement('div') as HTMLDivElement; dropdown.id = `${CSS.escape(invite.code)}_collapse`; dropdown.classList.add("collapse"); dropdown.innerHTML = ` ${profiles} ${dateCreated} Remaining uses: ${invite.remainingUses} ${middle} ${right} `; container.appendChild(dropdown); links.appendChild(container); } function updateInvite(invite: Invite): void { document.getElementById(CSS.escape(invite.code) + "_expiry").textContent = invite.expiresIn; const remainingUses: any = document.getElementById(CSS.escape(invite.code) + "_remainingUses"); if (remainingUses) { remainingUses.textContent = `Remaining uses: ${invite.remainingUses}`; } document.getElementById(CSS.escape(invite.code) + "_usersCreated").innerHTML = genUsedBy(invite.usedBy); } // delete invite from DOM const hideInvite = (code: string): void => document.getElementById(CSS.escape(code)).remove(); // delete invite from jfa-go const deleteInvite = (code: string): void => _post("/deleteInvite", { "code": code }, function (): void { if (this.readyState == 4) { generateInvites(); } }); function generateInvites(empty?: boolean): void { if (empty) { document.getElementById('invites').textContent = ''; addItem(emptyInvite()); return; } _get("/getInvites", null, function (): void { if (this.readyState == 4) { let data = this.response; availableProfiles = data['profiles']; if (data['invites'] == null || data['invites'].length == 0) { document.getElementById('invites').textContent = ''; addItem(emptyInvite()); return; } let items = document.getElementById('invites').children; for (const i in data['invites']) { let match = false; const inv = parseInvite(data['invites'][i]); for (const x in items) { if (items[x].id == inv.code) { match = true; updateInvite(inv); break; } } if (!match) { addItem(inv); } } // second pass to check for expired invites items = document.getElementById('invites').children; for (let i = 0; i < items.length; i++) { let exists = false; for (const x in data['invites']) { if (items[i].id == data['invites'][x]['code']) { exists = true; break; } } if (!exists) { hideInvite(items[i].id); } } } }); } const addOptions = (length: number, el: HTMLSelectElement): void => { for (let v = 0; v <= length; v++) { const opt = document.createElement('option'); opt.textContent = ""+v; opt.value = ""+v; el.appendChild(opt); } el.value = "0"; }; function fixCheckboxes(): void { const send_to_address: Array = [document.getElementById('send_to_address') as HTMLInputElement, document.getElementById('send_to_address_enabled') as HTMLInputElement]; if (send_to_address[0] != null) { send_to_address[0].disabled = !send_to_address[1].checked; } const multiUseEnabled = document.getElementById('multiUseEnabled') as HTMLInputElement; const multiUseCount = document.getElementById('multiUseCount') as HTMLInputElement; const noUseLimit = document.getElementById('noUseLimit') as HTMLInputElement; multiUseCount.disabled = !multiUseEnabled.checked; noUseLimit.checked = false; noUseLimit.disabled = !multiUseEnabled.checked; } fixCheckboxes(); (document.getElementById('inviteForm') as HTMLFormElement).onsubmit = function (): boolean { const button = document.getElementById('generateSubmit') as HTMLButtonElement; button.disabled = true; button.innerHTML = ` Loading...`; let send = serializeForm('inviteForm'); send["remaining-uses"] = +send["remaining-uses"]; if (!send['multiple-uses'] || send['no-limit']) { delete send['remaining-uses']; } const sendToAddress: any = document.getElementById('send_to_address'); const sendToAddressEnabled: any = document.getElementById('send_to_address_enabled'); if (sendToAddress && sendToAddressEnabled) { send['email'] = send['send_to_address']; delete send['send_to_address']; delete send['send_to_address_enabled']; } _post("/generateInvite", send, function (): void { if (this.readyState == 4) { button.textContent = 'Generate'; button.disabled = false; generateInvites(); } }); return false; }; triggerTooltips(); function setProfile(select: HTMLSelectElement): void { if (!select.value) { return; } const invite = select.id.replace("profile_", ""); const send = { "invite": invite, "profile": select.value }; _post("/setProfile", send, function (): void { if (this.readyState == 4 && this.status != 200) { generateInvites(); } }); } function checkDuration(): void { const boxVals: Array = [+(document.getElementById("days") as HTMLSelectElement).value, +(document.getElementById("hours") as HTMLSelectElement).value, +(document.getElementById("minutes") as HTMLSelectElement).value]; const submit = document.getElementById('generateSubmit') as HTMLButtonElement; if (boxVals.reduce((a: number, b: number): number => a + b) == 0) { submit.disabled = true; } else { submit.disabled = false; } } const nE: Array = ["days", "hours", "minutes"]; for (const i in nE) { document.getElementById(nE[i]).addEventListener("change", checkDuration); }