canopy/www/js/channelSettings.js

257 lines
8.4 KiB
JavaScript

/*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 <https://www.gnu.org/licenses/>.*/
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();