From a05228ab187751a4f21bddd0dead346901ffc7ce Mon Sep 17 00:00:00 2001 From: redman13 Date: Fri, 6 Dec 2024 19:45:32 -0800 Subject: [PATCH 1/5] baseline --- src/routes/panel/+page.svelte | 1962 +-------------------------------- 1 file changed, 58 insertions(+), 1904 deletions(-) diff --git a/src/routes/panel/+page.svelte b/src/routes/panel/+page.svelte index 50b29eec..827135b1 100644 --- a/src/routes/panel/+page.svelte +++ b/src/routes/panel/+page.svelte @@ -27,11 +27,11 @@ ).toLocaleTimeString()}`; } - let loggedIn = null; - let projectIdSelection; - let serverStats = []; - const selectForReject = $page.url.searchParams.get('reject'); + let tab = 'projects'; + let admin = false; + let loggedIn = true; + /* function kickOut(loggedOut) { const error = loggedOut ? 401 : 403; location.href = location.origin + `/error?error=${error}`; @@ -57,6 +57,7 @@ }); Authentication.usernameFromCode(username, token) .then(({ isAdmin, isApprover }) => { + admin = isAdmin; if (!isAdmin && !isApprover) { kickOut(false); return; @@ -78,803 +79,7 @@ loggedIn = false; location.href = location.origin; }); - - // moved this here so it can be used latter on - let dropdownSelectMenu; - - let contentWithReports = []; - let unapprovedProjects = []; - let selectedReportDetailed = -1; - let reportDetails = Object.create(null); - - const guidelinesNotifs = { - tos: false, - pp: false, - ug: false - }; - - const loadReportDetails = (id) => { - let type = "user"; - if (dropdownSelectMenu.value === "project") { - type = "project"; - } - if (id in reportDetails) { - return; - } - ProjectClient.getReports(type, id).then((reports) => { - reportDetails[id] = reports; - reportDetails = reportDetails; - }); - }; - - const setGetProjects = (allowGetProjects) => { - if (!confirm("Are you sure?")) return; - ProjectClient.setErrorAllGetProjects(allowGetProjects) - .then(() => { - alert("done"); - }) - .catch((err) => { - console.error(err); - alert(err); - }); - }; - const setUploadProjects = (allowUploadProjects) => { - if (!confirm("Are you sure?")) return; - ProjectClient.setErrorAllUploadProjects(allowUploadProjects) - .then(() => { - alert("done"); - }) - .catch((err) => { - console.error(err); - alert(err); - }); - }; - - let projectListStyle = ''; - const refreshProjectMenu = () => { - unapprovedProjects = []; - contentWithReports = []; - projectListStyle = ''; - selectedReportDetailed = -1; - reportDetails = Object.create(null); - switch (dropdownSelectMenu.value) { - case "user": - case "project": - return openReportsMenu(dropdownSelectMenu.value); - case "removed": - projectListStyle = 'flex-direction: row;flex-wrap: wrap;'; - //return openProjectsMenu(dropdownSelectMenu.value); - } - }; - const closeUserReport = (reportID) => { - const confirmed = prompt( - "Are you sure you've looked over this result completely? (Type 'ok' to confirm)" - ); - if (confirmed !== "ok") return; - ProjectClient.closeReport(reportID) - .then(() => { - refreshProjectMenu(); - }) - .catch((err) => { - alert(err); - }); - }; - - let unapprovedPage = 1; - function openProjectsMenu(type) { - // type is assumed to be unapproved because we have nothing else right now - unapprovedProjects = []; - contentWithReports = []; - ProjectClient.getRemovedProjects(unapprovedPage - 1).then(unapprovedProjs => { - unapprovedProjects = unapprovedProjs; - }); - } - function openReportsMenu(type) { - unapprovedProjects = []; - contentWithReports = []; - ProjectClient.getTypeWithReports(type, 0).then((projectsWithReports) => { - contentWithReports = projectsWithReports; - }); - // get approved projects anyways cuz we need to update list - // todo: getProjects is paged breh what we do? - // add a new endpoint containing all project names with tons of compression propably :idk_man: - // remember: network usage is key here since that makes us loose money :() - - // ProjectApi.getProjects().then((projects) => { - // approvedProjectNames = projects.map((p) => p.name); - // }); - } - // function deleteProject(id, name) { - // const code = prompt( - // `Delete ${name}? This CANNOT be undone!\nType "${id}" to delete this project.` - // ); - // if (String(code).replace(/[^0-9]*/gim, "") !== String(id)) { - // return; - // } - // ProjectClient.deleteProject(id); - // } - let rejectionPageOpen = false; - let deletionPageOpen = false; - let rejectingId = 0; - let rejectingName = ""; - let rejectingTextboxAreaText = ""; - let isRejectHard = false; - function rejectProject(id) { - id ??= Number(projectIdSelection.value); - if (isNaN(id)) return; - const confirmationMessage = `Reject "${rejectingName}"?\n` - + `${isRejectHard ? - 'Hard reject is enabled.\nThe uploader will not be able to edit the original project once you reject it.' - : 'Soft reject is enabled.'}`; - if (!confirm(confirmationMessage)) return; - if (rejectingTextboxAreaText.length <= 3) { - return alert("The action was cancelled."); - } - if (!isRejectHard) { - ProjectClient.rejectProject(id, rejectingTextboxAreaText).then(() => { - rejectionPageOpen = false; - refreshProjectMenu(); - }); - } else { - ProjectClient.hardRejectProject(id, rejectingTextboxAreaText).then(() => { - rejectionPageOpen = false; - refreshProjectMenu(); - }); - } - } - let selectedProjectName = ""; - let lastSelectedProjectId = 0; - function selectProject(id, name) { - projectIdSelection.value = id; - lastSelectedProjectId = id; - if (name) { - selectedProjectName = name; - } - } - - const openRemoveProjectMenu = async () => { - const id = String(projectIdSelection.value); - rejectingId = id; - if (selectedProjectName) { - rejectingName = selectedProjectName; - } else { - try { - const projectMeta = await ProjectApi.getProjectMeta(id); - rejectingName = projectMeta.title; - } catch { - rejectingName = ''; - } - } - rejectionPageOpen = true; - }; - - const openDeleteProjectMenu = async () => { - const id = String(projectIdSelection.value); - rejectingId = id; - if (selectedProjectName) { - rejectingName = selectedProjectName; - } else { - try { - const projectMeta = await ProjectApi.getProjectMeta(id); - rejectingName = projectMeta.title; - } catch { - rejectingName = ''; - } - } - deletionPageOpen = true; - } - function featureProject(value) { - const id = String(projectIdSelection.value); - const usure = confirm(`${value ? "Feature" : "Unfeature"} project?`); - if (!usure) return; - ProjectClient.featureProject(id, value).catch((err) => alert(err)); - } - - onMount(() => { - projectIdSelection.onchange = () => { - const value = projectIdSelection.value; - if (value !== lastSelectedProjectId) { - selectedProjectName = ""; - } - }; - if (selectForReject && String(selectForReject).length > 4) { - projectIdSelection.value = selectForReject; - openRemoveProjectMenu(); - } - }); - - // let sendWebhook = true; - // function approveProject() { - // const id = Number(projectIdSelection.value); - // if (isNaN(id)) return; - // ProjectClient.approveProject(id, sendWebhook) - // .then(() => { - // alert("The project was approved!"); - // // uhhhhhhh apparently we need to do this ig? - // const newProjects = projects.filter((proj) => proj.id !== id); - // projects = []; - // projects = newProjects; - // }) - // .catch((err) => { - // alert(err); - // }); - // } - - const filterJSONStuff = { - text: '' - }; - filterJSONStuff.get = async () => { - filterJSONStuff.text = JSON.stringify(await ProjectClient.getProfanityFilter(), null, 4); - }; - filterJSONStuff.set = (data) => { - ProjectClient.setProfanityFilter(data); - }; - - let inspectMenuOpen = false; - let censorMenuOpen = false; - const inspectMenuDetails = { - downloading: false, - error: false, - errorText: false, - extensions: [], - extensionData: {}, - extensionUrls: {}, - }; - const censorMenuDetails = { - downloading: false, - uploading: false, - error: false, - id: 0, - costumes: [], - sounds: [], - censoredCostumes: {}, - mutedSounds: {}, - previewNoBG: true, - previewBlack: false, - size: 128, - rawProject: null, - }; - let _resettingInspectMenu = true; - function resetInspectMenu() { - _resettingInspectMenu = false; - setTimeout(() => { - _resettingInspectMenu = true; - }, 10); - } - function openInspectMenu() { - inspectMenuOpen = true; - inspectMenuDetails.downloading = true; - inspectMenuDetails.error = false; - setTimeout(async () => { - if (!inspectMenuOpen) return; // dont download if we closed - const id = String(projectIdSelection.value); - ProjectApi.getProjectFile(id) - .then((blob) => { - JSZip.loadAsync(blob) - .then(async (zip) => { - const project = await zip - .file("project.json") - .async("string"); - const json = JSON.parse(project); - - const extensionList = json.extensions; - inspectMenuDetails.extensions = extensionList; - const extensionData = json.extensionURLs - ? json.extensionURLs - : {}; - - inspectMenuDetails.extensionData = extensionData; - inspectMenuDetails.extensionUrls = JSON.parse( - JSON.stringify(extensionData) - ); - inspectMenuDetails.downloading = false; - // get all urls - for (const extensionId of extensionList) { - if (!extensionData[extensionId]) { - extensionData[extensionId] = - "(Core Extension)"; - continue; - } - fetch(extensionData[extensionId]).then( - (res) => { - res.text().then((code) => { - extensionData[extensionId] = code; - resetInspectMenu(); - }); - } - ); - } - }) - .catch((err) => { - inspectMenuDetails.error = true; - inspectMenuDetails.errorText = err; - }); - }) - .catch((err) => { - inspectMenuDetails.error = true; - inspectMenuDetails.errorText = err; - }); - }, 1000); - } - const addToCensorMenuArray = async (asset, array, zip) => { - const assetFile = asset.md5ext; - try { - /** - * @type {Blob} - */ - const blob = await zip - .file(assetFile) - .async("blob"); - const fileType = await BlobAndDataUrl.fileTypeFromBlob(blob); - const mimeType = FileTypes.mimeTypePairs[fileType]; - const typedBlob = new Blob([await blob.arrayBuffer()], { type: mimeType }); - const properURL = URL.createObjectURL(typedBlob); - array.push({ name: asset.name, url: properURL, file: assetFile }); - } catch (e) { - console.warn('asset', asset.name, assetFile, 'failed to load', e); - } - }; - const fillCensorMenu = async (projectJson, zip) => { - const displayCostumes = censorMenuDetails.costumes; - const displaySounds = censorMenuDetails.sounds; - for (const target of projectJson.targets) { - for (const costume of target.costumes) { - await addToCensorMenuArray(costume, displayCostumes, zip); - } - for (const sound of target.sounds) { - await addToCensorMenuArray(sound, displaySounds, zip); - } - } - // svelte doesnt react to array.push apparently - censorMenuDetails.costumes = displayCostumes; - censorMenuDetails.sounds = displaySounds; - censorMenuDetails.downloading = false; - censorMenuDetails.uploading = false; - }; - const fetchElementAsBlob = async (url) => { - const res = await fetch(url); - if (!res.ok) throw `${url} not OK`; - const arrayBuffer = await res.arrayBuffer(); - const blob = BlobAndDataUrl.arrayBufferToBlob(arrayBuffer); - return blob; - }; - const _applyCensorChanges = async () => { - /** - * @type {{ zip:JSZip, json:object }} - */ - const project = censorMenuDetails.rawProject; - const censorCostume = await fetchElementAsBlob('/censor/costume.svg'); - const censorSound = await fetchElementAsBlob('/censor/sound.mp3'); - // get info that needs updating - // NOTE: these include the file type at the end - const censoredCostumes = Object.keys(censorMenuDetails.censoredCostumes) - .filter(key => censorMenuDetails.censoredCostumes[key] === true); - const censoredSounds = Object.keys(censorMenuDetails.mutedSounds) - .filter(key => censorMenuDetails.mutedSounds[key] === true); - // update json - for (const target of project.json.targets) { - for (const costumeId of censoredCostumes) { - for (const costume of target.costumes) { - if (!(costume.md5ext === costumeId)) continue; - costume.rotationCenterX = 32; - costume.rotationCenterY = 32; - costume.bitmapResolution = 1; - costume.dataFormat = "svg"; - costume.md5ext = `${costume.assetId}.svg`; - } - } - for (const soundId of censoredSounds) { - for (const sound of target.sounds) { - if (!(sound.md5ext === soundId)) continue; - sound.dataFormat = "mp3"; - sound.format = "mp3"; - sound.md5ext = `${sound.assetId}.mp3`; - } - } - } - // update zip - for (const costumeId of censoredCostumes) { - project.zip.file(costumeId, censorCostume); - } - for (const soundId of censoredSounds) { - project.zip.file(soundId, censorSound); - } - const penguinModProject = await project.zip.generateAsync({ type: "blob" }); - const projectId = censorMenuDetails.id; - - const meta = await ProjectApi.getProjectMeta(projectId); - const thumbnail = await ProjectApi.getProjectThumbnail(projectId); - - await ProjectClient.updateProject(projectId, { - project: penguinModProject, - title: meta.title, - instructions: meta.instructions, - notes: meta.notes, - image: thumbnail - }); - }; - const applyCensorChanges = async () => { - censorMenuDetails.uploading = true; - try { - await _applyCensorChanges(); - censorMenuOpen = false; - } catch (e) { - console.error(e); - alert(e); - } - censorMenuDetails.uploading = false; - }; - function openCensorMenu() { - censorMenuOpen = true; - censorMenuDetails.downloading = true; - censorMenuDetails.uploading = false; - censorMenuDetails.error = false; - setTimeout(() => { - if (!censorMenuOpen) return; // dont download if we closed - const id = String(projectIdSelection.value); - censorMenuDetails.id = id; - ProjectApi.getProjectFile(id) - .then((blob) => { - JSZip.loadAsync(blob) - .then(async (zip) => { - const project = await zip - .file("project.json") - .async("string"); - const json = JSON.parse(project); - censorMenuDetails.costumes = []; - censorMenuDetails.sounds = []; - censorMenuDetails.rawProject = { - zip, - json - }; - await fillCensorMenu(json, zip); - }) - .catch((err) => { - censorMenuDetails.error = true; - censorMenuDetails.errorText = err; - }); - }) - .catch((err) => { - censorMenuDetails.error = true; - censorMenuDetails.errorText = err; - }); - }, 1000); - } - - const messageReplyInfo = { - id: "", - text: "", - }; - const replyToMessage = () => { - if (!messageReplyInfo.id) return alert("Message ID is not specified."); - if (!messageReplyInfo.text) - return alert("No message text was specified."); - if ( - !confirm( - `Reply to message with "${messageReplyInfo.text}"?` - ) - ) - return; - ProjectClient.respondToDispute( - messageReplyInfo.id, - messageReplyInfo.text - ).then(() => { - alert("Sent!"); - messageReplyInfo.id = ""; - messageReplyInfo.text = ""; - }).catch(err => alert('Failed to send message:' + err)); - }; - const sendGuidelinesNotifs = () => { - const notifs = []; - if (guidelinesNotifs.tos) { - notifs.push('tos'); - } - if (guidelinesNotifs.pp) { - notifs.push('privacyPolicy'); - } - if (guidelinesNotifs.ug) { - notifs.push('guidelines'); - } - if (notifs.length <= 0) return alert("No notifs were selected!"); - const confirmed = prompt('Are you sure you want to notify ALL users of the site?\nType "ok" to confirm.'); - if (confirmed !== 'ok') return; - ProjectClient.setLastPolicyUpdate(notifs) - }; - - let rejectedProjectId = "0"; - const downloadRejectedProject = async () => { - try { - const projectFile = await ProjectClient.downloadHardRejectedProject( - rejectedProjectId - ); - FileSaver.saveAs( - new Blob([projectFile]), - `Project_${rejectedProjectId}.pmp` - ); - } catch (err) { - console.error(err); - alert(`Failed to download the project; ${err}`); - } - }; - const restoreRejectedProject = () => { - if (!confirm("Are you sure you want to restore this project?")) return; - ProjectClient.restoreRejectedProject(rejectedProjectId) - .then(() => { - alert("Restored!"); - }) - .catch((err) => { - console.error(err); - alert(`Failed to restore project; ${err}`); - }); - }; - const deleteProject = (id, reason) => { - if ( - !confirm( - "Are you sure you want to PERMANENTLY delete this project?\nYou should only do this if the project contains some really bad stuff." - ) - ) - return; - ProjectClient.deleteProject(id, reason) - .then(() => { - alert("Deleted."); - }) - .catch((err) => { - console.error(err); - alert(`Failed to delete project; ${err}`); - }); - }; - - const userSelectionData = { - username: "", - reason: "", - time: 0, - admin: false, - approver: false, - newUsername: "", - newPfp: null, - }; - const renameUser = () => { - const promptMessage = prompt( - `Are you sure you want to rename ${userSelectionData.username} to ${userSelectionData.newUsername}?\nType "ok" to confirm.` - ); - if (promptMessage !== "ok") return; - ProjectClient.setUsernameOfUser(userSelectionData.username, userSelectionData.newUsername) - .then(() => { - alert(`Renamed ${userSelectionData.username} to ${userSelectionData.newUsername}`); - }) - .catch((err) => { - console.error(err); - alert(`Failed to rename user; ${err}`); - }); - }; - const setNewPfpInput = (event) => { - const file = event.target.files[0]; - if (!file) return; - - const reader = new FileReader(); - reader.onload = async () => { - const arrayBuffer = reader.result; - userSelectionData.newPfp = arrayBuffer; - }; - - // get it as a blob - reader.readAsArrayBuffer(file); - }; - const changePfpUser = () => { - const promptMessage = prompt( - `Are you sure you want to change ${userSelectionData.username}'s Profile Picture?\nType "ok" to confirm.` - ); - if (promptMessage !== "ok") return; - ProjectClient.setPFPOfUser(userSelectionData.username, userSelectionData.newPfp) - .then(() => { - alert(`Changed ${userSelectionData.username}'s Profile Picture.`); - }) - .catch((err) => { - console.error(err); - alert(`Failed to change profile picture of user; ${err}`); - }); - }; - - const banUser = () => { - const promptMessage = prompt( - `Are you sure you want to ban ${userSelectionData.username} for "${userSelectionData.reason}"? Type "ok" to confirm.` - ); - if (promptMessage !== "ok") return; - ProjectClient.banUser(userSelectionData.username, userSelectionData.reason, 0, true) - .then(() => { - alert(`Banned ${userSelectionData.username}.`); - }) - .catch((err) => { - console.error(err); - alert(`Failed to ban user; ${err}`); - }); - }; - - const tempBanUser = () => { - const promptMessage = prompt( - `Are you sure you want to temp ban ${userSelectionData.username} for "${userSelectionData.reason}" for ${userSelectionData.time} seconds (${userSelectionData.time / (60 * 60)} hours)? Type "ok" to confirm.` - ); - if (promptMessage !== "ok") return; - ProjectClient.banUser(userSelectionData.username, userSelectionData.reason, Math.ceil(userSelectionData.time*1000), true) - .then(() => { - alert(`Banned ${userSelectionData.username}.`); - }) - .catch((err) => { - console.error(err); - alert(`Failed to ban user; ${err}`); - }); - }; - - const unbanUser = () => { - const promptMessage = prompt( - `Are you sure you want to unban ${userSelectionData.username}? Type "ok" to confirm.` - ); - if (promptMessage !== "ok") return; - ProjectClient.banUser(userSelectionData.username, userSelectionData.reason, 0, false) - .then(() => { - alert(`Unbanned ${userSelectionData.username}.`); - }) - .catch((err) => { - console.error(err); - alert(`Failed to unban user; ${err}`); - }); - }; - - let areBadgesLoadedForVisibility = false; - let currentUserBadges = {}; - let userBadgesUsername = ""; - const loadUserBadges = async () => { - areBadgesLoadedForVisibility = false; - if (!userBadgesUsername) return; - const realBadges = await ProjectApi.getUserBadges(userBadgesUsername); - currentUserBadges = {}; - for (const badgeName in ProfileBadges) { - currentUserBadges[badgeName] = false; - } - for (const badgeName of realBadges) { - currentUserBadges[badgeName] = true; - } - areBadgesLoadedForVisibility = true; - }; - const applyUserBadges = () => { - if (!confirm("Apply badges to this user?")) return; - - const newBadges = [] - for (const badgeName in currentUserBadges) { - if (currentUserBadges[badgeName] === true) { - newBadges.push(badgeName); - } - } - - ProjectClient.setUserBadges(userBadgesUsername, newBadges) - .then(() => { - alert("Badges are set!"); - }) - .catch((err) => { - alert(`An error occurred: ${err}`); - }); - }; - const setUsersPerms = () => { - const verbAdmin = userSelectionData.admin - ? `grant ${userSelectionData.username} admin?` - : `revoke ${userSelectionData.username}'s admin?`; - const verbApprover = userSelectionData.approver - ? `grant ${userSelectionData.username} modderator?` - : `revoke ${userSelectionData.username}'s modderation possition?`; - const promptMessage = prompt( - `Are you sure you want to ${verbAdmin} & ${verbApprover} Type "ok" to confirm.` - ); - if (promptMessage !== "ok") return; - ProjectClient.assingUsersPermisions( - userSelectionData.username, - userSelectionData.admin, - userSelectionData.approver - ) - .then(() => { - // i don wana make it re-say the whole grant-revoke thingy - alert( - `Successfully did what ever you said to do ${userSelectionData.username}.` - ); - }) - .catch((err) => { - console.error(err); - alert(`Failed to moddify users permissions; ${err}`); - }); - }; - - function ipBanUser(toggle=true) { - if (toggle) { - const promptMessage = prompt( - `Are you sure you want to IP ban ${userSelectionData.username}? They will be unable to use ANY part of the site that requires the server. People who are on the same network may not be able to access that either. Type "ok" to confirm.` - ); - if (promptMessage !== "ok") return; - } - - ProjectClient.ipBanUser(userSelectionData.username, toggle) - .then(() => { - alert(`${toggle ? "" : "Un "}IP Banned ${userSelectionData.username}.`); - }) - .catch((err) => { - console.error(err); - alert(`Failed to ${toggle ? "" : "Un "}IP ban user; ${err}`); - }); - } - - function deleteAccount() { - if (prompt("Are you sure you want to delete this account? THIS IS PERMANENT AND DELETES **ALL** DATA. enter \"ok\" to confirm.") !== "ok") return; - ProjectClient.deleteUserAccount(userSelectionData.username, userSelectionData.reason) - .then(() => { - alert("Account deleted."); - }) - .catch((err) => { - console.error(err); - alert(`Failed to delete account; ${err}`); - }); - } - - let ipBanData = { - input: "", - connectedIPs: [], - } - - function getConnectedIPs() { - ProjectClient.getConnectedIPs(ipBanData.input) - .then((ips) => { - ipBanData.connectedIPs = _parseIPs(ips); - }) - .catch((err) => { - console.error(err); - alert(`Failed to get connected IPs; ${err}`); - }); - } - - function getConnectedUsers() { - ProjectClient.getConnectedUsers(ipBanData.input) - .then((users) => { - ipBanData.connectedIPs = users.map(v => v.username); - }) - .catch((err) => { - console.error(err); - alert(`Failed to get connected users; ${err}`); - }); - } - - function _parseIPs(ips) { - return ips.map((ip) => { - return `IP: ${ip.ip}, banned: ${ip.banned}, last login: ${unixToDisplayDate(ip.lastLogin)}`; - }); - } - - function banIP(toggle) { - if (toggle) { - const promptMessage = prompt( - `Are you sure you want to ban this ip? No one who has this ip, even who are just on the same network, will be able to use anything that needs the api. Type "ok" to confirm.` - ); - if (promptMessage !== "ok") return; - } - - ProjectClient.banIP(ipBanData.input, toggle) - .then(() => { - alert(`${toggle ? "" : "Un "}Banned ${ipBanData.input}.`); - }) - .catch((err) => { - console.error(err); - alert(`Failed to ${toggle ? "" : "Un "}ban IP; ${err}`); - }); - } - - let showUserPerms = false; - let listOfAdmins = []; - let listOfMods = []; - const loadUserPerms = () => ProjectClient.getAllPermitedUsers() - .then(users => { - listOfAdmins = users.admins; - listOfMods = users.mods; - }) - .catch((err) => { - console.error(err); - alert(`Failed to get permited users; ${err}`); - }); + */ @@ -898,927 +103,33 @@
-
-
-
-

Reject Project

-
-
-

Rejecting {rejectingName}

- Image of {rejectingName} - - -
-
- - -
-
-
- -

Global Server Toggles: (applies to all users)

- - - - - -
-
-
-
-
- - -
- {#if !dropdownSelectMenu?.value} -

- Please select what type of reports you wish to view -

- {/if} - -
- {#if dropdownSelectMenu?.value} - {#if contentWithReports.length > 0 || unapprovedProjects.length > 0} - {#if dropdownSelectMenu.value === "user"} -

- Click on a user to expand details -

- {:else} -

- Click on a project to expand details -

- {/if} - {:else} - {#if dropdownSelectMenu.value === "user"} -

- No user reports currently! -

- {:else if dropdownSelectMenu.value === 'removed'} -

- No removed projects currently! -

- {:else} -

- No project reports currently! -

- {/if} - {/if} - {#each unapprovedProjects as project} -
- { - selectProject(project.id, project.name); - }} - /> -
- {/each} - {#each contentWithReports as content, idx} - {#if dropdownSelectMenu.value === "user"} - - {#if selectedReportDetailed === idx} -
- {#if !reportDetails[content.target]} - - {:else} -
By: {content.reporter}
-

- {content.report} -

- - go to profile -

View reports by

- {#each reportDetails[content.target] as report} -
- - {report.reporter} - - -

- {report.report} -

-
- {/each} - {/if} -
- {/if} - {:else} - - {#if selectedReportDetailed === idx} -
-
By: {content.reporter}
-

- {content.report} -

- -

- View project at - - {`${PUBLIC_STUDIO_URL}/#${content.targetID}`} - - or - -

