// Substitution from jinja const cssFile = "{{ css_file }}"; // To grab theme preference function getCookie(cname) { let name = cname + "="; let decodedCookie = decodeURIComponent(document.cookie); let ca = decodedCookie.split(';'); for (let c of ca) { while(c.charAt(0) == ' ') { c = c.substring(1); } if (c.indexOf(name) == 0) { return c.substring(name.length, c.length); } } return ""; } // Used for theme change animation function whichTransitionEvent() { let t; let el = document.createElement('fakeelement'); let transitions = { 'transition': 'transitionend', 'OTransition': 'oTransitionEnd', 'MozTransition': 'transitionend', 'WebkitTransition': 'webkitTransitionEnd' }; for (t in transitions) { if (el.style[t] !== undefined) { return transitions[t]; } } } var transitionEndEvent = whichTransitionEvent(); // Toggles between light and dark themes function toggleCSS() { let cssEl = document.querySelectorAll('link[rel="stylesheet"][type="text/css"]')[0]; let href = "bs" + bsVersion; if (cssEl.href.includes(href + "-jf")) { href += ".css"; } else { href += "-jf.css"; } cssEl.href = href document.cookie = "css=" + href; } // Toggles between light and dark themes, but runs animation if necessary (dependent on window width for performance) var buttonWidth = 0; function toggleCSSAnim(el) { let switchToColor = window.getComputedStyle(document.body, null).backgroundColor; let maxWidth = 1500; if (window.innerWidth < maxWidth) { // Calculate minimum radius to cover whole screen let radius = Math.sqrt(Math.pow(window.innerWidth, 2) + Math.pow(window.innerHeight, 2)); let currentRadius = el.getBoundingClientRect().width / 2; let scale = radius / currentRadius; buttonWidth = window.getComputedStyle(el, null).width; document.body.classList.remove('smooth-transition'); el.style.transform = `scale(${scale})`; el.style.color = switchToColor; el.addEventListener(transitionEndEvent, function() { if (this.style.transform.length != 0) { toggleCSS(); this.style.removeProperty('transform'); document.body.classList.add('smooth-transition'); }; }, false); } else { toggleCSS(); el.style.color = switchToColor; } } var buttonColor = "custom"; // Predefined colors for 'theme' button if (cssFile.includes("jf")) { buttonColor = "rgb(255,255,255)"; } else if (cssFile == ('bs' + bsVersion + '.css')) { buttonColor = "rgb(16,16,16)"; } if (buttonColor != "custom") { let fakeButton = document.createElement('i'); fakeButton.classList.add('fa', 'fa-circle', 'circle'); fakeButton.style = `color: ${buttonColor}; margin-left: 0.4rem;`; fakeButton.id = "fakeButton"; let switchButton = document.createElement('button'); switchButton.classList.add('btn', 'btn-secondary'); switchButton.textContent = "Theme"; switchButton.onclick = function() { let fakeButton = document.getElementById('fakeButton'); toggleCSSAnim(fakeButton); }; let group = document.getElementById('headerButtons'); switchButton.appendChild(fakeButton); group.appendChild(switchButton); } {% if bsVersion == 5 %} function createModal(id, find = false) { if (find) { return bootstrap.Modal.getInstance(document.getElementById(id)); } return new bootstrap.Modal(document.getElementById(id)); } {% elif bsVersion == 4 %} let send_to_addess_enabled = document.getElementById('send_to_address_enabled'); if (typeof(send_to_address_enabled) != 'undefined') { send_to_address_enabled.classList.remove('form-check-input'); } let multiUseEnabled = document.getElementById('multiUseEnabled'); if (typeof(multiUseEnabled) != 'undefined') { multiUseEnabled.classList.remove('form-check-input'); } function createModal(id, find = false) { return { show: function() { return $('#' + id).modal('show'); }, hide: function() { return $('#' + id).modal('hide'); } }; } {% endif %} function triggerTooltips() { {% if bsVersion == 5 %} document.getElementById('settingsMenu').addEventListener('shown.bs.modal', function() { {% elif bsVersion == 4 %} $('#settingsMenu').on('shown.bs.modal', function() { {% endif %} // Hacky way to ensure anything dependent on checkbox state is disabled if necessary by just clicking them let checkboxes = document.getElementById('settingsMenu').querySelectorAll('input[type="checkbox"]'); for (checkbox of checkboxes) { checkbox.click(); checkbox.click(); } let tooltips = [].slice.call(document.querySelectorAll('a[data-toggle="tooltip"]')); tooltips.map(function(el) { {% if bsVersion == 5 %} return new bootstrap.Tooltip(el); {% elif bsVersion == 4 %} return $(el).tooltip(); {% endif %} }); }); } var loginModal = createModal('login'); var settingsModal = createModal('settingsMenu'); var userDefaultsModal = createModal('userDefaults'); var usersModal = createModal('users'); var restartModal = createModal('restartModal'); // Parsed invite: [, , <1: Empty invite (no delete/link), 0: Actual invite>, , , [], ] function parseInvite(invite, empty = false) { if (empty) { return ["None", "", 1]; } let i = [invite["code"], "", 0, invite["email"]]; let time = "" for (m of ["days", "hours", "minutes"]) { if (invite[m] != 0) { time += `${invite[m]}${m[0]} `; } } i[1] = `Expires in ${time.slice(0, -1)}`; if ('remaining-uses' in invite) { i[4] = invite['remaining-uses']; } if (invite['no-limit']) { i[4] = '∞'; } if ('used-by' in invite) { i[5] = invite['used-by']; } else { i[5] = []; } if ('created' in invite) { i[6] = invite['created']; } return i; } function addItem(parsedInvite) { let links = document.getElementById('invites'); let itemContainer = document.createElement('div'); itemContainer.id = parsedInvite[0]; let listItem = document.createElement('div'); // listItem.id = parsedInvite[0]; listItem.classList.add('list-group-item', 'd-flex', 'justify-content-between', 'd-inline-block'); let code = document.createElement('div'); code.classList.add('d-flex', 'align-items-center', 'font-monospace'); let codeLink = document.createElement('a'); codeLink.setAttribute('style', 'margin-right: 0.5rem;'); codeLink.textContent = parsedInvite[0].replace(/-/g, '-'); code.appendChild(codeLink); listItem.appendChild(code); let listRight = document.createElement('div'); let listText = document.createElement('span'); listText.id = parsedInvite[0] + '_expiry'; listText.setAttribute('style', 'margin-right: 1rem;'); listText.textContent = parsedInvite[1]; listRight.appendChild(listText); if (parsedInvite[2] == 0) { let inviteCode = window.location.href.split('#')[0] + 'invite/' + parsedInvite[0]; // codeLink.href = inviteCode; let copyButton = document.createElement('i'); copyButton.onclick = function() { toClipboard(inviteCode); }; copyButton.classList.add('fa', 'fa-clipboard', 'icon-button'); code.appendChild(copyButton); if (parsedInvite[3] !== undefined) { let sentTo = document.createElement('span'); sentTo.classList.add('text-muted'); sentTo.setAttribute('style', 'margin-left: 0.4rem; font-style: italic, font-size: 0.75rem;'); if (!parsedInvite[3].includes('Failed to send to')) { sentTo.textContent = "Sent to "; } sentTo.textContent += parsedInvite[3]; code.appendChild(sentTo); } let deleteButton = document.createElement('button'); deleteButton.onclick = function() { deleteInvite(parsedInvite[0]); }; deleteButton.classList.add('btn', 'btn-outline-danger'); deleteButton.textContent = "Delete"; listRight.appendChild(deleteButton); let dropButton = document.createElement('i'); dropButton.classList.add('fa', 'fa-angle-down', 'collapsed', 'icon-button', 'not-rotated'); dropButton.setAttribute('data-toggle', 'collapse'); dropButton.setAttribute('aria-expanded', 'false'); dropButton.setAttribute('data-target', '#' + CSS.escape(parsedInvite[0]) + '_collapse'); dropButton.onclick = function() { if (this.classList.contains('rotated')) { this.classList.remove('rotated'); this.classList.add('not-rotated'); } else { this.classList.remove('not-rotated'); this.classList.add('rotated'); } }; dropButton.setAttribute('style', 'margin-left: 1rem;'); listRight.appendChild(dropButton); } listItem.appendChild(listRight); itemContainer.appendChild(listItem); if (parsedInvite[2] == 0) { let itemDropdown = document.createElement('div'); itemDropdown.id = parsedInvite[0] + '_collapse'; itemDropdown.classList.add('collapse'); let dropdownContent = document.createElement('div'); dropdownContent.classList.add('container', 'row', 'align-items-start', 'card-body'); let dropdownLeft = document.createElement('div'); dropdownLeft.classList.add('col'); let leftList = document.createElement('ul'); leftList.classList.add('list-group', 'list-group-flush'); if (typeof(parsedInvite[6]) != 'undefined') { let createdDate = document.createElement('li'); createdDate.classList.add('list-group-item', 'py-1'); createdDate.textContent = `Created: ${parsedInvite[6]}`; leftList.appendChild(createdDate); } let remainingUses = document.createElement('li'); remainingUses.classList.add('list-group-item', 'py-1'); remainingUses.id = parsedInvite[0] + '_remainingUses'; remainingUses.textContent = `Remaining uses: ${parsedInvite[4]}`; leftList.appendChild(remainingUses); dropdownLeft.appendChild(leftList); dropdownContent.appendChild(dropdownLeft); let dropdownRight = document.createElement('div'); dropdownRight.id = parsedInvite[0] + '_usersCreated'; dropdownRight.classList.add('col'); if (parsedInvite[5].length != 0) { let userList = document.createElement('ul'); userList.classList.add('list-group', 'list-group-flush'); userList.innerHTML = '
  • Users created:
  • '; for (let user of parsedInvite[5]) { let li = document.createElement('li'); li.classList.add('list-group-item', 'py-1', 'disabled'); let username = document.createElement('div'); username.classList.add('d-flex', 'float-left'); username.textContent = user[0]; li.appendChild(username); let date = document.createElement('div'); date.classList.add('d-flex', 'float-right'); date.textContent = user[1]; li.appendChild(date); userList.appendChild(li); } dropdownRight.appendChild(userList); } dropdownContent.appendChild(dropdownRight); itemDropdown.appendChild(dropdownContent); itemContainer.appendChild(itemDropdown); } links.appendChild(itemContainer); } function updateInvite(parsedInvite) { let expiry = document.getElementById(parsedInvite[0] + '_expiry'); expiry.textContent = parsedInvite[1]; let remainingUses = document.getElementById(parsedInvite[0] + '_remainingUses'); if (remainingUses) { remainingUses.textContent = `Remaining uses: ${parsedInvite[4]}`; } if (parsedInvite[5].length != 0) { let usersCreated = document.getElementById(parsedInvite[0] + '_usersCreated'); let dropdownRight = document.createElement('div'); dropdownRight.id = parsedInvite[0] + '_usersCreated'; dropdownRight.classList.add('col'); let userList = document.createElement('ul'); userList.classList.add('list-group', 'list-group-flush'); userList.innerHTML = '
  • Users created:
  • '; for (let user of parsedInvite[5]) { let li = document.createElement('li'); li.classList.add('list-group-item', 'py-1', 'disabled'); let username = document.createElement('div'); username.classList.add('d-flex', 'float-left'); username.textContent = user[0]; li.appendChild(username); let date = document.createElement('div'); date.classList.add('d-flex', 'float-right'); date.textContent = user[1]; li.appendChild(date); userList.appendChild(li); } dropdownRight.appendChild(userList); usersCreated.replaceWith(dropdownRight); } } // delete from list on page function removeInvite(code) { let item = document.getElementById(code); item.parentNode.removeChild(item); } function generateInvites(empty = false) { if (empty === false) { let req = new XMLHttpRequest(); req.open("GET", "/getInvites", true); req.setRequestHeader("Authorization", "Basic " + btoa(window.token + ":")); req.responseType = 'json'; req.onreadystatechange = function() { if (this.readyState == 4) { var data = this.response; if (data['invites'].length == 0) { document.getElementById('invites').textContent = ''; addItem(parseInvite([], true)); } else { for (let invite of data['invites']) { let match = false; let items = document.getElementById('invites').children; for (let item of items) { if (item.id == invite['code']) { match = true; updateInvite(parseInvite(invite)); } } if (match == false) { addItem(parseInvite(invite)); } } let items = document.getElementById('invites').children; for (let item of items) { var exists = false; for (let invite of data['invites']) { if (item.id == invite['code']) { exists = true; } } if (exists == false) { removeInvite(item.id); } } } } }; req.send(); } else if (empty === true) { document.getElementById('invites').textContent = ''; addItem(parseInvite([], true)); } } // actually delete invite function deleteInvite(code) { let send = JSON.stringify({ "code": code }); let req = new XMLHttpRequest(); req.open("POST", "/deleteInvite", true); req.setRequestHeader("Authorization", "Basic " + btoa(window.token + ":")); req.setRequestHeader('Content-Type', 'application/json; charset=UTF-8'); req.onreadystatechange = function() { if (this.readyState == 4) { generateInvites(); } }; req.send(send); } // Add numbers to select element function addOptions(length, selectElement) { for (let v = 0; v <= length; v++) { let opt = document.createElement('option'); opt.textContent = v; opt.value = v; selectElement.appendChild(opt); } } function toClipboard(str) { const el = document.createElement('textarea'); el.value = str; el.setAttribute('readOnly', ''); el.style.position = 'absolute'; el.style.left = '-9999px'; document.body.appendChild(el); const selected = document.getSelection().rangeCount > 0 ? document.getSelection().getRangeAt(0) : false; el.select(); document.execCommand('copy'); document.body.removeChild(el); if (selected) { document.getSelection().removeAllRanges(); document.getSelection().addRange(selected); } } function fixCheckboxes() { let send_to_address = [document.getElementById('send_to_address'), document.getElementById('send_to_address_enabled')] if (send_to_address[0] != null) { send_to_address[0].disabled = !send_to_address[1].checked; } let multiUseEnabled = document.getElementById('multiUseEnabled'); let multiUseCount = document.getElementById('multiUseCount'); let noUseLimit = document.getElementById('noUseLimit'); multiUseCount.disabled = !multiUseEnabled.checked; noUseLimit.checked = false; noUseLimit.disabled = !multiUseEnabled.checked; } fixCheckboxes(); document.getElementById('inviteForm').onsubmit = function() { let button = document.getElementById('generateSubmit'); button.disabled = true; button.innerHTML = '' + 'Loading...'; send_object = serializeForm('inviteForm'); if (!send_object['multiple-uses'] || send_object['no-limit']) { delete send_object['remaining-uses']; } if (document.getElementById('send_to_address') != null) { if (send_object['send_to_address_enabled']) { send_object['email'] = send_object['send_to_address']; delete send_object['send_to_address']; delete send_object['send_to_address_enabled']; } } let send = JSON.stringify(send_object); let req = new XMLHttpRequest(); req.open("POST", "/generateInvite", true); req.setRequestHeader("Authorization", "Basic " + btoa(window.token + ":")); req.setRequestHeader('Content-Type', 'application/json; charset=UTF-8'); req.onreadystatechange = function() { if (this.readyState == 4) { button.textContent = 'Generate'; button.disabled = false; generateInvites(); } }; req.send(send); return false; }; document.getElementById('loginForm').onsubmit = function() { window.token = ""; let details = serializeForm('loginForm'); let errorArea = document.getElementById('loginErrorArea'); errorArea.textContent = ''; let button = document.getElementById('loginSubmit'); button.disabled = true; button.innerHTML = '' + 'Loading...'; let req = new XMLHttpRequest(); req.responseType = 'json'; req.onreadystatechange = function() { if (this.readyState == 4) { if (this.status == 401) { button.disabled = false; button.textContent = 'Login'; let wrongPassword = document.createElement('div'); wrongPassword.classList.add('alert', 'alert-danger'); wrongPassword.setAttribute('role', 'alert'); wrongPassword.textContent = "Incorrect username or password."; errorArea.appendChild(wrongPassword); } else { const data = this.response; window.token = data['token']; generateInvites(); const interval = setInterval(function() { generateInvites(); }, 60 * 1000); let day = document.getElementById('days'); addOptions(30, day); day.selected = "0"; let hour = document.getElementById('hours'); addOptions(24, hour); hour.selected = "0"; let minutes = document.getElementById('minutes'); addOptions(59, minutes); minutes.selected = "30"; loginModal.hide(); } } }; req.open("GET", "/getToken", true); req.setRequestHeader("Authorization", "Basic " + btoa(details['username'] + ":" + details['password'])); req.send(); return false; }; document.getElementById('openDefaultsWizard').onclick = function() { this.disabled = true this.innerHTML = '' + 'Loading...'; let req = new XMLHttpRequest(); req.responseType = 'json'; req.open("GET", "/getUsers", true); req.setRequestHeader("Authorization", "Basic " + btoa(window.token + ":")); req.onreadystatechange = function() { if (this.readyState == 4) { if (this.status == 200) { let users = req.response['users']; let radioList = document.getElementById('defaultUserRadios'); radioList.textContent = ''; if (document.getElementById('setDefaultUser')) { document.getElementById('setDefaultUser').remove(); } let first = true; for (user of users) { let radio = document.createElement('div'); radio.classList.add('radio'); if (first) { const checked = 'checked'; first = false; } else { const checked = ''; }; radio.innerHTML = ``; radioList.appendChild(radio); } let button = document.getElementById('openDefaultsWizard'); button.disabled = false; button.innerHTML = 'Set new account defaults'; let submitButton = document.getElementById('storeDefaults'); submitButton.disabled = false; submitButton.textContent = 'Submit'; if (submitButton.classList.contains('btn-success')) { submitButton.classList.remove('btn-success'); submitButton.classList.add('btn-primary'); } else if (submitButton.classList.contains('btn-danger')) { submitButton.classList.remove('btn-danger'); submitButton.classList.add('btn-primary'); } settingsModal.hide(); userDefaultsModal.show(); } } }; req.send(); }; document.getElementById('storeDefaults').onclick = function () { this.disabled = true; this.innerHTML = '' + 'Loading...'; let button = document.getElementById('storeDefaults'); let radios = document.getElementsByName('defaultRadios'); for (let radio of radios) { if (radio.checked) { let data = { 'username': radio.id.slice(8), 'homescreen': false}; if (document.getElementById('storeDefaultHomescreen').checked) { data['homescreen'] = true; } let req = new XMLHttpRequest(); req.open("POST", "/setDefaults", true); req.setRequestHeader("Authorization", "Basic " + btoa(window.token + ":")); req.setRequestHeader('Content-Type', 'application/json; charset=UTF-8'); req.onreadystatechange = function() { if (this.readyState == 4) { if (this.status == 200 || this.status == 204) { button.textContent = "Success"; if (button.classList.contains('btn-danger')) { button.classList.remove('btn-danger'); } else if (button.classList.contains('btn-primary')) { button.classList.remove('btn-primary'); } button.classList.add('btn-success'); button.disabled = false; setTimeout(function() { userDefaultsModal.hide(); }, 1000); } else { button.textContent = "Failed"; button.classList.remove('btn-primary'); button.classList.add('btn-danger'); setTimeout(function() { let button = document.getElementById('storeDefaults'); button.textContent = "Submit"; button.classList.remove('btn-danger'); button.classList.add('btn-primary'); button.disabled = false; }, 1000); } } }; req.send(JSON.stringify(data)); } } }; document.getElementById('openUsers').onclick = function () { this.disabled = true; this.innerHTML = '' + 'Loading...'; let req = new XMLHttpRequest(); req.open("GET", "/getUsers", true); req.responseType = 'json'; req.setRequestHeader("Authorization", "Basic " + btoa(window.token + ":")); req.onreadystatechange = function() { if (this.readyState == 4) { if (this.status == 200) { let list = document.getElementById('userList'); list.textContent = ''; if (document.getElementById('saveUsers')) { document.getElementById('saveUsers').remove(); } let users = req.response['users']; for (let user of users) { let entry = document.createElement('div'); entry.classList.add('form-group', 'list-group-item', 'py-1'); entry.id = 'user_' + user['name']; let label = document.createElement('label'); label.classList.add('d-inline-block'); label.setAttribute('for', 'address_' + user['email']); label.textContent = user['name']; entry.appendChild(label); let address = document.createElement('input'); address.setAttribute('type', 'email'); address.readOnly = true; address.classList.add('form-control-plaintext', 'text-muted', 'd-inline-block', 'addressText'); address.id = 'address_' + user['email']; if (typeof(user['email']) != 'undefined') { address.value = user['email']; address.setAttribute('style', 'width: auto; margin-left: 2%;'); } let editButton = document.createElement('i'); editButton.classList.add('fa', 'fa-edit', 'd-inline-block', 'icon-button'); editButton.setAttribute('style', 'margin-left: 2%;'); editButton.onclick = function() { this.classList.remove('fa', 'fa-edit'); let addressElement = this.parentNode.getElementsByClassName('form-control-plaintext')[0]; addressElement.classList.remove('form-control-plaintext', 'text-muted'); addressElement.classList.add('form-control'); addressElement.readOnly = false; if (addressElement.value == '') { addressElement.placeholder = 'Email Address'; address.setAttribute('style', 'width: auto; margin-left: 2%;'); } if (document.getElementById('saveUsers') == null) { let footer = document.getElementById('userFooter') let saveUsers = document.createElement('input'); saveUsers.classList.add('btn', 'btn-primary'); saveUsers.setAttribute('type', 'button'); saveUsers.value = 'Save Changes'; saveUsers.id = 'saveUsers'; saveUsers.onclick = function() { let send = {} let entries = document.getElementById('userList').children; for (let entry of entries) { if (typeof(entry.getElementsByTagName('input')[0]) != 'undefined') { const name = entry.id.replace(/user_/g, ''); const address = entry.getElementsByTagName('input')[0].value; send[name] = address; } } send = JSON.stringify(send); let req = new XMLHttpRequest(); req.open("POST", "/modifyUsers", true); req.setRequestHeader("Authorization", "Basic " + btoa(window.token + ":")); req.setRequestHeader('Content-Type', 'application/json; charset=UTF-8'); req.onreadystatechange = function() { if (this.readyState == 4) { if (this.status == 200 || this.status == 204) { usersModal.hide(); } } }; req.send(send); }; footer.appendChild(saveUsers); } }; entry.appendChild(editButton); entry.appendChild(address); list.appendChild(entry); }; let button = document.getElementById('openUsers'); button.disabled = false; button.innerHTML = 'Users '; settingsModal.hide(); usersModal.show(); } } }; req.send(); }; generateInvites(empty = true); loginModal.show(); var config = {}; var modifiedConfig = {}; document.getElementById('openSettings').onclick = function () { let req = new XMLHttpRequest(); req.open("GET", "/getConfig", true); req.responseType = 'json'; req.setRequestHeader("Authorization", "Basic " + btoa(window.token + ":")); req.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { let settingsList = document.getElementById('settingsList'); settingsList.textContent = ''; config = this.response; for (let section of Object.keys(config)) { let sectionCollapse = document.createElement('div'); sectionCollapse.classList.add('collapse'); sectionCollapse.id = section; let sectionTitle = config[section]['meta']['name']; let sectionDescription = config[section]['meta']['description']; let entryListID = section + '_entryList'; let sectionFooter = section + '_footer'; let innerCollapse = `
    ${sectionDescription}
    `; sectionCollapse.innerHTML = innerCollapse; for (var entry of Object.keys(config[section])) { if (entry != 'meta') { let entryName = config[section][entry]['name']; let required = false; if (config[section][entry]['required']) { entryName += ' *'; required = true; } if (config[section][entry]['requires_restart']) { entryName += ' R'; } if (config[section][entry].hasOwnProperty('description')) { let tooltip = ` `; entryName += ' '; entryName += tooltip; }; let entryValue = config[section][entry]['value']; let entryType = config[section][entry]['type']; let entryGroup = document.createElement('div'); if (entryType == 'bool') { entryGroup.classList.add('form-check'); if (entryValue.toString() == 'true') { var checked = true; } else { var checked = false; } entryGroup.innerHTML = ` `; entryGroup.getElementsByClassName('form-check-input')[0].required = required; entryGroup.getElementsByClassName('form-check-input')[0].checked = checked; entryGroup.getElementsByClassName('form-check-input')[0].onclick = function() { var state = this.checked; for (var sect of Object.keys(config)) { for (var ent of Object.keys(config[sect])) { if ((sect + '_' + config[sect][ent]['depends_true']) == this.id) { document.getElementById(sect + '_' + ent).disabled = !state; } else if ((sect + '_' + config[sect][ent]['depends_false']) == this.id) { document.getElementById(sect + '_' + ent).disabled = state; } } } }; } else if ((entryType == 'text') || (entryType == 'email') || (entryType == 'password') || (entryType == 'number')) { entryGroup.classList.add('form-group'); entryGroup.innerHTML = ` `; entryGroup.getElementsByClassName('form-control')[0].required = required; } else if (entryType == 'select') { entryGroup.classList.add('form-group'); let entryOptions = config[section][entry]['options']; let innerGroup = ` '; entryGroup.innerHTML = innerGroup; entryGroup.getElementsByClassName('form-control')[0].required = required; } sectionCollapse.getElementsByClassName(entryListID)[0].appendChild(entryGroup); } } let sectionButton = document.createElement('button'); sectionButton.setAttribute('type', 'button'); sectionButton.classList.add('list-group-item', 'list-group-item-action'); sectionButton.appendChild(document.createTextNode(sectionTitle)); sectionButton.id = section + '_button'; sectionButton.setAttribute('data-toggle', 'collapse'); sectionButton.setAttribute('data-target', '#' + section); settingsList.appendChild(sectionButton); settingsList.appendChild(sectionCollapse); } } }; req.send(); settingsModal.show(); } triggerTooltips(); function sendConfig(modalId) { let modal = document.getElementById(modalId); let send = JSON.stringify(modifiedConfig); let req = new XMLHttpRequest(); req.open("POST", "/modifyConfig", true); req.setRequestHeader("Authorization", "Basic " + btoa(window.token + ":")); req.setRequestHeader('Content-Type', 'application/json; charset=UTF-8'); req.onreadystatechange = function() { if (this.readyState == 4) { if (this.status == 200 || this.status == 204) { createModal(modalId, true).hide(); if (modalId != 'settingsMenu') { settingsModal.hide(); } } } }; req.send(send); } document.getElementById('settingsSave').onclick = function() { modifiedConfig = {}; var restart_setting_changed = false; var settings_changed = false; for (let section of Object.keys(config)) { for (let entry of Object.keys(config[section])) { if (entry != 'meta') { let entryID = section + '_' + entry; let el = document.getElementById(entryID); if (el.type == 'checkbox') { var value = el.checked.toString(); } else { var value = el.value.toString(); } if (value != config[section][entry]['value'].toString()) { if (!modifiedConfig.hasOwnProperty(section)) { modifiedConfig[section] = {}; } modifiedConfig[section][entry] = value; settings_changed = true; if (config[section][entry]['requires_restart']) { restart_setting_changed = true; } } } } } if (restart_setting_changed) { document.getElementById('applyRestarts').onclick = function(){sendConfig('restartModal');}; settingsModal.hide(); restartModal.show(); } else if (settings_changed) { sendConfig('settingsMenu'); } else { settingsModal.hide(); } }