Compare commits

...

4 commits

13 changed files with 142 additions and 82 deletions

View file

@ -24,6 +24,11 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. %>
</head> </head>
<body> <body>
<%- include('partial/navbar', {user}); %> <%- include('partial/navbar', {user}); %>
<div id="admin-panel-list-container">
<div id="admin-nav-list">
</div>
<div class="admin-panel-container-div">
<h1 class="panel-title"><%= unescape(channel.name) %> - Channel Settings</h1> <h1 class="panel-title"><%= unescape(channel.name) %> - Channel Settings</h1>
<div class="admin-panel-container-div"> <div class="admin-panel-container-div">
<%- include('partial/channelSettings/info.ejs', {unescape, channel}); %> <%- include('partial/channelSettings/info.ejs', {unescape, channel}); %>
@ -34,7 +39,8 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. %>
<%- include('partial/channelSettings/tokeCommandList.ejs'); %> <%- include('partial/channelSettings/tokeCommandList.ejs'); %>
<%- include('partial/channelSettings/emoteList.ejs'); %> <%- include('partial/channelSettings/emoteList.ejs'); %>
</div> </div>
<button href="javascript:" class="danger-button" id="chan-delete">Delete Channel</button> </div>
</div>
<footer> <footer>
<%- include('partial/scripts', {user}); %> <%- include('partial/scripts', {user}); %>
<script src="/js/popup/banPopup.js"></script> <script src="/js/popup/banPopup.js"></script>

View file

@ -13,14 +13,15 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License 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/>. %> along with this program. If not, see <https://www.gnu.org/licenses/>. %>
<div class="admin-list-div"> <div class="admin-list-div" id="chan-ban-list">
<h3 id="channel-ban-title">Channel Bans:</h3> <h3 id="channel-ban-title">Channel Bans:</h3>
<div class="control-prompt"> <div class="control-prompt">
<input placeholder="Add Username..." id="new-ban-input" class="control-prompt"> <input placeholder="Add Username..." id="new-ban-input" class="control-prompt">
<button id="new-ban-button" class="danger-button">Ban</button> <button id="new-ban-button" class="danger-button">Ban</button>
</div> </div>
<div class="dynamic-container"> <div class="dynamic-container resizable table-container">
<table id="admin-ban-list-table" class="admin-list-table"> <table id="admin-ban-list-table" class="admin-list-table">
<thead>
<tr class="admin-list-entry-title-row"> <tr class="admin-list-entry-title-row">
<td class="admin-list-entry-item admin-list-entry-img-title"><h3>Img</h3></td> <td class="admin-list-entry-item admin-list-entry-img-title"><h3>Img</h3></td>
<td id="admin-user-list-entry-id-title" class="admin-list-entry-item not-first-col"><h3>ID</h3></td> <td id="admin-user-list-entry-id-title" class="admin-list-entry-item not-first-col"><h3>ID</h3></td>
@ -30,6 +31,10 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. %>
<td id="channel-user-list-entry-expiration-date-title" class="admin-list-entry-item not-first-col"><h3>Expires</h3></td> <td id="channel-user-list-entry-expiration-date-title" class="admin-list-entry-item not-first-col"><h3>Expires</h3></td>
<td id="channel-user-list-entry-actions-title" class="admin-list-entry-item not-first-col">&nbsp;</td> <td id="channel-user-list-entry-actions-title" class="admin-list-entry-item not-first-col">&nbsp;</td>
</tr> </tr>
</thead>
<tbody>
</tbody>
<%# This is getting filled via AJAX since we need to refresh it when new users are added anywho. %> <%# This is getting filled via AJAX since we need to refresh it when new users are added anywho. %>
</table> </table>
</div> </div>

View file