- {#if !reportDetails[content.targetID]} - - {:else} -

View reports by

- {#each reportDetails[content.targetID] as report} -
- - {report.reporter} - - -

- {report.report} -

-
- {/each} - {/if} -
- {/if} - {/if} - {/each} - {/if} -
-
-
From 6159c8b2c5a04005143bf220f6662efb0038275b Mon Sep 17 00:00:00 2001 From: redman13 Date: Fri, 6 Dec 2024 20:07:33 -0800 Subject: [PATCH 2/5] add stats --- src/lib/statsComponent/stats.svelte | 9 +++++++-- src/routes/panel/+page.svelte | 22 ++++++++++++---------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/lib/statsComponent/stats.svelte b/src/lib/statsComponent/stats.svelte index b14210d2..ac97c2ba 100644 --- a/src/lib/statsComponent/stats.svelte +++ b/src/lib/statsComponent/stats.svelte @@ -21,9 +21,11 @@ {#if typeof stat === 'object'}

{object_clicks[stat.name] = !object_clicks[stat.name]}}>{object_clicks[stat.name] ? ">" : "v"} {stat.name}

- +
+ +
{:else} -

{stat}

+ {stat}
{/if} {/each} {/if} @@ -33,5 +35,8 @@ cursor: pointer; /* underline */ text-decoration: underline; + margin-left: -3px; + margin-top: 10px; + margin-bottom: 0px; } diff --git a/src/routes/panel/+page.svelte b/src/routes/panel/+page.svelte index 507ad241..943a0351 100644 --- a/src/routes/panel/+page.svelte +++ b/src/routes/panel/+page.svelte @@ -31,21 +31,14 @@ let tab = 'projects'; let admin = false; let loggedIn = true; + let serverStats = []; - /* function kickOut(loggedOut) { const error = loggedOut ? 401 : 403; location.href = location.origin + `/error?error=${error}`; } onMount(() => { - const username = localStorage.getItem("username"); - const token = localStorage.getItem("token"); - if (!token || !username) { - loggedIn = false; - return; - } - function Flatten(obj) { let stats = []; for (const name in obj) { @@ -65,6 +58,15 @@ .catch((err) => { console.error(err); }); + + const username = localStorage.getItem("username"); + const token = localStorage.getItem("token"); + if (!token || !username) { + loggedIn = false; + return; + } + + /* Authentication.usernameFromCode(username, token) .then(({ isAdmin, isApprover }) => { admin = isAdmin; @@ -80,6 +82,7 @@ loggedIn = false; kickOut(true); }); + */ }); // we dont need to add an "onAuthenticate" event // because you cant sign in on the /panel page, @@ -89,7 +92,6 @@ loggedIn = false; location.href = location.origin; }); - */ @@ -136,7 +138,7 @@
ip management
{:else if tab === 'misc'}
-
server stats
+
server on/offs and profanity config
{/if} From 143e108a998cb68566574070d4bddd5e97bbc42f Mon Sep 17 00:00:00 2001 From: redman13 Date: Sat, 7 Dec 2024 16:55:51 -0800 Subject: [PATCH 3/5] finish misc --- src/resources/projectapi.js | 18 +++ src/routes/panel/+page.svelte | 201 +++++++++++++++++++++++++++++----- 2 files changed, 189 insertions(+), 30 deletions(-) diff --git a/src/resources/projectapi.js b/src/resources/projectapi.js index 60eab615..89008702 100644 --- a/src/resources/projectapi.js +++ b/src/resources/projectapi.js @@ -17,6 +17,24 @@ class ProjectApi { static OriginApiUrl = OriginApiUrl; static CachedDonators = {}; + static canUploadProjects() { + return fetch(`${OriginApiUrl}/api/v1/projects/canuploadprojects`) + .then(async res => { + // if this api call fails, expect that all others will fail aswell + if (!res.ok) return false; + return (await res.json()).canUpload; + }) + .catch(() => false); + } + static canViewProjects() { + return fetch(`${OriginApiUrl}/api/v1/projects/canviewprojects`) + .then(async res => { + // if this api call fails, expect that all others will fail aswell + if (!res.ok) return false; + return (await res.json()).viewing; + }) + .catch(() => false); + } static getServerInfo(user) { return new Promise((resolve, reject) => { const url = `${OriginApiUrl}/api/v1/misc/getStats`; diff --git a/src/routes/panel/+page.svelte b/src/routes/panel/+page.svelte index 943a0351..af1b000d 100644 --- a/src/routes/panel/+page.svelte +++ b/src/routes/panel/+page.svelte @@ -1,5 +1,6 @@ @@ -139,7 +166,75 @@ {:else if tab === 'misc'}
-
server on/offs and profanity config
+
+
+
+ User IP Lookup +
+
+ +
+
+ + +
+
+
+
+ Profanity List +
+
+ +
+
+ +
+
+
+
+
+ +
+
+ +
+
+
+
{/if} @@ -161,6 +256,42 @@ color: white; } + .text-box { + box-sizing: border-box; + width: 100%; + height: 150px; + } + .text-controlable { + display: grid; + grid-template-columns: minmax(auto, 1fr) max-content; + justify-content: end; + width: 100%; + } + .misc-member { + width: 100%; + height: 100%; + border-top: 1px solid grey; + padding-top: 10px; + text-align: center; + } + .misc-members { + display: grid; + grid-template-columns: 100%; + grid-template-rows: repeat(2, minmax(auto, 1fr)) max-content; + justify-content: end; + height: 100%; + width: 100%; + } + + .can-upload-toggle { + display: inline; + float: left; + } + .can-view-toggle { + display: inline; + float: right; + } + .projects-control { display: grid; grid-template-columns: 35% 65%; @@ -172,6 +303,8 @@ border-radius: 10px; background-color: #00c3ff22; height: 100%; + overflow-x: hidden; + overflow-y: scroll; } .section-category-toggles { background-color: rgba(100%, 100%, 100%, 0.05); @@ -183,26 +316,34 @@ margin: 0px; } .category-toggle-section { - display: flex; - flex-direction: row; - align-items: center; + display: grid; + grid-template-columns: repeat(5, 20%); + align-items: flex-end; justify-content: center; - width: 30%; - margin: 4px 10px; + width: 100%; + margin-top: 4px; } .category-toggle-section button { - border-radius: 1024px; + border-top-left-radius: 10px; + border-top-right-radius: 10px; + border-width: 4px; + border-style: solid; + border-color: grey; padding: 4px 10px; background: #008cff; font-weight: bold; font-size: 1em; border: 0; - margin: 0 4px; + margin: 2px 0.5px; + margin-bottom: 0; color: white; cursor: pointer; } .category-toggle-section button[active="true"] { + margin-top: 0; + padding: 7px 10px; background: #003bdd; + z-index: 2; } .category-toggle-section button[admin="true"] { background: #215a8a; From a156298a2dc5235da99b222de05c6a5eb6b71698 Mon Sep 17 00:00:00 2001 From: redman13 Date: Sat, 7 Dec 2024 18:38:42 -0800 Subject: [PATCH 4/5] ohhhhhhhh thats why it wasnt greyed out on none admin --- src/routes/panel/+page.svelte | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/routes/panel/+page.svelte b/src/routes/panel/+page.svelte index af1b000d..01c3d131 100644 --- a/src/routes/panel/+page.svelte +++ b/src/routes/panel/+page.svelte @@ -33,7 +33,7 @@ ? location.hash.slice(1) : 'projects'; let admin = false; - let loggedIn = true; + let loggedIn = null; function kickOut(loggedOut) { const error = loggedOut ? 401 : 403; @@ -60,7 +60,6 @@ return; } - /* Authentication.usernameFromCode(username, token) .then(({ isAdmin, isApprover }) => { admin = isAdmin; @@ -76,7 +75,6 @@ loggedIn = false; kickOut(true); }); - */ }); // we dont need to add an "onAuthenticate" event // because you cant sign in on the /panel page, @@ -102,7 +100,6 @@ case 'projects': break; case 'messages': break; case 'users': break; - case 'admin': break; case 'misc': ProjectApi.getServerInfo() .then(stats => serverStats = Flatten(stats)) @@ -147,9 +144,8 @@
- - - + +
{#if tab === 'projects'} @@ -161,8 +157,6 @@
messages
{:else if tab === 'users'}
users bans and badges
- {:else if tab === 'admin'} -
ip management
{:else if tab === 'misc'}
@@ -172,6 +166,7 @@ User IP Lookup
+ +
+
+ +
+ + +
+
+
+ +
+ {:else if tab === 'misc'}
-
- User IP Lookup -
-
- - -
-
- - -
-
-
Profanity List
@@ -253,6 +295,7 @@ .text-box { box-sizing: border-box; + resize: none; width: 100%; height: 150px; } @@ -272,7 +315,7 @@ .misc-members { display: grid; grid-template-columns: 100%; - grid-template-rows: repeat(2, minmax(auto, 1fr)) max-content; + grid-template-rows: minmax(auto, 1fr) max-content; justify-content: end; height: 100%; width: 100%; @@ -312,7 +355,7 @@ } .category-toggle-section { display: grid; - grid-template-columns: repeat(4, 20%); + grid-template-columns: repeat(5, 20%); align-items: flex-end; justify-content: center; width: 100%;