From 41d0302dede8957351cd61ef211a8d6761e967fe Mon Sep 17 00:00:00 2001 From: rainbow napkin Date: Thu, 19 Dec 2024 22:48:23 -0500 Subject: [PATCH] Finished up with emote management pane in adminPanel page. --- src/validators/emoteValidator.js | 2 +- www/css/adminPanel.css | 44 +++++++++++++++ www/js/adminPanel.js | 91 ++++++++++++++++++++++++++++---- 3 files changed, 126 insertions(+), 11 deletions(-) diff --git a/src/validators/emoteValidator.js b/src/validators/emoteValidator.js index 74edeef..b7b9655 100644 --- a/src/validators/emoteValidator.js +++ b/src/validators/emoteValidator.js @@ -18,6 +18,6 @@ along with this program. If not, see .*/ const { check } = require('express-validator'); module.exports = { - name: (field = 'name') => check(field).escape().trim().isAlphanumeric().isLength({min: 1, max: 30}), + name: (field = 'name') => check(field).escape().trim().isAlphanumeric().isLength({min: 1, max: 14}), link: (field = 'link') => check(field).trim().isURL() } \ No newline at end of file diff --git a/www/css/adminPanel.css b/www/css/adminPanel.css index 6a0f176..ab577d8 100644 --- a/www/css/adminPanel.css +++ b/www/css/adminPanel.css @@ -129,4 +129,48 @@ p.toke-command-list{ i.toke-command-list{ margin: 0.2em; +} + +#emote-list-div{ + height: 30vh; +} + +#emote-list{ + display: grid; + grid-template-columns: repeat(auto-fit, minmax(10em, 1fr)); + padding: 1em; + overflow-y: auto; + justify-items: center; +} + +div.emote-list-emote{ + height: 100%; + width: fit-content; + display: flex; + flex-direction: column; +} + +span.emote-list-title{ + display: flex; + flex-direction: row; + position: relative; + width: 100%; + margin-top: 0.5em; +} + +p.emote-list-title{ + margin: 0 1.5em; + flex: 1; + text-align: center; +} + +i.emote-list-delete{ + position: absolute; + right: 0; +} + +.emote-list-media{ + max-height: 8em; + max-width: 10em; + margin: auto; } \ No newline at end of file diff --git a/www/js/adminPanel.js b/www/js/adminPanel.js index 1e88f40..57fbe1d 100644 --- a/www/js/adminPanel.js +++ b/www/js/adminPanel.js @@ -519,13 +519,53 @@ class adminTokeCommandList{ class adminEmoteList{ constructor(){ - this.linkPrompt = document.querySelector('new-emote-link-input'); - this.namePrompt = document.querySelector('new-emote-link-input'); + this.linkPrompt = document.querySelector('#new-emote-link-input'); + this.namePrompt = document.querySelector('#new-emote-name-input'); + this.addButton = document.querySelector('#new-emote-button'); this.emoteList = document.querySelector('#emote-list'); + //Setup input + this.setupInput(); + + //Pull and render emote list this.updateList(); } + setupInput(){ + this.addButton.addEventListener('click', this.addEmote.bind(this)); + } + + async deleteEmote(event){ + //Strip name from element id + const name = event.target.id.replace('emote-list-delete-',''); + + console.log(name); + + //Delete emote and pull list + const list = await adminUtil.deleteEmote(name); + + //If we received a list + if(list != null){ + //Pass updated liste to renderEmoteList function instead of pulling it twice + this.renderEmoteList(list); + } + } + + async addEmote(event){ + //Add emote to list and ingest returned updates list + const list = await adminUtil.addEmote(this.namePrompt.value, this.linkPrompt.value); + + //If we received a list + if(list != null){ + //Pass updated liste to renderEmoteList function instead of pulling it twice + this.renderEmoteList(list); + + //Clear out the prompts + this.namePrompt.value = ''; + this.linkPrompt.value = ''; + } + } + async updateList(){ const list = await adminUtil.getEmotes(); this.renderEmoteList(list); @@ -537,30 +577,61 @@ class adminEmoteList{ //For each emote in the list list.forEach((emote) => { - const emoteSpan = document.createElement('span'); - emoteSpan.classList.add('emote-list-emote'); + //Create span to hold emote + const emoteDiv = document.createElement('div'); + emoteDiv.classList.add('emote-list-emote'); //If the emote is an image if(emote.type == 'image'){ //Create image node var emoteMedia = document.createElement('img'); - //add link as source - emoteMedia.src = emote.link; //if emote is a video }else if(emote.type == 'video'){ //create video node var emoteMedia = document.createElement('video'); - //Add video link - emoteMeida.src = emote.link; //Set video properties emoteMedia.autoplay = true; emoteMedia.muted = true; emoteMedia.controls = false; + emoteMedia.loop = true; } - emoteSpan.appendChild(emoteMedia); + //set media link as source + emoteMedia.src = emote.link; + //Set media class + emoteMedia.classList.add('emote-list-media'); - this.emoteList.appendChild(emoteSpan); + //Create title span + const titleSpan = document.createElement('span'); + titleSpan.classList.add('emote-list-title'); + + //Create paragraph tag + const emoteTitle = document.createElement('p'); + //Set title class + emoteTitle.classList.add('emote-list-title'); + //Set emote title + emoteTitle.innerHTML = `[${emote.name}]`; + + //Create delete icon + const deleteIcon = document.createElement('i'); + //Set delete icon id and class + deleteIcon.classList.add('bi-trash-fill', 'emote-list-delete'); + deleteIcon.id = `emote-list-delete-${emote.name}`; + //Add delete icon event listener + deleteIcon.addEventListener('click',this.deleteEmote.bind(this)); + + + //Add the emote media to the emote span + emoteDiv.appendChild(emoteMedia); + //Add title paragraph node + titleSpan.appendChild(emoteTitle); + //Add trash icon node + titleSpan.appendChild(deleteIcon); + //Add title span + emoteDiv.appendChild(titleSpan); + + //Append the mote span to the emote list + this.emoteList.appendChild(emoteDiv); }); } }