@ -13,7 +13,7 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License 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/>. %> along with this program. If not, see <https://www.gnu.org/licenses/>. %>
<div id="emote-list-div" class="admin-list-div"> <div id="chan-emote-list" class="admin-list-div">
<h3>Emote List:</h3> <h3>Emote List:</h3>
<div class="control-prompt"> <div class="control-prompt">
<%# Probably not the cleanest way to do this but fuggit %> <%# Probably not the cleanest way to do this but fuggit %>
@ -23,6 +23,6 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. %>
<div class="control-prompt"> <div class="control-prompt">
<input placeholder="Emote Link..." id="new-emote-link-input" class="control-prompt"> <input placeholder="Emote Link..." id="new-emote-link-input" class="control-prompt">
</div> </div>
<div class="dynamic-container" id="emote-list"> <div class="dynamic-container resizable" id="emote-list">
</div> </div>
</div> </div>

View file

@ -13,7 +13,7 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License 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/>. %> along with this program. If not, see <https://www.gnu.org/licenses/>. %>
<div class="admin-list-div"> <div class="admin-list-div" id="chan-info-list">
<h3 id="channel-info-title">Channel Info:</h3> <h3 id="channel-info-title">Channel Info:</h3>
<div class="dynamic-container" id="channel-info-div"> <div class="dynamic-container" id="channel-info-div">
<span class="channel-info-span" id="channel-info-thumbnail-span"> <span class="channel-info-span" id="channel-info-thumbnail-span">

View file

@ -13,7 +13,7 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License 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/>. %> along with this program. If not, see <https://www.gnu.org/licenses/>. %>
<div class="admin-list-div"> <div class="admin-list-div" id="chan-perm-list">
<h3> Permissions:</h3> <h3> Permissions:</h3>
<div class="dynamic-container"> <div class="dynamic-container">
<form action="javascript:" class="admin-list-field"> <form action="javascript:" class="admin-list-field">

View file

@ -13,7 +13,7 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License 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/>. %> along with this program. If not, see <https://www.gnu.org/licenses/>. %>
<div class="admin-list-div"> <div class="admin-list-div" id="chan-settings-list">
<h3>Channel Preferences:</h3> <h3>Channel Preferences:</h3>
<div class="dynamic-container"> <div class="dynamic-container">
<form action="javascript:" class="admin-list-field"> <form action="javascript:" class="admin-list-field">
@ -45,7 +45,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. %>
<input type="radio" name="streamType" id="channel-preference-list-stream-type-hls" value="livehls" <% if(channel.settings["streamType"] == "livehls"){ %> checked <% }%> > <input type="radio" name="streamType" id="channel-preference-list-stream-type-hls" value="livehls" <% if(channel.settings["streamType"] == "livehls"){ %> checked <% }%> >
<label for="channel-preference-list-stream-type-hls">Self-Hosted (HLS)</label> <label for="channel-preference-list-stream-type-hls">Self-Hosted (HLS)</label>
</span> </span>
<input <% if(channel.settings["streamType"] != "livehls"){ %> disabled <%}%> id="channel-preference-list-stream-url" placeholder="Stream URL" value="<%= channel.settings["streamURL"] %>"> <input <% if(channel.settings["streamType"] != "livehls"){ %> disabled <%}%> id="channel-preference-list-stream-url" placeholder="HLS Stream URL" value="<%= channel.settings["streamURL"] %>">
</span> </span>
</span> </span>

View file

@ -13,12 +13,12 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License 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/>. %> along with this program. If not, see <https://www.gnu.org/licenses/>. %>
<div id="toke-command-list-div" class="admin-list-div"> <div id="chan-toke-list" class="admin-list-div">
<h3>Toke Command List:</h3> <h3>Toke Command List:</h3>
<div class="control-prompt"> <div class="control-prompt">
!<input placeholder="Add Command..." id="new-toke-command-input" class="control-prompt"> !<input placeholder="Add Command..." id="new-toke-command-input" class="control-prompt">
<button id="new-toke-command-button" class="positive-button">Add</button> <button id="new-toke-command-button" class="positive-button">Add</button>
</div> </div>
<div class="dynamic-container toke-command-list"> <div class="dynamic-container toke-command-list resizable">
</div> </div>
</div> </div>

View file

