neutral/public/javascripts/filexplorer.js

786 lines
32 KiB
JavaScript
Raw Normal View History

document.addEventListener("contextmenu", (e) => {
e.preventDefault()
})
2023-11-28 20:05:44 +00:00
explorer.createWindow(() => {
var inCopyOrCut = null;
const View = new ViewWindow({
title: `<i class="fa fa-folder"></i> Gestionnaire de fichiers`,
width: "1000px",
height: "600px"
})
2023-11-28 20:05:44 +00:00
2023-11-28 20:05:44 +00:00
goHomePath()
function goHomePath() {
const rFiles = post("FX_GET", "homepath")
rFiles.then((result) => {
loadFiles(result)
})
}
function goSharePath() {
const rFiles = post("FX_GET", "sharepath")
rFiles.then((result) => {
loadFiles(result)
})
}
View.setContent(`
<div class="fx-window">
<div class='fx-bar'>
<span id='${View.getViewTitle()}_home' class='btn-cover'><i class='fa fa-home'></i></span>
<span id='${View.getViewTitle()}_sharebtn' class='btn-cover'><i class="fa-solid fa-share-from-square"></i></span>
<input class='fx-root-input' type="text" id='${View.getViewTitle()}_rootInput'>
<div class='fx-bar-actions'>
<button id='${View.getViewTitle()}_newFolder' class='btn blue'><span><i class='fa fa-folder'></i> Nouv. dossier</span></button>
<button id='${View.getViewTitle()}_newFile' class='btn green'><span><i class="fa-solid fa-file-arrow-up"></i> Nouveau</span></button>
</div>
</div>
<div id='${View.getViewTitle()}_explorer' class='fx-explorer'>
<div style='font-size: 24px; margin-top: 225px;' class='t-center'>
<p><i class="fa-solid fa-rotate fa-spin"></i> Chargement en cours ...</p>
</div>
</div>
</div>
`)
const rootInput = getID(View.getViewTitle() + '_rootInput')
const explorer = getID(View.getViewTitle() + '_explorer')
const newFolder = getID(View.getViewTitle() + '_newFolder')
const newFile = getID(View.getViewTitle() + '_newFile')
const home = getID(View.getViewTitle() + '_home')
const sharebtn = getID(View.getViewTitle() + '_sharebtn')
2023-11-28 20:05:44 +00:00
View.ViewWindowDiv.addEventListener("contextmenu", () => {
if(inCopyOrCut != null) {
const dMenu = new DroppableMenu()
dMenu.add("paste", "<i class='fa fa-paste'></i> Coller")
dMenu.show()
dMenu.get("paste").addEventListener("click", () => {
console.log({newPath: rootInput.value, action: inCopyOrCut.action, file: inCopyOrCut.file, name: inCopyOrCut.file.name, orginalPath: inCopyOrCut.orginalPath})
dMenu.hide()
const reqFiles = post("FX_PASTE", {newPath: rootInput.value, action: inCopyOrCut.action, file: inCopyOrCut.file, name: inCopyOrCut.file.name, orginalPath: inCopyOrCut.orginalPath})
reqFiles.then((result) => {
if(result == "OK") {
const reqFiles = post("FX_GET", rootInput.value)
reqFiles.then((result) => {
loadFiles(result)
})
} else if(result == "NOT_PERMITTED") {
const reqFiles = post("FX_GET", rootInput.value)
reqFiles.then((result) => {
loadFiles(result)
})
View.createPopup({
title: `<i class='fa fa-warning'></i> Erreur`,
content: `<p class='yellow'>Vous n'avez pas les permissions pour coller ce fichier.</p>`
})
} else {
const reqFiles = post("FX_GET", rootInput.value)
reqFiles.then((result) => {
loadFiles(result)
})
View.createPopup({
title: `<i class='fa fa-warning'></i> Erreur`,
content: `<p class='yellow'>Une erreur est survenue.</p>`
})
}
})
inCopyOrCut = null
})
} else {
console.log("LISTENER : " + rootInput.value)
}
})
home.addEventListener("click", () => {
goHomePath()
})
sharebtn.addEventListener("click", () => {
goSharePath()
})
newFolder.addEventListener("click", () => {
View.createPopup({
2023-11-04 13:50:28 +00:00
title: `<i class='fa fa-folder'></i> Nouveau dossier`,
content: `
<input type='text' class='field' id='${View.getViewTitle()}_foldername'>
<div id='${View.getViewTitle()}_folderInfo'></div>
<button class='btn green' id='${View.getViewTitle()}_foldercreate'><span><i class='fa fa-add'></i> Créer</span></button>
`})
const foldername = getID(View.getViewTitle() + "_foldername")
const foldercreate = getID(View.getViewTitle() + "_foldercreate")
2023-11-28 20:05:44 +00:00
const folderInfo = new TextResponse(View.getViewTitle() + "_folderInfo")
folderInfo.setSize("13px")
foldercreate.addEventListener("click", () => {
folderInfo.clear()
if(foldername.value.length < 1) {
folderInfo.err("Le nom du dossier est trop court.")
return
}
const regex = new RegExp(/^[a-zA-Z0-9-_]+$/)
if(!regex.test(foldername.value) | foldername.value.replace(/\s/g, '').length < 1) {
folderInfo.err("Le nom du dossier est invalide.")
return
}
const reqFiles = post("FX_NEW_FOLDER", rootInput.value + "/" + foldername.value)
reqFiles.then((result) => {
if(result == "OK") {
View.destroyPopup(`<i class="fa fa-folder"></i> Nouveau dossier`)
const reqFiles = post("FX_GET", rootInput.value)
reqFiles.then((result) => {
loadFiles(result)
})
} else if(result == "EXIST") {
folderInfo.err("Le dossier existe déjà.")
} else if(result == "NOT_PERMITTED") {
folderInfo.err("Vous n'avez pas les permissions pour créer un dossier ici.")
} else {
folderInfo.err("Une erreur est survenue.")
}
})
})
})
// Create a new file with a popup wth 2 options, upload or create, if create give a input name or if upload, upload a file
newFile.addEventListener("click", () => {
View.createPopup({
2023-11-04 13:50:28 +00:00
title: `<i class='fa-solid fa-file-arrow-up'></i> Nouveau fichier`,
content: `
<input type='text' class='field' id='${View.getViewTitle()}_filename'>
<div id='${View.getViewTitle()}_fileInfo'></div>
<button class='btn green' id='${View.getViewTitle()}_filecreate'><span><i class='fa fa-add'></i> Créer</span></button>
<button class='btn blue' id='${View.getViewTitle()}_fileupload'><span><i class='fa fa-upload'></i> Upload</span></button>
`})
const filename = getID(View.getViewTitle() + "_filename")
const filecreate = getID(View.getViewTitle() + "_filecreate")
const fileupload = getID(View.getViewTitle() + "_fileupload")
2023-11-28 20:05:44 +00:00
const fileInfo = new TextResponse(View.getViewTitle() + "_fileInfo")
fileInfo.setSize("13px")
filecreate.addEventListener("click", () => {
fileInfo.clear()
if(filename.value.length < 1) {
fileInfo.err("Le nom du fichier est trop court.")
return
}
const regex = new RegExp(/^[a-zA-Z0-9-_.]+$/)
if(!regex.test(filename.value) | filename.value.replace(/\s/g, '').length < 1) {
fileInfo.err("Le nom du fichier est invalide.")
return
}
const reqFiles = post("FX_NEW_FILE", rootInput.value + "/" + filename.value)
reqFiles.then((result) => {
if(result == "OK") {
View.destroyPopup(`<i class="fa-solid fa-file-arrow-up"></i> Nouveau fichier`)
const reqFiles = post("FX_GET", rootInput.value)
reqFiles.then((result) => {
loadFiles(result)
})
} else if(result == "EXIST") {
fileInfo.err("Le fichier existe déjà.")
} else if(result == "NOT_PERMITTED") {
fileInfo.err("Vous n'avez pas les permissions pour créer un fichier ici.")
} else {
fileInfo.err("Une erreur est survenue.")
}
})
})
fileupload.addEventListener("click", () => {
fileInfo.clear()
View.destroyPopup(`<i class="fa-solid fa-file-arrow-up"></i> Nouveau fichier`)
View.createPopup({
2023-11-04 13:50:28 +00:00
title: `<i class='fa-solid fa-file-arrow-up'></i> Upload`,
content: `
<input type='file' class='field' id='${View.getViewTitle()}_fileuploadInput'>
<div id='${View.getViewTitle()}_fileuploadInfo'></div>
<button class='btn green' id='${View.getViewTitle()}_fileuploadBtn'><span><i class='fa fa-upload'></i> Upload</span></button>
`})
const fileuploadInput = getID(View.getViewTitle() + "_fileuploadInput")
const fileuploadBtn = getID(View.getViewTitle() + "_fileuploadBtn")
2023-11-28 20:05:44 +00:00
const fileuploadInfo = new TextResponse(View.getViewTitle() + "_fileuploadInfo")
fileuploadBtn.addEventListener("click", () => {
fileuploadInfo.clear()
if(fileuploadInput.files.length < 1) {
fileuploadInfo.err("Aucun fichier sélectionné.")
return
}
const file = fileuploadInput.files[0]
console.log(file)
const reqFiles = post("FX_UPLOAD", {name: file.name ,root: rootInput.value, file: file})
reqFiles.then((result) => {
if(result == "OK") {
View.destroyPopup(`<i class="fa-solid fa-file-arrow-up"></i> Upload`)
const reqFiles = post("FX_GET", rootInput.value)
reqFiles.then((result) => {
loadFiles(result)
})
}
if(result == "EXIST") {
fileuploadInfo.err("Le fichier existe déjà.")
}
if(result == "NOT_PERMITTED") {
fileuploadInfo.err("Vous n'avez pas les permissions pour uploader un fichier ici.")
}
if(result == "NOT_FILE") {
fileuploadInfo.err("Le fichier n'est pas valide.")
}
if(result == "NOT_EXIST") {
fileuploadInfo.err("Le fichier n'existe pas.")
}
if(result == "TOO_BIG") {
fileuploadInfo.err("Le fichier est trop volumineux.")
}
if(result == "ERROR") {
fileuploadInfo.err("Une erreur est survenue.")
}
})
})
})
})
rootInput.addEventListener("change", () => {
const reqFiles = post("FX_GET", rootInput.value)
reqFiles.then((result) => {
loadFiles(result)
})
})
function loadFiles(files) {
rootInput.value = files.root
var fileElements = new Array()
if(files.content == "NOT_PERMITTED") {
fileElements.unshift(`<div id='fx-parent' class='fx-element'><p><i class="fa-solid fa-rotate-left"></i> Revenir au dossier parent </p></div>`)
fileElements.push("<p class='yellow' style='text-align: center;'><i class='fa fa-warning'></i> Vous n'avez pas les permissions pour accéder à ce dossier.</p>")
} else if(files.content == "NOT_EXIST") {
fileElements.unshift(`<div id='fx-parent' class='fx-element'><p><i class="fa-solid fa-rotate-left"></i> Revenir au dossier parent </p></div>`)
explorer.innerHTML = "<p class='yellow' style='text-align: center;'><i class='fa fa-warning'></i> Ce dossier n'existe pas.</p>"
} else {
for(const file of files.content) {
if(file.directory) {
file.size = "Dossier"
} else {
console.log('------------')
console.log(file.size)
console.log(bytesToSize(file.size))
console.log('------------')
file.size = bytesToSize(file.size)
}
fileElements.push(`<div id='${file.id}' class='fx-element'>
<div>
${getIcon(file)}
<p>${file.name}</p>
</div>
<p>Taille : ${file.size}</p>
<p>Date de modification : ${getFormattedDate(file.lastedition)}</p>
</div>`)
}
// Sort the files by directory and then by name
fileElements.sort((a, b) => {
if(a.includes("Dossier") && !b.includes("Dossier")) {
return -1
} else if(!a.includes("Dossier") && b.includes("Dossier")) {
return 1
} else {
return 0
}
})
fileElements.unshift(`<div id='fx-parent' class='fx-element'><p><i class="fa-solid fa-rotate-left"></i> Revenir au dossier parent </p></div>`)
}
explorer.innerHTML = fileElements.join("")
const parent = document.getElementById("fx-parent")
parent.addEventListener("click", () => {
const reqFiles = post("FX_GET", files.parent)
reqFiles.then((result) => {
loadFiles(result)
})
})
if(files.content != "NOT_PERMITTED" && files.content != "NOT_EXIST") {
// If it's a directory, get the file directory and make the request to get the files in it and loadIt
for(const file of files.content) {
2023-11-28 20:05:44 +00:00
const element = document.getElementById(file.id)
if(file.directory) {
element.addEventListener("click", () => {
const reqFiles = post("FX_GET", file.fileDirectory)
reqFiles.then((result) => {
loadFiles(result)
})
})
} else {
element.addEventListener("dblclick", () => {
editFile()
})
2023-11-28 20:05:44 +00:00
}
2023-11-28 20:05:44 +00:00
2023-11-28 20:05:44 +00:00
getID(file.id).addEventListener("contextmenu", () => {
2023-11-28 20:05:44 +00:00
const dropMenu = new DroppableMenu()
2023-11-28 20:05:44 +00:00
if(!file.directory) {
dropMenu.add("edit", "<i class='fa-solid fa-pen'></i> Editer")
dropMenu.add("share", "<i class='fa fa-share'></i> Partager")
dropMenu.add("download", "<i class='fa fa-download'></i> Télécharger")
}
dropMenu.add("copy", "<i class='fa fa-copy'></i> Copier")
dropMenu.add("cut", "<i class='fa fa-cut'></i> Couper")
dropMenu.add("rename", "<i class='fa-solid fa-file-signature'></i> Renommer")
dropMenu.add("delete", "<i class='fa fa-trash'></i> Supprimer")
dropMenu.show()
2023-11-28 20:05:44 +00:00
dropMenu.get("copy").addEventListener("click", () => {
dropMenu.hide()
inCopyOrCut = {"action": "copy", "file": file, "orginalPath": files.root}
})
dropMenu.get("cut").addEventListener("click", () => {
dropMenu.hide()
inCopyOrCut = {"action": "cut", "file": file, "orginalPath": files.root}
})
dropMenu.get("delete").addEventListener("click", () => {
dropMenu.hide()
const reqFiles = post("FX_DELETE", file.fileDirectory)
reqFiles.then((result) => {
if(result == "OK") {
const reqFiles = post("FX_GET", files.root)
reqFiles.then((result) => {
loadFiles(result)
})
} else if(result == "NOT_PERMITTED") {
const reqFiles = post("FX_GET", files.root)
reqFiles.then((result) => {
loadFiles(result)
})
View.createPopup({
2023-11-04 13:50:28 +00:00
title: `<i class='fa fa-warning'></i> Erreur`,
content: `<p class='yellow'>Vous n'avez pas les permissions pour supprimer ce fichier.</p>`
})
} else {
const reqFiles = post("FX_GET", files.root)
reqFiles.then((result) => {
loadFiles(result)
})
View.createPopup({
2023-11-04 13:50:28 +00:00
title: `<i class='fa fa-warning'></i> Erreur`,
content: `<p class='yellow'>Une erreur est survenue.</p>`
})
}
})
})
dropMenu.get("rename").addEventListener("click", () => {
dropMenu.hide()
View.createPopup({
2023-11-04 13:50:28 +00:00
title: `<i class='fa fa-file-signature'></i> Renommer`,
content: `
<input type='text' class='field' id='${View.getViewTitle()}_rename'>
<div id='${View.getViewTitle()}_renameInfo'></div>
<button class='btn green' id='${View.getViewTitle()}_renameBtn'><span><i class='fa fa-pen'></i> Renommer</span></button>
`})
const rename = getID(View.getViewTitle() + "_rename")
const renameBtn = getID(View.getViewTitle() + "_renameBtn")
2023-11-28 20:05:44 +00:00
const renameInfo = new TextResponse(View.getViewTitle() + "_renameInfo")
renameInfo.setSize("13px")
rename.value = file.name
rename.focus()
rename.select()
renameBtn.addEventListener("click", () => {
renameInfo.clear()
if(rename.value.length < 1) {
renameInfo.err("Le nom du fichier / dossier est trop court.")
return
}
2023-11-04 13:50:28 +00:00
const regex = new RegExp(/^[a-zA-Z0-9-_.]+$/)
if(!regex.test(rename.value) | rename.value.replace(/\s/g, '').length < 1) {
renameInfo.err("Le nom du fichier / dossier est invalide.")
return
}
const reqFiles = post("FX_RENAME", {root: files.root, oldName: file.name, newName: rename.value})
reqFiles.then((result) => {
if(result == "OK") {
View.destroyPopup(`<i class="fa fa-file-signature"></i> Renommer`)
const reqFiles = post("FX_GET", files.root)
reqFiles.then((result) => {
loadFiles(result)
})
} else if(result == "EXIST") {
renameInfo.err("Le fichier / dossier existe déjà.")
} else if(result == "NOT_PERMITTED") {
renameInfo.err("Vous n'avez pas les permissions pour renommer ce fichier / dossier.")
} else {
renameInfo.err("Une erreur est survenue.")
}
})
})
})
if(!file.directory) {
dropMenu.get("share").addEventListener("click", () => {
dropMenu.hide()
const reqFiles = post("FX_SHARE", {root: files.root, name: file.name})
reqFiles.then((result) => {
if(result == "NOT_PERMITTED") {
View.createPopup({
2023-11-04 13:50:28 +00:00
title: `<i class='fa fa-warning'></i> Erreur`,
content: `<p class='yellow'>Vous n'avez pas les permissions pour partager ce fichier.</p>`
})
} else {
View.createPopup({
2023-11-04 13:50:28 +00:00
title: `<i class='fa fa-share'></i> Partager`,
content: `
<input style='width: 300px' type='text' class='field' id='${View.getViewTitle()}_sharelink'>
<div id='${View.getViewTitle()}_shareInfo'></div>
<button class='btn green' id='${View.getViewTitle()}_shareBtn'><span><i class='fa fa-share'></i> Copier</span></button>
`})
const sharelink = getID(View.getViewTitle() + "_sharelink")
const shareBtn = getID(View.getViewTitle() + "_shareBtn")
2023-11-28 20:05:44 +00:00
const shareInfo = new TextResponse(View.getViewTitle() + "_shareInfo")
shareInfo.setSize("13px")
sharelink.value = result
sharelink.focus()
sharelink.select()
shareBtn.addEventListener("click", () => {
sharelink.focus()
sharelink.select()
window.navigator.clipboard.writeText(sharelink.value)
shareInfo.ok("Copié !")
})
}
})
})
// Edit file with an ViewWindow with 2 options close & save and the name of the window is like File - Editor
dropMenu.get("edit").addEventListener("click", () => {
dropMenu.hide()
editFile()
})
dropMenu.get("download").addEventListener("click", () => {
dropMenu.hide()
const reqFiles = post("FX_GETFILE", file.fileDirectory)
reqFiles.then((result) => {
if(result == "NOT_PERMITTED") {
View.createPopup({
2023-11-04 13:50:28 +00:00
title: `<i class='fa fa-warning'></i> Erreur`,
content: `<p class='yellow'>Vous n'avez pas les permissions pour télécharger ce fichier.</p>`
})
} else {
// Make Download using result
const element = document.createElement('a');
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(result));
element.setAttribute('download', file.name);
element.style.display = 'none';
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
}
})
})
}
})
function editFile() {
const reqFiles = post("FX_GETFILE", file.fileDirectory)
//Create a popup for the loading
View.createPopup({
title: `<i class='fa-solid fa-file-pen'></i> Editeur`,
content: `<p><i class='fa-solid fa-rotate fa-spin'></i> Chargement en cours ...</p>`
})
reqFiles.then((result) => {
View.destroyPopup(`<i class='fa-solid fa-file-pen'></i> Editeur}`)
if(result == "NOT_PERMITTED") {
View.createPopup({
2023-11-04 13:50:28 +00:00
title: `<i class='fa fa-warning'></i> Erreur`,
content: `<p class='yellow'>Vous n'avez pas les permissions pour éditer ce fichier.</p>`
})
} else {
const editor = new ViewWindow({
title: `<i class="fa-solid fa-file-pen"></i> Editeur - ${file.fileDirectory}`,
width: "1000px",
height: "650px"
})
if(file.type == "image/png" | file.type == "image/jpeg") {
editor.setContent(`
<div style='width: 100%; text-align: center;'>
<img style='width: 500px;' src='${result}'/>
</div>`)
} else {
editor.setContent(`
<div class='fx-bar'>
<span id='${editor.getViewTitle()}_save' class='btn-cover'><i class='fa fa-save'></i></span>
</div>
<textarea id='${editor.getViewTitle()}_editorContent' class='fx-editor-content'>${result}</textarea>
`)
const editorSave = getID(editor.getViewTitle() + "_save")
const editorContent = getID(editor.getViewTitle() + "_editorContent")
// Sauvegarder le fichier en l'envoyant
editorSave.addEventListener("click", () => {
const reqFiles = post("FX_SAVEFILE", {root: files.root, name: file.name, content: editorContent.value})
reqFiles.then((result) => {
if(result == "OK") {
editor.destroy()
const reqFiles = post("FX_GET", files.root)
reqFiles.then((result) => {
loadFiles(result)
})
} else if(result == "NOT_PERMITTED") {
editor.createPopup({
title: `<i class='fa fa-warning'></i> Erreur`,
content: `<p class='yellow'>Vous n'avez pas les permissions pour éditer ce fichier.</p>`
})
} else {
editor.createPopup({
title: `<i class='fa fa-warning'></i> Erreur`,
content: `<p class='yellow'>Une erreur est survenue.</p>`
})
}
})
})
//forbid textarea resize
editorContent.style.resize = "none"
}
}
})
}
}
}
}
2023-11-28 20:05:44 +00:00
})
function getIcon(file) {
if(file.type == "application/json") {
return '<i style="color:rgb(179, 141, 4);" class="fa-sharp fa-code"></i>'
}
if(file.type == "application/msword" | file.type == "application/vnd.openxmlformats-officedocument.wordprocessingml.document") {
return '<i style="color:rgb(47, 94, 247);" class="fa-solid fa-file-word"></i>'
}
if(file.type == "application/vnd.ms-powerpoint") {
return '<i style="color:rgb(255, 112, 51);" class="fa-solid fa-file-powerpoint"></i>'
}
if(file.type == "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" | file.type == "application/vnd.ms-excel") {
return '<i style="color:rgb(51, 255, 61);" class="fa-solid fa-file-excel"></i>'
}
if(file.type == "application/java-archive") {
return '<i style="color:rgb(255, 202, 150);" class="fa-brands fa-java"></i>'
}
if(file.type == "application/x-sh") {
return '<i style="color:rgb(171, 226, 255);" class="fa-solid fa-file-code"></i>'
}
if(file.type == "application/x-msdos-program" | file.type == "application/x-msdownload") {
return'<i style="color:rgb(53, 191, 255);" class="fa-brands fa-windows"></i>'
}
if(file.type == "application/javascript") {
return '<i style="color:rgb(179, 141, 4);" class="fa-brands fa-js"></i>'
}
if(file.type == "image/png" | file.type == "image/jpeg") {
return '<i style="color:rgb(189, 104, 189);" class="fa-solid fa-file-image"></i>'
}
if(file.type == "text/html") {
return '<i style="color:tomato;" class="fa-brands fa-html5"></i>'
}
if(file.type == "text/css") {
return '<i style="color:rgb(66, 135, 245);" class="fa-brands fa-css3-alt"></i>'
}
if(file.type == "application/zip") {
return '<i style="color:rgb(255, 139, 38);" class="fa-solid fa-file-zipper"></i>'
}
if(file.type == "audio/mpeg") {
return '<i style="color:rgb(38, 222, 255);" class="fa-solid fa-file-audio"></i>'
}
if(file.type == "application/pdf") {
return '<i style="color:rgb(255, 71, 51);" class="fa-solid fa-file-pdf"></i>'
}
if(file.directory) {
return '<i style="color:yellow;" class="fa fa-folder"></i>'
} else {
return '<i class="fa fa-file"></i>'
}
}
function bytesToSize(bytes) {
var sizes = ['o', 'Ko', 'Mo', 'Go', 'To'];
if (bytes == 0) return '0 o';
var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
return Math.round(bytes / Math.pow(1024, i), 2) + ' ' + sizes[i];
}