From e4fe1452fbb679df648243e33d8ed95b43f4d049 Mon Sep 17 00:00:00 2001 From: Marc Ole Bulling Date: Wed, 18 Dec 2024 12:02:21 +0100 Subject: [PATCH] Add new API keys to UI without reloading, add small animation, remove html_users.tmpl originaly from unpublished branch --- internal/webserver/web/static/css/cover.css | 15 ++ .../web/static/css/min/gokapi.min.3.css | 2 +- internal/webserver/web/static/js/admin_ui.js | 144 ++++++++++++------ .../web/static/js/min/admin.min.7.js | 8 +- .../webserver/web/templates/html_api.tmpl | 5 +- .../webserver/web/templates/html_users.tmpl | 91 ----------- 6 files changed, 120 insertions(+), 145 deletions(-) delete mode 100644 internal/webserver/web/templates/html_users.tmpl diff --git a/internal/webserver/web/static/css/cover.css b/internal/webserver/web/static/css/cover.css index b77e48c..3884bf5 100644 --- a/internal/webserver/web/static/css/cover.css +++ b/internal/webserver/web/static/css/cover.css @@ -220,6 +220,16 @@ td.newItem { } } + +@keyframes subtleHighlightNewApiKey { + 0% { + background-color: green; /* Pale green for new items */ + } + 100% { + background-color: transparent; + } +} + /* Apply the animation to the updated table cells */ .updatedDownloadCount { animation: subtleHighlight 0.5s ease-out; @@ -230,4 +240,9 @@ td.newItem { animation: subtleHighlightNewItem 0.5s ease-out; } +.newApiKey { + animation: subtleHighlightNewApiKey 0.7s ease-out; +} + + diff --git a/internal/webserver/web/static/css/min/gokapi.min.3.css b/internal/webserver/web/static/css/min/gokapi.min.3.css index 8f1b80b..073b7fe 100644 --- a/internal/webserver/web/static/css/min/gokapi.min.3.css +++ b/internal/webserver/web/static/css/min/gokapi.min.3.css @@ -1 +1 @@ -.btn-secondary,.btn-secondary:hover,.btn-secondary:focus{color:#333;text-shadow:none}body{background:url(../../assets/background.jpg)no-repeat 50% fixed;-webkit-background-size:cover;-moz-background-size:cover;-o-background-size:cover;background-size:cover;display:-ms-flexbox;display:-webkit-box;display:flex;-ms-flex-pack:center;-webkit-box-pack:center;justify-content:center}td{vertical-align:middle;position:relative}a{color:inherit}a:hover{color:inherit;filter:brightness(80%)}.dropzone{background:#2f343a!important;color:#fff;border-radius:5px}.dropzone:hover{background:#33393f!important;color:#fff;border-radius:5px}.card{margin:0 auto;float:none;margin-bottom:10px;border:2px solid #33393f}.card-body{background-color:#212529;color:#ddd}.card-title{font-weight:900}.admin-input{text-align:center}.form-control:disabled{background:#bababa}.break{flex-basis:100%;height:0}.bd-placeholder-img{font-size:1.125rem;text-anchor:middle;-webkit-user-select:none;-moz-user-select:none;user-select:none}@media(min-width:768px){.bd-placeholder-img-lg{font-size:3.5rem}.break{flex-basis:0}}.masthead{margin-bottom:2rem}.masthead-brand{margin-bottom:0}.nav-masthead .nav-link{padding:.25rem 0;font-weight:700;color:rgba(255,255,255,.5);background-color:initial;border-bottom:.25rem solid transparent}.nav-masthead .nav-link:hover,.nav-masthead .nav-link:focus{border-bottom-color:rgba(255,255,255,.25)}.nav-masthead .nav-link+.nav-link{margin-left:1rem}.nav-masthead .active{color:#fff;border-bottom-color:#fff}#qroverlay{display:none;position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,.3)}#qrcode{position:absolute;top:50%;left:50%;margin-top:-105px;margin-left:-105px;width:210px;height:210px;border:5px solid #fff}.toastnotification{pointer-events:none;position:fixed;bottom:20px;left:50%;transform:translateX(-50%);background-color:#333;color:#fff;padding:15px;border-radius:5px;box-shadow:0 2px 5px rgba(0,0,0,.3);opacity:0;transition:opacity .3s ease-in-out;z-index:9999}.toastnotification.show{opacity:1;pointer-events:auto}.apiperm-granted{cursor:pointer;color:#19b90e}.apiperm-notgranted{cursor:pointer;color:#7e7e7e}.apiperm-processing{color:#e5eb00}.gokapi-dialog{background-color:#212529;color:#ddd}td.newItem{background-color:green}@keyframes subtleHighlight{0%{background-color:#444950}100%{background-color:initial}}@keyframes subtleHighlightNewItem{0%{background-color:#a8e6a3}100%{background-color:green}}.updatedDownloadCount{animation:subtleHighlight .5s ease-out}.updatedDownloadCount.newItem{animation:subtleHighlightNewItem .5s ease-out}.filename{font-weight:700;font-size:14px;margin-bottom:5px}.upload-progress-container{display:flex;align-items:center}.upload-progress-bar{position:relative;height:10px;background-color:#eee;flex:1;margin-right:10px;border-radius:4px}.upload-progress-bar-progress{position:absolute;top:0;left:0;height:100%;background-color:#0a0;border-radius:4px;transition:width .2s ease-in-out}.upload-progress-info{font-size:12px}.us-container{margin-top:10px;margin-bottom:20px}.uploaderror{font-weight:700;color:red;margin-bottom:5px}.uploads-container{background-color:#2f343a;border:2px solid rgba(0,0,0,.3);border-radius:5px;margin-left:0;margin-right:0;max-width:none;visibility:hidden} \ No newline at end of file +.btn-secondary,.btn-secondary:hover,.btn-secondary:focus{color:#333;text-shadow:none}body{background:url(../../assets/background.jpg)no-repeat 50% fixed;-webkit-background-size:cover;-moz-background-size:cover;-o-background-size:cover;background-size:cover;display:-ms-flexbox;display:-webkit-box;display:flex;-ms-flex-pack:center;-webkit-box-pack:center;justify-content:center}td{vertical-align:middle;position:relative}a{color:inherit}a:hover{color:inherit;filter:brightness(80%)}.dropzone{background:#2f343a!important;color:#fff;border-radius:5px}.dropzone:hover{background:#33393f!important;color:#fff;border-radius:5px}.card{margin:0 auto;float:none;margin-bottom:10px;border:2px solid #33393f}.card-body{background-color:#212529;color:#ddd}.card-title{font-weight:900}.admin-input{text-align:center}.form-control:disabled{background:#bababa}.break{flex-basis:100%;height:0}.bd-placeholder-img{font-size:1.125rem;text-anchor:middle;-webkit-user-select:none;-moz-user-select:none;user-select:none}@media(min-width:768px){.bd-placeholder-img-lg{font-size:3.5rem}.break{flex-basis:0}}.masthead{margin-bottom:2rem}.masthead-brand{margin-bottom:0}.nav-masthead .nav-link{padding:.25rem 0;font-weight:700;color:rgba(255,255,255,.5);background-color:initial;border-bottom:.25rem solid transparent}.nav-masthead .nav-link:hover,.nav-masthead .nav-link:focus{border-bottom-color:rgba(255,255,255,.25)}.nav-masthead .nav-link+.nav-link{margin-left:1rem}.nav-masthead .active{color:#fff;border-bottom-color:#fff}#qroverlay{display:none;position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,.3)}#qrcode{position:absolute;top:50%;left:50%;margin-top:-105px;margin-left:-105px;width:210px;height:210px;border:5px solid #fff}.toastnotification{pointer-events:none;position:fixed;bottom:20px;left:50%;transform:translateX(-50%);background-color:#333;color:#fff;padding:15px;border-radius:5px;box-shadow:0 2px 5px rgba(0,0,0,.3);opacity:0;transition:opacity .3s ease-in-out;z-index:9999}.toastnotification.show{opacity:1;pointer-events:auto}.apiperm-granted{cursor:pointer;color:#19b90e}.apiperm-notgranted{cursor:pointer;color:#7e7e7e}.apiperm-processing{color:#e5eb00}.gokapi-dialog{background-color:#212529;color:#ddd}td.newItem{background-color:green}@keyframes subtleHighlight{0%{background-color:#444950}100%{background-color:initial}}@keyframes subtleHighlightNewItem{0%{background-color:#a8e6a3}100%{background-color:green}}@keyframes subtleHighlightNewApiKey{0%{background-color:green}100%{background-color:initial}}.updatedDownloadCount{animation:subtleHighlight .5s ease-out}.updatedDownloadCount.newItem{animation:subtleHighlightNewItem .5s ease-out}.newApiKey{animation:subtleHighlightNewApiKey .7s ease-out}.filename{font-weight:700;font-size:14px;margin-bottom:5px}.upload-progress-container{display:flex;align-items:center}.upload-progress-bar{position:relative;height:10px;background-color:#eee;flex:1;margin-right:10px;border-radius:4px}.upload-progress-bar-progress{position:absolute;top:0;left:0;height:100%;background-color:#0a0;border-radius:4px;transition:width .2s ease-in-out}.upload-progress-info{font-size:12px}.us-container{margin-top:10px;margin-bottom:20px}.uploaderror{font-weight:700;color:red;margin-bottom:5px}.uploads-container{background-color:#2f343a;border:2px solid rgba(0,0,0,.3);border-radius:5px;margin-left:0;margin-right:0;max-width:none;visibility:hidden} \ No newline at end of file diff --git a/internal/webserver/web/static/js/admin_ui.js b/internal/webserver/web/static/js/admin_ui.js index f7d5acf..9091831 100644 --- a/internal/webserver/web/static/js/admin_ui.js +++ b/internal/webserver/web/static/js/admin_ui.js @@ -278,52 +278,6 @@ function requestFileInfo(fileId, uid) { } -function addFriendlyNameChange() { - document.querySelectorAll(".apiname").forEach(function(node) { - node.onclick = function() { - if (this.classList.contains("isBeingEdited")) - return; - this.classList.add("isBeingEdited"); - var val = this.innerHTML; - var input = document.createElement("input"); - input.size = 5; - input.value = val; - let row = this; - let allowEdit = true; - - let submitEntry = function() { - if (!allowEdit) - return; - allowEdit = false; - var newName = input.value; - input.parentNode.innerHTML = newName; - - row.classList.remove("isBeingEdited"); - - apiAuthFriendlyName(row.id, newName) - .catch(error => { - alert("Unable to save name: " + error); - console.error('Error:', error); - }); - }; - - input.onblur = submitEntry; - input.addEventListener("keyup", function(event) { - // Enter - if (event.keyCode === 13) { - event.preventDefault(); - submitEntry(); - } - }); - this.innerHTML = ""; - this.appendChild(input); - input.focus(); - }; - }); -} - - - function parseProgressStatus(eventData) { let container = document.getElementById(`us-container-${eventData.chunk_id}`); if (container == null) { @@ -601,12 +555,11 @@ function deleteApiKey(apiKey) { function newApiKey() { - document.getElementById("button-newapi").disabled = true; - apiAuthCreate() .then(data => { - location.reload(); + addRowApi(data.Id); + document.getElementById("button-newapi").disabled = false; }) .catch(error => { alert("Unable to create API key: " + error); @@ -615,6 +568,99 @@ function newApiKey() { } + + +function addFriendlyNameChange(apiKey) { + let cell = document.getElementById("friendlyname-" + apiKey); + if (cell.classList.contains("isBeingEdited")) + return; + cell.classList.add("isBeingEdited"); + let currentName = cell.innerHTML; + let input = document.createElement("input"); + input.size = 5; + input.value = currentName; + let allowEdit = true; + + let submitEntry = function() { + if (!allowEdit) + return; + allowEdit = false; + let newName = input.value; + cell.innerHTML = newName; + + cell.classList.remove("isBeingEdited"); + + apiAuthFriendlyName(apiKey, newName) + .catch(error => { + alert("Unable to save name: " + error); + console.error('Error:', error); + }); + }; + + input.onblur = submitEntry; + input.addEventListener("keyup", function(event) { + // Enter + if (event.keyCode === 13) { + event.preventDefault(); + submitEntry(); + } + }); + cell.innerHTML = ""; + cell.appendChild(input); + input.focus(); +} + + + + +function addRowApi(apiKey) { + + let table = document.getElementById("apitable"); + let row = table.insertRow(0); + row.id = "row-" + apiKey; + let cellFriendlyName = row.insertCell(0); + let cellId = row.insertCell(1); + let cellLastUsed = row.insertCell(2); + let cellPermissions = row.insertCell(3); + let cellButtons = row.insertCell(4); + let cellEmpty = row.insertCell(5); + + cellFriendlyName.classList.add("newApiKey"); + cellId.classList.add("newApiKey"); + cellLastUsed.classList.add("newApiKey"); + cellPermissions.classList.add("newApiKey"); + cellButtons.classList.add("newApiKey"); + cellEmpty.classList.add("newApiKey"); + + + cellFriendlyName.innerText = "Unnamed key"; + cellFriendlyName.id = "friendlyname-" + apiKey; + cellFriendlyName.onclick = function() { + addFriendlyNameChange(apiKey); + }; + cellId.innerText = apiKey; + cellLastUsed.innerText = "Never"; + cellButtons.innerHTML = ' '; + cellPermissions.innerHTML = ` + + + + + + `; + + setTimeout(() => { + cellFriendlyName.classList.remove("newApiKey"); + cellId.classList.remove("newApiKey"); + cellLastUsed.classList.remove("newApiKey"); + cellPermissions.classList.remove("newApiKey"); + cellButtons.classList.remove("newApiKey"); + cellEmpty.classList.remove("newApiKey"); + }, 700); + +} + + function deleteFile(id) { document.getElementById("button-delete-" + id).disabled = true; diff --git a/internal/webserver/web/static/js/min/admin.min.7.js b/internal/webserver/web/static/js/min/admin.min.7.js index de70bf9..3ac5ab4 100644 --- a/internal/webserver/web/static/js/min/admin.min.7.js +++ b/internal/webserver/web/static/js/min/admin.min.7.js @@ -1 +1,7 @@ -async function apiAuthModify(e,t,n){const s="./api/auth/modify",o={method:"POST",headers:{"Content-Type":"application/json",apikey:systemKey,apiKeyToModify:e,permission:t,permissionModifier:n}};try{const e=await fetch(s,o);if(!e.ok)throw new Error(`Request failed with status: ${e.status}`)}catch(e){throw console.error("Error in apiAuthModify:",e),e}}async function apiAuthFriendlyName(e,t){const n="./api/auth/friendlyname",s={method:"PUT",headers:{"Content-Type":"application/json",apikey:systemKey,apiKeyToModify:e,friendlyName:t}};try{const e=await fetch(n,s);if(!e.ok)throw new Error(`Request failed with status: ${e.status}`)}catch(e){throw console.error("Error in apiAuthModify:",e),e}}async function apiAuthDelete(e){const t="./api/auth/delete",n={method:"POST",headers:{"Content-Type":"application/json",apikey:systemKey,apiKeyToModify:e}};try{const e=await fetch(t,n);if(!e.ok)throw new Error(`Request failed with status: ${e.status}`)}catch(e){throw console.error("Error in apiAuthDelete:",e),e}}async function apiAuthCreate(){const e="./api/auth/create",t={method:"POST",headers:{"Content-Type":"application/json",apikey:systemKey,basicPermissions:"true"}};try{const n=await fetch(e,t);if(!n.ok)throw new Error(`Request failed with status: ${n.status}`);const s=await n.json();return s}catch(e){throw console.error("Error in apiAuthCreate:",e),e}}async function apiFilesReplace(e,t){const n="./api/files/replace",s={method:"PUT",headers:{"Content-Type":"application/json",id:e,apikey:systemKey,idNewContent:t,deleteNewFile:!1}};try{const e=await fetch(n,s);if(!e.ok)throw new Error(`Request failed with status: ${e.status}`);const t=await e.json();return t}catch(e){throw console.error("Error in apiFilesReplace:",e),e}}async function apiFilesListById(e){const t="./api/files/list/"+e,n={method:"GET",headers:{"Content-Type":"application/json",apikey:systemKey}};try{const e=await fetch(t,n);if(!e.ok)throw new Error(`Request failed with status: ${e.status}`);const s=await e.json();return s}catch(e){throw console.error("Error in apiFilesListById:",e),e}}async function apiFilesModify(e,t,n,s,o){const i="./api/files/modify",a={method:"PUT",headers:{"Content-Type":"application/json",id:e,apikey:systemKey,allowedDownloads:t,expiryTimestamp:n,password:s,originalPassword:o}};try{const e=await fetch(i,a);if(!e.ok)throw new Error(`Request failed with status: ${e.status}`);const t=await e.json();return t}catch(e){throw console.error("Error in apiFilesModify:",e),e}}async function apiFilesDelete(e){const t="./api/files/delete",n={method:"POST",headers:{"Content-Type":"application/json",apikey:systemKey,id:e}};try{const e=await fetch(t,n);if(!e.ok)throw new Error(`Request failed with status: ${e.status}`)}catch(e){throw console.error("Error in apiFilesDelete:",e),e}}var dropzoneObject,calendarInstance,statusItemCount,clipboard=new ClipboardJS(".btn"),isE2EEnabled=!1,isUploading=!1,rowCount=-1;window.addEventListener("beforeunload",e=>{isUploading&&(e.returnValue="Upload is still in progress. Do you want to close this page?")}),Dropzone.options.uploaddropzone={paramName:"file",dictDefaultMessage:"Drop files, paste or click here to upload",createImageThumbnails:!1,chunksUploaded:function(e,t){sendChunkComplete(e,t)},init:function(){dropzoneObject=this,this.on("addedfile",e=>{saveUploadDefaults(),addFileProgress(e)}),this.on("queuecomplete",function(){isUploading=!1}),this.on("sending",function(){isUploading=!0}),this.on("error",function(e,t,n){n&&n.status===413?showError(e,"File too large to upload. If you are using a reverse proxy, make sure that the allowed body size is at least 70MB."):showError(e,"Error: "+t)}),this.on("uploadprogress",function(e,t,n){updateProgressbar(e,t,n)}),isE2EEnabled&&(dropzoneObject.disable(),dropzoneObject.options.dictDefaultMessage="Loading end-to-end encryption...",document.getElementsByClassName("dz-button")[0].innerText="Loading end-to-end encryption...",setE2eUpload())}};function updateProgressbar(e,t,n){let o=e.upload.uuid,i=document.getElementById(`us-container-${o}`);if(i==null||i.getAttribute("data-complete")==="true")return;let s=Math.round(t);s<0&&(s=0),s>100&&(s=100);let r=Date.now()-i.getAttribute("data-starttime"),c=n/(r/1e3)/1024/1024;document.getElementById(`us-progressbar-${o}`).style.width=s+"%";let a=Math.round(c*10)/10;Number.isNaN(a)||(document.getElementById(`us-progress-info-${o}`).innerText=s+"% - "+a+"MB/s")}function addFileProgress(e){addFileStatus(e.upload.uuid,e.upload.filename)}document.onpaste=function(e){if(dropzoneObject.disabled)return;var t,n=(e.clipboardData||e.originalEvent.clipboardData).items;for(let e in n)t=n[e],t.kind==="file"&&dropzoneObject.addFile(t.getAsFile()),t.kind==="string"&&t.getAsString(function(e){const t=//gi;if(t.test(e)===!1){let t=new Blob([e],{type:"text/plain"}),n=new File([t],"Pasted Text.txt",{type:"text/plain",lastModified:new Date(0)});dropzoneObject.addFile(n)}})};function setUploadDefaults(){let s=getLocalStorageWithDefault("defaultDownloads",1),o=getLocalStorageWithDefault("defaultExpiry",14),e=getLocalStorageWithDefault("defaultPassword",""),t=getLocalStorageWithDefault("defaultUnlimitedDownloads",!1)==="true",n=getLocalStorageWithDefault("defaultUnlimitedTime",!1)==="true";document.getElementById("allowedDownloads").value=s,document.getElementById("expiryDays").value=o,document.getElementById("password").value=e,document.getElementById("enableDownloadLimit").checked=!t,document.getElementById("enableTimeLimit").checked=!n,e===""?(document.getElementById("enablePassword").checked=!1,document.getElementById("password").disabled=!0):(document.getElementById("enablePassword").checked=!0,document.getElementById("password").disabled=!1),t&&(document.getElementById("allowedDownloads").disabled=!0),n&&(document.getElementById("expiryDays").disabled=!0)}function saveUploadDefaults(){localStorage.setItem("defaultDownloads",document.getElementById("allowedDownloads").value),localStorage.setItem("defaultExpiry",document.getElementById("expiryDays").value),localStorage.setItem("defaultPassword",document.getElementById("password").value),localStorage.setItem("defaultUnlimitedDownloads",!document.getElementById("enableDownloadLimit").checked),localStorage.setItem("defaultUnlimitedTime",!document.getElementById("enableTimeLimit").checked)}function getLocalStorageWithDefault(e,t){var n=localStorage.getItem(e);return n===null?t:n}function urlencodeFormData(e){let t="";function s(e){return encodeURIComponent(e).replace(/%20/g,"+")}for(var n of e.entries())typeof n[1]=="string"&&(t+=(t?"&":"")+s(n[0])+"="+s(n[1]));return t}function sendChunkComplete(e,t){var s=new XMLHttpRequest;s.open("POST","./uploadComplete",!0),s.setRequestHeader("Content-Type","application/x-www-form-urlencoded");let n=new FormData;n.append("allowedDownloads",document.getElementById("allowedDownloads").value),n.append("expiryDays",document.getElementById("expiryDays").value),n.append("password",document.getElementById("password").value),n.append("isUnlimitedDownload",!document.getElementById("enableDownloadLimit").checked),n.append("isUnlimitedTime",!document.getElementById("enableTimeLimit").checked),n.append("chunkid",e.upload.uuid),e.isEndToEndEncrypted===!0?(n.append("filesize",e.sizeEncrypted),n.append("filename","Encrypted File"),n.append("filecontenttype",""),n.append("isE2E","true"),n.append("realSize",e.size)):(n.append("filesize",e.size),n.append("filename",e.name),n.append("filecontenttype",e.type)),s.onreadystatechange=function(){if(this.readyState==4)if(this.status==200){t();let n=document.getElementById(`us-progress-info-${e.upload.uuid}`);n!=null&&(n.innerText="In Queue...")}else dropzoneUploadError(e,getErrorMessage(s.responseText))},s.send(urlencodeFormData(n))}function dropzoneUploadError(e,t){e.accepted=!1,dropzoneObject._errorProcessing([e],t),showError(e,t)}function getErrorMessage(e){let t;try{t=JSON.parse(e)}catch{return"Unknown error: Server could not process file"}return"Error: "+t.ErrorMessage}function dropzoneGetFile(e){for(let t=0;t{addRow(n);let s=dropzoneGetFile(t);if(s==null)return;if(s.isEndToEndEncrypted===!0){try{let o=GokapiE2EAddFile(t,e,s.name);if(o instanceof Error)throw o;let n=GokapiE2EInfoEncrypt();if(n instanceof Error)throw n;storeE2EInfo(n)}catch(e){s.accepted=!1,dropzoneObject._errorProcessing([s],e);return}GokapiE2EDecryptMenu()}removeFileStatus(t)}).catch(e=>{let n=dropzoneGetFile(t);n!=null&&dropzoneUploadError(n,e),console.error("Error:",e)})}function addFriendlyNameChange(){document.querySelectorAll(".apiname").forEach(function(e){e.onclick=function(){if(this.classList.contains("isBeingEdited"))return;this.classList.add("isBeingEdited");var o=this.innerHTML,e=document.createElement("input");e.size=5,e.value=o;let t=this,n=!0,s=function(){if(!n)return;n=!1;var s=e.value;e.parentNode.innerHTML=s,t.classList.remove("isBeingEdited"),apiAuthFriendlyName(t.id,s).catch(e=>{alert("Unable to save name: "+e),console.error("Error:",e)})};e.onblur=s,e.addEventListener("keyup",function(e){e.keyCode===13&&(e.preventDefault(),s())}),this.innerHTML="",this.appendChild(e),e.focus()}})}function parseProgressStatus(e){let n=document.getElementById(`us-container-${e.chunk_id}`);if(n==null)return;n.setAttribute("data-complete","true");let t;switch(e.upload_status){case 0:t="Processing file...";break;case 1:t="Uploading file...";break;case 2:t="Finalising...",requestFileInfo(e.file_id,e.chunk_id);break;case 3:t="Error";let n=dropzoneGetFile(e.chunk_id);e.error_message==""&&(e.error_message="Server Error"),n!=null&&dropzoneUploadError(n,e.error_message);return;default:t="Unknown status";break}document.getElementById(`us-progress-info-${e.chunk_id}`).innerText=t}function showError(e,t){let n=e.upload.uuid;document.getElementById(`us-progressbar-${n}`).style.width="100%",document.getElementById(`us-progressbar-${n}`).style.backgroundColor="red",document.getElementById(`us-progress-info-${n}`).innerText=t,document.getElementById(`us-progress-info-${n}`).classList.add("uploaderror")}function editFile(){const e=document.getElementById("mb_save");e.disabled=!0;let n=e.getAttribute("data-fileid"),s=document.getElementById("mi_edit_down").value,o=document.getElementById("mi_edit_expiry").value,t=document.getElementById("mi_edit_pw").value,i=t==="(unchanged)";document.getElementById("mc_download").checked||(s=0),document.getElementById("mc_expiry").checked||(o=0),document.getElementById("mc_password").checked||(i=!1,t="");let a=!1,r="";document.getElementById("mc_replace").checked&&(a=!0,r=document.getElementById("mi_edit_replace").value),apiFilesModify(n,s,o,t,i).then(t=>{if(!a){location.reload();return}apiFilesReplace(n,r).then(e=>{location.reload()}).catch(t=>{alert("Unable to edit file: "+t),console.error("Error:",t),e.disabled=!1})}).catch(t=>{alert("Unable to edit file: "+t),console.error("Error:",t),e.disabled=!1})}calendarInstance=null;function createCalendar(e){const t=new Date(e*1e3);calendarInstance=flatpickr("#mi_edit_expiry",{enableTime:!0,dateFormat:"U",altInput:!0,altFormat:"Y-m-d H:i",allowInput:!0,time_24hr:!0,defaultDate:t,minDate:"today"})}function handleEditCheckboxChange(e){var t=document.getElementById(e.getAttribute("data-toggle-target")),n=e.getAttribute("data-timestamp");e.checked?(t.classList.remove("disabled"),t.removeAttribute("disabled"),n!=null&&(calendarInstance._input.disabled=!1)):(n!=null&&(calendarInstance._input.disabled=!0),t.classList.add("disabled"),t.setAttribute("disabled",!0))}function showEditModal(e,t,n,s,o,i,a,r){document.getElementById("m_filenamelabel").innerHTML=e,document.getElementById("mc_expiry").setAttribute("data-timestamp",s),document.getElementById("mb_save").setAttribute("data-fileid",t),createCalendar(s),i?(document.getElementById("mi_edit_down").value="1",document.getElementById("mi_edit_down").disabled=!0,document.getElementById("mc_download").checked=!1):(document.getElementById("mi_edit_down").value=n,document.getElementById("mi_edit_down").disabled=!1,document.getElementById("mc_download").checked=!0),a?(document.getElementById("mi_edit_expiry").value=add14DaysIfBeforeCurrentTime(s),document.getElementById("mi_edit_expiry").disabled=!0,document.getElementById("mc_expiry").checked=!1,calendarInstance._input.disabled=!0):(document.getElementById("mi_edit_expiry").value=s,document.getElementById("mi_edit_expiry").disabled=!1,document.getElementById("mc_expiry").checked=!0,calendarInstance._input.disabled=!1),o?(document.getElementById("mi_edit_pw").value="(unchanged)",document.getElementById("mi_edit_pw").disabled=!1,document.getElementById("mc_password").checked=!0):(document.getElementById("mi_edit_pw").value="",document.getElementById("mi_edit_pw").disabled=!0,document.getElementById("mc_password").checked=!1);let c=document.getElementById("mi_edit_replace");if(r)document.getElementById("mc_replace").disabled=!0,document.getElementById("mc_replace").title="Replacing content is not available for end-to-end encrypted files",c.add(new Option("Unavailable",0)),c.title="Replacing content is not available for end-to-end encrypted files",c.value="0";else{let e=getAllAvailableFiles();for(let n=0;n{o?s.classList.add("apiperm-notgranted"):s.classList.add("apiperm-granted"),s.classList.remove("apiperm-processing")}).catch(e=>{o?s.classList.add("apiperm-granted"):s.classList.add("apiperm-notgranted"),s.classList.remove("apiperm-processing"),alert("Unable to set permission: "+e),console.error("Error:",e)})}function deleteApiKey(e){document.getElementById("delete-"+e).disabled=!0,apiAuthDelete(e).then(t=>{document.getElementById("row-"+e).remove()}).catch(e=>{alert("Unable to delete API key: "+e),console.error("Error:",e)})}function newApiKey(){document.getElementById("button-newapi").disabled=!0,apiAuthCreate().then(e=>{location.reload()}).catch(e=>{alert("Unable to create API key: "+e),console.error("Error:",e)})}function deleteFile(e){document.getElementById("button-delete-"+e).disabled=!0,apiFilesDelete(e).then(e=>{location.reload()}).catch(e=>{alert("Unable to delete file: "+e),console.error("Error:",e)})}function checkBoxChanged(e,t){let n=!e.checked;n?document.getElementById(t).setAttribute("disabled",""):document.getElementById(t).removeAttribute("disabled"),t==="password"&&n&&(document.getElementById("password").value="")}function parseSseData(e){let t;try{t=JSON.parse(e)}catch(e){console.error("Failed to parse event data:",e);return}switch(t.event){case"download":setNewDownloadCount(t.file_id,t.download_count,t.downloads_remaining);return;case"uploadStatus":parseProgressStatus(t);return;default:console.error("Unknown event",t)}}function setNewDownloadCount(e,t,n){let s=document.getElementById("cell-downloads-"+e);if(s!=null&&(s.innerHTML=t,s.classList.add("updatedDownloadCount"),setTimeout(()=>s.classList.remove("updatedDownloadCount"),500)),n!=-1){let t=document.getElementById("cell-downloadsRemaining-"+e);t!=null&&(t.innerHTML=n,t.classList.add("updatedDownloadCount"),setTimeout(()=>t.classList.remove("updatedDownloadCount"),500))}}function registerChangeHandler(){const e=new EventSource("./uploadStatus");e.onmessage=e=>{parseSseData(e.data)},e.onerror=t=>{t.target.readyState!==EventSource.CLOSED&&e.close(),console.log("Reconnecting to SSE..."),setTimeout(registerChangeHandler,5e3)}}statusItemCount=0;function addFileStatus(e,t){const n=document.createElement("div");n.setAttribute("id",`us-container-${e}`),n.classList.add("us-container");const a=document.createElement("div");a.classList.add("filename"),a.textContent=t,n.appendChild(a);const s=document.createElement("div");s.classList.add("upload-progress-container"),s.setAttribute("id",`us-progress-container-${e}`);const r=document.createElement("div");r.classList.add("upload-progress-bar");const o=document.createElement("div");o.setAttribute("id",`us-progressbar-${e}`),o.classList.add("upload-progress-bar-progress"),o.style.width="0%",r.appendChild(o);const i=document.createElement("div");i.setAttribute("id",`us-progress-info-${e}`),i.classList.add("upload-progress-info"),i.textContent="0%",s.appendChild(r),s.appendChild(i),n.appendChild(s),n.setAttribute("data-starttime",Date.now()),n.setAttribute("data-complete","false");const c=document.getElementById("uploadstatus");c.appendChild(n),c.style.visibility="visible",statusItemCount++}function removeFileStatus(e){const t=document.getElementById(`us-container-${e}`);if(t==null)return;t.remove(),statusItemCount--,statusItemCount<1&&(document.getElementById("uploadstatus").style.visibility="hidden")}function addRow(e){let m=document.getElementById("downloadtable"),n=m.insertRow(0);n.id="row-"+e.Id;let r=n.insertCell(0),i=n.insertCell(1),s=n.insertCell(2),a=n.insertCell(3),o=n.insertCell(4),c=n.insertCell(5),l=n.insertCell(6),d="";e.IsPasswordProtected===!0&&(d=' '),r.innerText=e.Name,r.id="cell-name-"+e.Id,o.id="cell-downloads-"+e.Id,i.innerText=e.Size,e.UnlimitedDownloads?s.innerText="Unlimited":(s.innerText=e.DownloadsRemaining,s.id="cell-downloadsRemaining-"+e.Id),e.UnlimitedTime?a.innerText="Unlimited":a.innerText=e.ExpireAtString,o.innerHTML="0",c.innerHTML=''+e.Id+""+d;let t=' ';e.UrlHotlink===""?t=t+' ':t=t+' ',t=t+' `,t=t+` ',t=t+'`,l.innerHTML=t,r.classList.add("newItem"),i.classList.add("newItem"),s.classList.add("newItem"),s.style.backgroundColor="green",a.classList.add("newItem"),o.classList.add("newItem"),o.style.backgroundColor="green",c.classList.add("newItem"),l.classList.add("newItem"),i.setAttribute("data-order",e.SizeBytes);let u=$("#maintable").DataTable();rowCount==-1&&(rowCount=u.rows().count()),rowCount=rowCount+1,u.row.add(n);let h=document.getElementsByClassName("dataTables_empty")[0];return typeof h!="undefined"?h.innerText="Files stored: "+rowCount:document.getElementsByClassName("dataTables_info")[0].innerText="Files stored: "+rowCount,e.Id}function hideQrCode(){document.getElementById("qroverlay").style.display="none",document.getElementById("qrcode").innerHTML=""}function showQrCode(e){const t=document.getElementById("qroverlay");t.style.display="block",new QRCode(document.getElementById("qrcode"),{text:e,width:200,height:200,colorDark:"#000000",colorLight:"#ffffff",correctLevel:QRCode.CorrectLevel.H}),t.addEventListener("click",hideQrCode)}function showToast(){let e=document.getElementById("toastnotification");e.classList.add("show"),setTimeout(()=>{e.classList.remove("show")},1e3)} \ No newline at end of file +async function apiAuthModify(e,t,n){const s="./api/auth/modify",o={method:"POST",headers:{"Content-Type":"application/json",apikey:systemKey,apiKeyToModify:e,permission:t,permissionModifier:n}};try{const e=await fetch(s,o);if(!e.ok)throw new Error(`Request failed with status: ${e.status}`)}catch(e){throw console.error("Error in apiAuthModify:",e),e}}async function apiAuthFriendlyName(e,t){const n="./api/auth/friendlyname",s={method:"PUT",headers:{"Content-Type":"application/json",apikey:systemKey,apiKeyToModify:e,friendlyName:t}};try{const e=await fetch(n,s);if(!e.ok)throw new Error(`Request failed with status: ${e.status}`)}catch(e){throw console.error("Error in apiAuthModify:",e),e}}async function apiAuthDelete(e){const t="./api/auth/delete",n={method:"POST",headers:{"Content-Type":"application/json",apikey:systemKey,apiKeyToModify:e}};try{const e=await fetch(t,n);if(!e.ok)throw new Error(`Request failed with status: ${e.status}`)}catch(e){throw console.error("Error in apiAuthDelete:",e),e}}async function apiAuthCreate(){const e="./api/auth/create",t={method:"POST",headers:{"Content-Type":"application/json",apikey:systemKey,basicPermissions:"true"}};try{const n=await fetch(e,t);if(!n.ok)throw new Error(`Request failed with status: ${n.status}`);const s=await n.json();return s}catch(e){throw console.error("Error in apiAuthCreate:",e),e}}async function apiFilesReplace(e,t){const n="./api/files/replace",s={method:"PUT",headers:{"Content-Type":"application/json",id:e,apikey:systemKey,idNewContent:t,deleteNewFile:!1}};try{const e=await fetch(n,s);if(!e.ok)throw new Error(`Request failed with status: ${e.status}`);const t=await e.json();return t}catch(e){throw console.error("Error in apiFilesReplace:",e),e}}async function apiFilesListById(e){const t="./api/files/list/"+e,n={method:"GET",headers:{"Content-Type":"application/json",apikey:systemKey}};try{const e=await fetch(t,n);if(!e.ok)throw new Error(`Request failed with status: ${e.status}`);const s=await e.json();return s}catch(e){throw console.error("Error in apiFilesListById:",e),e}}async function apiFilesModify(e,t,n,s,o){const i="./api/files/modify",a={method:"PUT",headers:{"Content-Type":"application/json",id:e,apikey:systemKey,allowedDownloads:t,expiryTimestamp:n,password:s,originalPassword:o}};try{const e=await fetch(i,a);if(!e.ok)throw new Error(`Request failed with status: ${e.status}`);const t=await e.json();return t}catch(e){throw console.error("Error in apiFilesModify:",e),e}}async function apiFilesDelete(e){const t="./api/files/delete",n={method:"POST",headers:{"Content-Type":"application/json",apikey:systemKey,id:e}};try{const e=await fetch(t,n);if(!e.ok)throw new Error(`Request failed with status: ${e.status}`)}catch(e){throw console.error("Error in apiFilesDelete:",e),e}}var dropzoneObject,calendarInstance,statusItemCount,clipboard=new ClipboardJS(".btn"),isE2EEnabled=!1,isUploading=!1,rowCount=-1;window.addEventListener("beforeunload",e=>{isUploading&&(e.returnValue="Upload is still in progress. Do you want to close this page?")}),Dropzone.options.uploaddropzone={paramName:"file",dictDefaultMessage:"Drop files, paste or click here to upload",createImageThumbnails:!1,chunksUploaded:function(e,t){sendChunkComplete(e,t)},init:function(){dropzoneObject=this,this.on("addedfile",e=>{saveUploadDefaults(),addFileProgress(e)}),this.on("queuecomplete",function(){isUploading=!1}),this.on("sending",function(){isUploading=!0}),this.on("error",function(e,t,n){n&&n.status===413?showError(e,"File too large to upload. If you are using a reverse proxy, make sure that the allowed body size is at least 70MB."):showError(e,"Error: "+t)}),this.on("uploadprogress",function(e,t,n){updateProgressbar(e,t,n)}),isE2EEnabled&&(dropzoneObject.disable(),dropzoneObject.options.dictDefaultMessage="Loading end-to-end encryption...",document.getElementsByClassName("dz-button")[0].innerText="Loading end-to-end encryption...",setE2eUpload())}};function updateProgressbar(e,t,n){let o=e.upload.uuid,i=document.getElementById(`us-container-${o}`);if(i==null||i.getAttribute("data-complete")==="true")return;let s=Math.round(t);s<0&&(s=0),s>100&&(s=100);let r=Date.now()-i.getAttribute("data-starttime"),c=n/(r/1e3)/1024/1024;document.getElementById(`us-progressbar-${o}`).style.width=s+"%";let a=Math.round(c*10)/10;Number.isNaN(a)||(document.getElementById(`us-progress-info-${o}`).innerText=s+"% - "+a+"MB/s")}function addFileProgress(e){addFileStatus(e.upload.uuid,e.upload.filename)}document.onpaste=function(e){if(dropzoneObject.disabled)return;var t,n=(e.clipboardData||e.originalEvent.clipboardData).items;for(let e in n)t=n[e],t.kind==="file"&&dropzoneObject.addFile(t.getAsFile()),t.kind==="string"&&t.getAsString(function(e){const t=//gi;if(t.test(e)===!1){let t=new Blob([e],{type:"text/plain"}),n=new File([t],"Pasted Text.txt",{type:"text/plain",lastModified:new Date(0)});dropzoneObject.addFile(n)}})};function setUploadDefaults(){let s=getLocalStorageWithDefault("defaultDownloads",1),o=getLocalStorageWithDefault("defaultExpiry",14),e=getLocalStorageWithDefault("defaultPassword",""),t=getLocalStorageWithDefault("defaultUnlimitedDownloads",!1)==="true",n=getLocalStorageWithDefault("defaultUnlimitedTime",!1)==="true";document.getElementById("allowedDownloads").value=s,document.getElementById("expiryDays").value=o,document.getElementById("password").value=e,document.getElementById("enableDownloadLimit").checked=!t,document.getElementById("enableTimeLimit").checked=!n,e===""?(document.getElementById("enablePassword").checked=!1,document.getElementById("password").disabled=!0):(document.getElementById("enablePassword").checked=!0,document.getElementById("password").disabled=!1),t&&(document.getElementById("allowedDownloads").disabled=!0),n&&(document.getElementById("expiryDays").disabled=!0)}function saveUploadDefaults(){localStorage.setItem("defaultDownloads",document.getElementById("allowedDownloads").value),localStorage.setItem("defaultExpiry",document.getElementById("expiryDays").value),localStorage.setItem("defaultPassword",document.getElementById("password").value),localStorage.setItem("defaultUnlimitedDownloads",!document.getElementById("enableDownloadLimit").checked),localStorage.setItem("defaultUnlimitedTime",!document.getElementById("enableTimeLimit").checked)}function getLocalStorageWithDefault(e,t){var n=localStorage.getItem(e);return n===null?t:n}function urlencodeFormData(e){let t="";function s(e){return encodeURIComponent(e).replace(/%20/g,"+")}for(var n of e.entries())typeof n[1]=="string"&&(t+=(t?"&":"")+s(n[0])+"="+s(n[1]));return t}function sendChunkComplete(e,t){var s=new XMLHttpRequest;s.open("POST","./uploadComplete",!0),s.setRequestHeader("Content-Type","application/x-www-form-urlencoded");let n=new FormData;n.append("allowedDownloads",document.getElementById("allowedDownloads").value),n.append("expiryDays",document.getElementById("expiryDays").value),n.append("password",document.getElementById("password").value),n.append("isUnlimitedDownload",!document.getElementById("enableDownloadLimit").checked),n.append("isUnlimitedTime",!document.getElementById("enableTimeLimit").checked),n.append("chunkid",e.upload.uuid),e.isEndToEndEncrypted===!0?(n.append("filesize",e.sizeEncrypted),n.append("filename","Encrypted File"),n.append("filecontenttype",""),n.append("isE2E","true"),n.append("realSize",e.size)):(n.append("filesize",e.size),n.append("filename",e.name),n.append("filecontenttype",e.type)),s.onreadystatechange=function(){if(this.readyState==4)if(this.status==200){t();let n=document.getElementById(`us-progress-info-${e.upload.uuid}`);n!=null&&(n.innerText="In Queue...")}else dropzoneUploadError(e,getErrorMessage(s.responseText))},s.send(urlencodeFormData(n))}function dropzoneUploadError(e,t){e.accepted=!1,dropzoneObject._errorProcessing([e],t),showError(e,t)}function getErrorMessage(e){let t;try{t=JSON.parse(e)}catch{return"Unknown error: Server could not process file"}return"Error: "+t.ErrorMessage}function dropzoneGetFile(e){for(let t=0;t{addRow(n);let s=dropzoneGetFile(t);if(s==null)return;if(s.isEndToEndEncrypted===!0){try{let o=GokapiE2EAddFile(t,e,s.name);if(o instanceof Error)throw o;let n=GokapiE2EInfoEncrypt();if(n instanceof Error)throw n;storeE2EInfo(n)}catch(e){s.accepted=!1,dropzoneObject._errorProcessing([s],e);return}GokapiE2EDecryptMenu()}removeFileStatus(t)}).catch(e=>{let n=dropzoneGetFile(t);n!=null&&dropzoneUploadError(n,e),console.error("Error:",e)})}function parseProgressStatus(e){let n=document.getElementById(`us-container-${e.chunk_id}`);if(n==null)return;n.setAttribute("data-complete","true");let t;switch(e.upload_status){case 0:t="Processing file...";break;case 1:t="Uploading file...";break;case 2:t="Finalising...",requestFileInfo(e.file_id,e.chunk_id);break;case 3:t="Error";let n=dropzoneGetFile(e.chunk_id);e.error_message==""&&(e.error_message="Server Error"),n!=null&&dropzoneUploadError(n,e.error_message);return;default:t="Unknown status";break}document.getElementById(`us-progress-info-${e.chunk_id}`).innerText=t}function showError(e,t){let n=e.upload.uuid;document.getElementById(`us-progressbar-${n}`).style.width="100%",document.getElementById(`us-progressbar-${n}`).style.backgroundColor="red",document.getElementById(`us-progress-info-${n}`).innerText=t,document.getElementById(`us-progress-info-${n}`).classList.add("uploaderror")}function editFile(){const e=document.getElementById("mb_save");e.disabled=!0;let n=e.getAttribute("data-fileid"),s=document.getElementById("mi_edit_down").value,o=document.getElementById("mi_edit_expiry").value,t=document.getElementById("mi_edit_pw").value,i=t==="(unchanged)";document.getElementById("mc_download").checked||(s=0),document.getElementById("mc_expiry").checked||(o=0),document.getElementById("mc_password").checked||(i=!1,t="");let a=!1,r="";document.getElementById("mc_replace").checked&&(a=!0,r=document.getElementById("mi_edit_replace").value),apiFilesModify(n,s,o,t,i).then(t=>{if(!a){location.reload();return}apiFilesReplace(n,r).then(e=>{location.reload()}).catch(t=>{alert("Unable to edit file: "+t),console.error("Error:",t),e.disabled=!1})}).catch(t=>{alert("Unable to edit file: "+t),console.error("Error:",t),e.disabled=!1})}calendarInstance=null;function createCalendar(e){const t=new Date(e*1e3);calendarInstance=flatpickr("#mi_edit_expiry",{enableTime:!0,dateFormat:"U",altInput:!0,altFormat:"Y-m-d H:i",allowInput:!0,time_24hr:!0,defaultDate:t,minDate:"today"})}function handleEditCheckboxChange(e){var t=document.getElementById(e.getAttribute("data-toggle-target")),n=e.getAttribute("data-timestamp");e.checked?(t.classList.remove("disabled"),t.removeAttribute("disabled"),n!=null&&(calendarInstance._input.disabled=!1)):(n!=null&&(calendarInstance._input.disabled=!0),t.classList.add("disabled"),t.setAttribute("disabled",!0))}function showEditModal(e,t,n,s,o,i,a,r){document.getElementById("m_filenamelabel").innerHTML=e,document.getElementById("mc_expiry").setAttribute("data-timestamp",s),document.getElementById("mb_save").setAttribute("data-fileid",t),createCalendar(s),i?(document.getElementById("mi_edit_down").value="1",document.getElementById("mi_edit_down").disabled=!0,document.getElementById("mc_download").checked=!1):(document.getElementById("mi_edit_down").value=n,document.getElementById("mi_edit_down").disabled=!1,document.getElementById("mc_download").checked=!0),a?(document.getElementById("mi_edit_expiry").value=add14DaysIfBeforeCurrentTime(s),document.getElementById("mi_edit_expiry").disabled=!0,document.getElementById("mc_expiry").checked=!1,calendarInstance._input.disabled=!0):(document.getElementById("mi_edit_expiry").value=s,document.getElementById("mi_edit_expiry").disabled=!1,document.getElementById("mc_expiry").checked=!0,calendarInstance._input.disabled=!1),o?(document.getElementById("mi_edit_pw").value="(unchanged)",document.getElementById("mi_edit_pw").disabled=!1,document.getElementById("mc_password").checked=!0):(document.getElementById("mi_edit_pw").value="",document.getElementById("mi_edit_pw").disabled=!0,document.getElementById("mc_password").checked=!1);let c=document.getElementById("mi_edit_replace");if(r)document.getElementById("mc_replace").disabled=!0,document.getElementById("mc_replace").title="Replacing content is not available for end-to-end encrypted files",c.add(new Option("Unavailable",0)),c.title="Replacing content is not available for end-to-end encrypted files",c.value="0";else{let e=getAllAvailableFiles();for(let n=0;n{o?s.classList.add("apiperm-notgranted"):s.classList.add("apiperm-granted"),s.classList.remove("apiperm-processing")}).catch(e=>{o?s.classList.add("apiperm-granted"):s.classList.add("apiperm-notgranted"),s.classList.remove("apiperm-processing"),alert("Unable to set permission: "+e),console.error("Error:",e)})}function deleteApiKey(e){document.getElementById("delete-"+e).disabled=!0,apiAuthDelete(e).then(t=>{document.getElementById("row-"+e).remove()}).catch(e=>{alert("Unable to delete API key: "+e),console.error("Error:",e)})}function newApiKey(){document.getElementById("button-newapi").disabled=!0,apiAuthCreate().then(e=>{addRowApi(e.Id),document.getElementById("button-newapi").disabled=!1}).catch(e=>{alert("Unable to create API key: "+e),console.error("Error:",e)})}function addFriendlyNameChange(e){let t=document.getElementById("friendlyname-"+e);if(t.classList.contains("isBeingEdited"))return;t.classList.add("isBeingEdited");let i=t.innerHTML,n=document.createElement("input");n.size=5,n.value=i;let s=!0,o=function(){if(!s)return;s=!1;let o=n.value;t.innerHTML=o,t.classList.remove("isBeingEdited"),apiAuthFriendlyName(e,o).catch(e=>{alert("Unable to save name: "+e),console.error("Error:",e)})};n.onblur=o,n.addEventListener("keyup",function(e){e.keyCode===13&&(e.preventDefault(),o())}),t.innerHTML="",t.appendChild(n),n.focus()}function addRowApi(e){let c=document.getElementById("apitable"),t=c.insertRow(0);t.id="row-"+e;let n=t.insertCell(0),s=t.insertCell(1),o=t.insertCell(2),i=t.insertCell(3),a=t.insertCell(4),r=t.insertCell(5);n.classList.add("newApiKey"),s.classList.add("newApiKey"),o.classList.add("newApiKey"),i.classList.add("newApiKey"),a.classList.add("newApiKey"),r.classList.add("newApiKey"),n.innerText="Unnamed key",n.id="friendlyname-"+e,n.onclick=function(){addFriendlyNameChange(e)},s.innerText=e,o.innerText="Never",a.innerHTML=' `,i.innerHTML=` + + + + + + `,setTimeout(()=>{n.classList.remove("newApiKey"),s.classList.remove("newApiKey"),o.classList.remove("newApiKey"),i.classList.remove("newApiKey"),a.classList.remove("newApiKey"),r.classList.remove("newApiKey")},700)}function deleteFile(e){document.getElementById("button-delete-"+e).disabled=!0,apiFilesDelete(e).then(e=>{location.reload()}).catch(e=>{alert("Unable to delete file: "+e),console.error("Error:",e)})}function checkBoxChanged(e,t){let n=!e.checked;n?document.getElementById(t).setAttribute("disabled",""):document.getElementById(t).removeAttribute("disabled"),t==="password"&&n&&(document.getElementById("password").value="")}function parseSseData(e){let t;try{t=JSON.parse(e)}catch(e){console.error("Failed to parse event data:",e);return}switch(t.event){case"download":setNewDownloadCount(t.file_id,t.download_count,t.downloads_remaining);return;case"uploadStatus":parseProgressStatus(t);return;default:console.error("Unknown event",t)}}function setNewDownloadCount(e,t,n){let s=document.getElementById("cell-downloads-"+e);if(s!=null&&(s.innerHTML=t,s.classList.add("updatedDownloadCount"),setTimeout(()=>s.classList.remove("updatedDownloadCount"),500)),n!=-1){let t=document.getElementById("cell-downloadsRemaining-"+e);t!=null&&(t.innerHTML=n,t.classList.add("updatedDownloadCount"),setTimeout(()=>t.classList.remove("updatedDownloadCount"),500))}}function registerChangeHandler(){const e=new EventSource("./uploadStatus");e.onmessage=e=>{parseSseData(e.data)},e.onerror=t=>{t.target.readyState!==EventSource.CLOSED&&e.close(),console.log("Reconnecting to SSE..."),setTimeout(registerChangeHandler,5e3)}}statusItemCount=0;function addFileStatus(e,t){const n=document.createElement("div");n.setAttribute("id",`us-container-${e}`),n.classList.add("us-container");const a=document.createElement("div");a.classList.add("filename"),a.textContent=t,n.appendChild(a);const s=document.createElement("div");s.classList.add("upload-progress-container"),s.setAttribute("id",`us-progress-container-${e}`);const r=document.createElement("div");r.classList.add("upload-progress-bar");const o=document.createElement("div");o.setAttribute("id",`us-progressbar-${e}`),o.classList.add("upload-progress-bar-progress"),o.style.width="0%",r.appendChild(o);const i=document.createElement("div");i.setAttribute("id",`us-progress-info-${e}`),i.classList.add("upload-progress-info"),i.textContent="0%",s.appendChild(r),s.appendChild(i),n.appendChild(s),n.setAttribute("data-starttime",Date.now()),n.setAttribute("data-complete","false");const c=document.getElementById("uploadstatus");c.appendChild(n),c.style.visibility="visible",statusItemCount++}function removeFileStatus(e){const t=document.getElementById(`us-container-${e}`);if(t==null)return;t.remove(),statusItemCount--,statusItemCount<1&&(document.getElementById("uploadstatus").style.visibility="hidden")}function addRow(e){let m=document.getElementById("downloadtable"),n=m.insertRow(0);n.id="row-"+e.Id;let r=n.insertCell(0),i=n.insertCell(1),s=n.insertCell(2),a=n.insertCell(3),o=n.insertCell(4),c=n.insertCell(5),l=n.insertCell(6),d="";e.IsPasswordProtected===!0&&(d=' '),r.innerText=e.Name,r.id="cell-name-"+e.Id,o.id="cell-downloads-"+e.Id,i.innerText=e.Size,e.UnlimitedDownloads?s.innerText="Unlimited":(s.innerText=e.DownloadsRemaining,s.id="cell-downloadsRemaining-"+e.Id),e.UnlimitedTime?a.innerText="Unlimited":a.innerText=e.ExpireAtString,o.innerHTML="0",c.innerHTML=''+e.Id+""+d;let t=' ';e.UrlHotlink===""?t=t+' ':t=t+' ',t=t+' `,t=t+` ',t=t+'`,l.innerHTML=t,r.classList.add("newItem"),i.classList.add("newItem"),s.classList.add("newItem"),s.style.backgroundColor="green",a.classList.add("newItem"),o.classList.add("newItem"),o.style.backgroundColor="green",c.classList.add("newItem"),l.classList.add("newItem"),i.setAttribute("data-order",e.SizeBytes);let u=$("#maintable").DataTable();rowCount==-1&&(rowCount=u.rows().count()),rowCount=rowCount+1,u.row.add(n);let h=document.getElementsByClassName("dataTables_empty")[0];return typeof h!="undefined"?h.innerText="Files stored: "+rowCount:document.getElementsByClassName("dataTables_info")[0].innerText="Files stored: "+rowCount,e.Id}function hideQrCode(){document.getElementById("qroverlay").style.display="none",document.getElementById("qrcode").innerHTML=""}function showQrCode(e){const t=document.getElementById("qroverlay");t.style.display="block",new QRCode(document.getElementById("qrcode"),{text:e,width:200,height:200,colorDark:"#000000",colorLight:"#ffffff",correctLevel:QRCode.CorrectLevel.H}),t.addEventListener("click",hideQrCode)}function showToast(){let e=document.getElementById("toastnotification");e.classList.add("show"),setTimeout(()=>{e.classList.remove("show")},1e3)} \ No newline at end of file diff --git a/internal/webserver/web/templates/html_api.tmpl b/internal/webserver/web/templates/html_api.tmpl index f7f6d42..950cbcb 100644 --- a/internal/webserver/web/templates/html_api.tmpl +++ b/internal/webserver/web/templates/html_api.tmpl @@ -21,11 +21,11 @@ - + {{ range .ApiKeys }} {{ if not .IsSystemKey }} - {{ .FriendlyName }} + {{ .FriendlyName }} {{ .Id }} {{ .GetReadableDate }} @@ -52,7 +52,6 @@ {{ template "footer" true }} diff --git a/internal/webserver/web/templates/html_users.tmpl b/internal/webserver/web/templates/html_users.tmpl deleted file mode 100644 index 6a03d1b..0000000 --- a/internal/webserver/web/templates/html_users.tmpl +++ /dev/null @@ -1,91 +0,0 @@ -{{ define "users" }} -{{ template "header" . }} -
-
-
-
-

API Keys

-
- Please visit the API documentation for more information about the API.
Click on the API key name to give it a new name. Permissions can be changed by clicking on them. -
-
-
- - - - - - - - - - - - -{{ range .Users }} - - - - - - - - -{{ end }} - -
NameEmailGroupPermissionsActions
{{ .Name }}{{ .Email }}{{ .UserLevel }} - -
-
-
-
-
API key copied to clipboard
-
-
- - -{{ template "footer" true }} -{{ end }}