@ -13,7 +13,7 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License 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/>. %> along with this program. If not, see <https://www.gnu.org/licenses/>. %>
<div class="admin-list-div"> <div class="admin-list-div" id="chan-user-list">
<h3 id="channel-rank-title">Channel Ranks:</h3> <h3 id="channel-rank-title">Channel Ranks:</h3>
<sup id="channel-rank-sup">Users set to default channel rank 'user' will NOT be listed below.</sup> <sup id="channel-rank-sup">Users set to default channel rank 'user' will NOT be listed below.</sup>
<div class="control-prompt"> <div class="control-prompt">
@ -24,14 +24,18 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. %>
<% }); %> <% }); %>
</select> </select>
</div> </div>
<div class="dynamic-container"> <div class="dynamic-container resizable table-container">
<table class="admin-list-table"> <table class="admin-list-table" id="admin-rank-list-table">
<thead>
<tr class="admin-list-entry-title-row"> <tr class="admin-list-entry-title-row">
<td class="admin-list-entry-item admin-list-entry-img-title"><h3>Img</h3></td> <td class="admin-list-entry-item admin-list-entry-img-title"><h3>Img</h3></td>
<td id="admin-user-list-entry-id-title" class="admin-list-entry-item not-first-col"><h3>ID</h3></td> <td id="admin-user-list-entry-id-title" class="admin-list-entry-item not-first-col"><h3>ID</h3></td>
<td class="admin-list-entry-item not-first-col"><h3>Name</h3></td> <td class="admin-list-entry-item not-first-col"><h3>Name</h3></td>
<td id="channel-user-list-entry-rank-title" class="admin-list-entry-item not-first-col"><h3>Rank</h3></td> <td id="channel-user-list-entry-rank-title" class="admin-list-entry-item not-first-col"><h3>Rank</h3></td>
</tr> </tr>
</thead>
<tbody>
</tbody>
<%# This is getting filled via AJAX since we need to refresh it when new users are added anywho. %> <%# This is getting filled via AJAX since we need to refresh it when new users are added anywho. %>
</table> </table>
</div> </div>

View file

@ -47,7 +47,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. %>
<br> <br>
<br> <br>
<h2>Pros/Cons of WebRTC:</h2> <h2>Pros/Cons of WebRTC:</h2>
WebRTC connections come in two flavors, STUN and TURN. STUN uses an intermediary server, to make a connection through your firewall, to another established peer. For certain connections, some users, suchas those on a CGNAT, will require a TURN server to relay the connection. At the current moment, ourfore.st only supplies STUN servers, however we do plan on looking into TURN relay servers in the future. WebRTC connections come in two flavors, STUN and TURN. STUN uses an intermediary server, to make a connection through your firewall, to another established peer. Some users, such as those on a CGNAT, will require a TURN server to relay the connection.
<br> <br>
<br> <br>
This means that each viewer uses up part of a streamers bandwidth, comparitively to HLS, in which the streaming-server takes the load of multiple connections off of the streamers connection (assuming they're it's not hosted on the same connection.) Furthermore, WebRTC's video-chat roots prioritizes real-time communication over video/audio quality. That being said, WebRTC requires no extra setup, and no extra software other than this website and your browser. This means that each viewer uses up part of a streamers bandwidth, comparitively to HLS, in which the streaming-server takes the load of multiple connections off of the streamers connection (assuming they're it's not hosted on the same connection.) Furthermore, WebRTC's video-chat roots prioritizes real-time communication over video/audio quality. That being said, WebRTC requires no extra setup, and no extra software other than this website and your browser.

View file

@ -284,7 +284,7 @@ a.admin-list-entry-item{
border-bottom: 1px var(--accent1) solid; border-bottom: 1px var(--accent1) solid;
} }
#admin-nav-list button:not(.positive-button, :hover){ #admin-nav-list button:not(.positive-button, :hover, .danger-button){
background-color: var(--bg1); background-color: var(--bg1);
color: var(--accent1); color: var(--accent1);
} }

View file

