/*Canopy - The next generation of stoner streaming software Copyright (C) 2024 Rainbownapkin and the TTN Community This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see .*/ class channelSettingsPage{ constructor(){ //Get channel name off of the URL this.channel = window.location.pathname.slice(3).replace('/settings',''); //Instantiate UX handling objects, making sure to pass the channel name. this.deleteBtn = new deleteBtn(this.channel); this.rankList = new rankList(this.channel); this.prefrenceList = new prefrenceList(this.channel); this.permList = new permList(this.channel); } } class rankList{ constructor(channel){ this.channel = channel this.table = document.querySelector(".admin-list-table"); this.userPrompt = document.querySelector("#new-rank-input"); this.rankSelect = document.querySelector("#new-rank-select"); //Load the userlist and setup input this.loadList(); this.setupInput(); } setupInput(){ this.userPrompt.addEventListener("keydown", this.submitNewRank.bind(this)); } resetInput(){ //These change every time the table is refreshed, so we should reset the property as well. this.inputs = document.querySelectorAll(".channel-rank-select"); this.inputs.forEach((input) => { input.addEventListener("change", this.submitUpdate.bind(this)); }); } async loadList(){ const list = await utils.ajax.getChannelRank(this.channel); this.updateList(list); } async submitNewRank(event){ if(event.key != "Enter" && event.key != null){ //Bail out if we didn't hit enter return; } //Send new rank this.submitUserRank(this.userPrompt.value, this.rankSelect.value); //Clear out prompt this.userPrompt.value = ""; } async submitUpdate(event){ const user = event.target.id.replace("channel-rank-select-",""); const rank = event.target.value; await this.submitUserRank(user, rank); } async submitUserRank(user, rank){ await this.updateList(await utils.ajax.setChannelRank(this.channel, user, rank)); } async updateList(data){ //If no data if(!data){ //Do not pass go, do not collect $200 return; } //Get rank of logged in user const curName = document.querySelector("#username").textContent const curUser = data[curName]; const rankEnum = await utils.ajax.getRankEnum(); //clear the table this.clearTable(); Object.entries(data).forEach((userAr) => { //pull user object from entry array const user = userAr[1]; //Create entry row const entryRow = document.createElement('tr'); entryRow.classList.add("admin-list-entry"); //Create IMG cell const imgCell = document.createElement('td') imgCell.classList.add("admin-list-entry","admin-list-entry-item"); //Create IMG node inside of IMG cell const imgNode = document.createElement('img'); imgNode.classList.add("admin-list-entry","admin-list-entry-item"); imgNode.src = user.img; //append Img Node to Img Cell imgCell.appendChild(imgNode); //Create ID cell const idCell = document.createElement('td'); idCell.classList.add("admin-list-entry","admin-list-entry-item","admin-list-entry-not-first-col"); idCell.innerHTML = user.id; //Create Name cell const nameCell = document.createElement('td'); nameCell.classList.add("admin-list-entry","admin-list-entry-item","admin-list-entry-not-first-col"); nameCell.innerHTML = user.user; //Create Rank cell const rankCell = document.createElement('td'); rankCell.classList.add("admin-list-entry","admin-list-entry-item","admin-list-entry-not-first-col"); //If the listed user rank is equal or higher than the signed-in user if(rankEnum.indexOf(user.rank) >= rankEnum.indexOf(curUser.rank)){ rankCell.innerHTML = user.rank; }else{ //Create rank select const rankSelect = document.createElement('select'); rankSelect.id = `channel-rank-select-${user.user}` rankSelect.classList.add("channel-rank-select") //for each rank in the enum rankEnum.slice().reverse().forEach((rank) => { //Create an option for the given rank const rankOption = document.createElement('option'); rankOption.value = rank; rankOption.innerHTML = rank; rankOption.selected = user.rank == rank; rankSelect.appendChild(rankOption); }); //Set value to current user rank and append it to Rank Cell rankCell.appendChild(rankSelect); } //Append cells to row entryRow.appendChild(imgCell); entryRow.appendChild(idCell); entryRow.appendChild(nameCell); entryRow.appendChild(rankCell); //Append row to table this.table.appendChild(entryRow); //reset input events this.resetInput(); }); } clearTable(){ //get all non-title table rows const rows = this.table.querySelectorAll("tr.admin-list-entry"); //for each row rows.forEach((row) => { //The Lord Yeeteth, and The Lord Yoinketh away... row.remove(); }); } } class prefrenceList{ constructor(channel){ this.channel = channel; this.inputs = document.querySelectorAll(".channel-preference-list-item"); } setupInput(){ this.inputs.forEach((input) => { input.addEventListener("change", this.submitUpdate.bind(this)); }); } async submitUpdate(event){ const key = event.target.id.replace("channel-preference-",""); const value = event.target.checked; const settingsMap = new Map([ [key, value] ]); this.handleUpdate(await utils.ajax.setChannelSetting(this.channel, settingsMap), event.target, key); } handleUpdate(data, target, key){ if(data){ target = data[key]; } } } class deleteBtn{ constructor(channel){ this.channel = channel; this.delete = document.querySelector("#channel-delete"); this.delete.addEventListener('click', this.promptDelete.bind(this)); } promptDelete(){ var confirm = window.prompt(`Warning: You are about to nuke ${this.channel} off of the face of the fucking planet, no taksie-backsies. \n \n Type in ${this.channel} to confirm.`); this.deleteChannel(confirm); } async deleteChannel(confirm){ if(this.channel === confirm){ utils.ajax.deleteChannel(this.channel, confirm); } } } class permList{ constructor(channel){ this.channel = channel this.inputs = document.querySelectorAll(".channel-perm-select"); this.setupInput(); } setupInput(){ this.inputs.forEach((input) => { input.addEventListener("change", this.submitUpdate.bind(this)); }); } async submitUpdate(event){ const key = event.target.id.replace("admin-perm-list-rank-select-",""); const value = event.target.value; const permMap = new Map([ [key, value] ]); this.handleUpdate(await utils.ajax.setChannelPermissions(this.channel, permMap), event.target, key); } handleUpdate(data, target, key){ target.value = data[key]; } } new channelSettingsPage();