@ -304,7 +304,7 @@ a.admin-list-entry-item{
border-bottom: 1px var(--accent1) solid; border-bottom: 1px var(--accent1) solid;
} }
#admin-nav-list button:not(.positive-button, :hover){ #admin-nav-list button:not(.positive-button, :hover, .danger-button){
background-image: var(--bg1-gradient); background-image: var(--bg1-gradient);
} }

View file

@ -27,7 +27,83 @@ class channelSettingsPage{
this.livestreamPreferences = new livestreamPreferences(this.channel); this.livestreamPreferences = new livestreamPreferences(this.channel);
this.tokeCommandList = new tokeCommandList(this.channel); this.tokeCommandList = new tokeCommandList(this.channel);
this.emoteList = new emoteList(this.channel); this.emoteList = new emoteList(this.channel);
this.deleteBtn = new deleteBtn(this.channel);
//Setup nav buttons
this.navButtons = new chanAdminNavButtons(this.channel);
}
}
class chanAdminNavButtons{
constructor(channel){
//Take down channel
this.channel = channel;
//Grab nav list
this.navList = document.querySelector("#admin-nav-list");
//Create empty map to do a holdem buttons
this.buttons = new Map();
//Build out options map
this.options = new Map([
["Channel Info", document.querySelector("#chan-info-list")],
["Ranked Users", document.querySelector("#chan-user-list")],
["Bans", document.querySelector("#chan-ban-list")],
["Preferences", document.querySelector("#chan-settings-list")],
["Permissions", document.querySelector("#chan-perm-list")],
["Toke Commands", document.querySelector("#chan-toke-list")],
["Emotes", document.querySelector("#chan-emote-list")],
["Delete Channel", null]
]);
//Render out buttons
this.renderButtons();
//Select the first option in the options map
this.displayOption(Array.from(this.options.keys())[0]);
}
renderButtons(){
//For erry list in the admin panel
for(const option of this.options.keys()){
//Create a button for it
const button = document.createElement('button');
button.innerText = option;
//If this aint the Delete Channel button
if(option != "Delete Channel"){
//Attatch an event listener to handle users clickin' der button
button.addEventListener('click',()=>{this.displayOption(option)});
}else{
//Attatch an event listener to blaire the fuckin' defcon five nukem alarm
button.addEventListener('click', () => {new deleteChannelPopup(this.channel)});
button.classList.add('danger-button');
}
//Drop button in the buttons map
this.buttons.set(option, button);
//Add that shit
this.navList.appendChild(button);
}
}
displayOption(selectedOption){
//For every option
for(const option of this.options.keys()){
//If this is the Delete Channel button
if(option == "Delete Channel"){
//ignorem
break;
}
//If we're on the selected option
if(option == selectedOption){
this.options.get(option).style.display = 'flex';
this.buttons.get(option).classList.add('positive-button');
}else{
this.options.get(option).style.display = 'none';
this.buttons.get(option).classList.remove('positive-button');
}
}
} }
} }
@ -131,7 +207,7 @@ class chanInfo{
class rankList{ class rankList{
constructor(channel){ constructor(channel){
this.channel = channel this.channel = channel
this.table = document.querySelector(".admin-list-table"); this.tbody = document.querySelector("#admin-rank-list-table tbody");
this.userPrompt = document.querySelector("#new-rank-input"); this.userPrompt = document.querySelector("#new-rank-input");
this.rankSelect = document.querySelector("#new-rank-select"); this.rankSelect = document.querySelector("#new-rank-select");
@ -186,7 +262,7 @@ class rankList{
const rankEnum = await utils.ajax.getRankEnum(); const rankEnum = await utils.ajax.getRankEnum();
//clear the table //clear the table
this.clearTable(); this.tbody.innerHTML = "";
//For each user in the list //For each user in the list
Object.entries(data).forEach((userAr) => { Object.entries(data).forEach((userAr) => {
@ -220,7 +296,7 @@ class rankList{
} }
//Generate row and append to table //Generate row and append to table
this.table.appendChild(utils.ux.newTableRow([ this.tbody.appendChild(utils.ux.newTableRow([
imgNode, imgNode,
user.id, user.id,
user.user, user.user,
@ -228,23 +304,12 @@ class rankList{
])); ]));
}); });
} }
clearTable(){
//get all non-title table rows
const rows = this.table.querySelectorAll("tr.gen-row");
//for each row
rows.forEach((row) => {
//The Lord Yeeteth, and The Lord Yoinketh away...
row.remove();
});
}
} }
class banList{ class banList{
constructor(channel){ constructor(channel){
this.channel = channel; this.channel = channel;
this.table = document.querySelector("#admin-ban-list-table"); this.tbody = document.querySelector("#admin-ban-list-table tbody");
this.banPrompt = document.querySelector("#new-ban-input"); this.banPrompt = document.querySelector("#new-ban-input");
this.banButton = document.querySelector("#new-ban-button"); this.banButton = document.querySelector("#new-ban-button");
@ -261,13 +326,6 @@ class banList{
this.updateList(data); this.updateList(data);
} }
clearList(){
const oldRows = this.table.querySelectorAll('tr.gen-row');
oldRows.forEach((row) => {
row.remove();
});
}
async ban(event){ async ban(event){
new chanBanUserPopup(this.channel, this.banPrompt.value, this.updateList.bind(this)); new chanBanUserPopup(this.channel, this.banPrompt.value, this.updateList.bind(this));
} }
@ -284,7 +342,8 @@ class banList{
updateList(bans){ updateList(bans){
//for each ban listed //for each ban listed
this.clearList(); this.tbody.innerHTML = "";
bans.forEach((ban)=>{ bans.forEach((ban)=>{
//Create IMG node //Create IMG node
const imgNode = document.createElement('img'); const imgNode = document.createElement('img');
@ -306,7 +365,7 @@ class banList{
const expirationString = ban.expirationDays < 0 ? "Never" : `${new Date(ban.expirationDate).toDateString()}<br>(${ban.daysUntilExpiration} day(s) left)`; const expirationString = ban.expirationDays < 0 ? "Never" : `${new Date(ban.expirationDate).toDateString()}<br>(${ban.daysUntilExpiration} day(s) left)`;
//Generate row and append to table //Generate row and append to table
this.table.appendChild(utils.ux.newTableRow([ this.tbody.appendChild(utils.ux.newTableRow([
imgNode, imgNode,
ban.user.id, ban.user.id,
ban.user.user, ban.user.user,
@ -659,21 +718,7 @@ class emoteList{
} }
} }
class deleteBtn{ class deleteChannelPopup{
constructor(channel){
this.channel = channel;
this.delete = document.querySelector("#chan-delete");
this.setupInput();
}
setupInput(){
this.delete.addEventListener('click', () => {new deleteAccountPopup(this.channel)});
}
}
class deleteAccountPopup{
constructor(channel){ constructor(channel){
this.channel = channel; this.channel = channel;
this.popup = new canopyUXUtils.popup("nukeChannel", true, this.asyncConstructor.bind(this)); this.popup = new canopyUXUtils.popup("nukeChannel", true, this.asyncConstructor.bind(this));

View file

@ -16,7 +16,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. -->
<link rel="stylesheet" type="text/css" href="/css/popup/delete.css"> <link rel="stylesheet" type="text/css" href="/css/popup/delete.css">
<h3 id="delete-channel-popup-title" class="popup-title">Delete Channel</h3> <h3 id="delete-channel-popup-title" class="popup-title">Delete Channel</h3>
<div> <div>
<p id="delete-channel-popup-content">WARNING: You are about to nuke channel '[CHANNEL]' off of the face of the fucking planet.<br> <p id="delete-channel-popup-content">WARNING: You are about to nuke the channel '[CHANNEL]' off of the face of the fucking planet.<br>
Enter '[CHANNEL]' below to confirm:</p> Enter '[CHANNEL]' below to confirm:</p>
<span id="delete-channel-popup-prompt-span"> <span id="delete-channel-popup-prompt-span">
<input type="text" id="delete-channel-popup-prompt"> <input type="text" id="delete-channel-popup-prompt">