From b19243a8afba1d0250444d77f1a8eb32d0c34642 Mon Sep 17 00:00:00 2001 From: Raphix Date: Tue, 28 Nov 2023 21:05:44 +0100 Subject: [PATCH] Version 0.4.0 - Ajout des metrics --- bin/files.js | 27 +- bin/server-metrics.js | 74 ++++ bin/{server.js => servers.js} | 23 +- bin/www | 2 +- package-lock.json | 18 +- package.json | 5 +- public/javascripts/basics.js | 613 +++++++++++++++++++++++++----- public/javascripts/filexplorer.js | 120 +++++- public/javascripts/indexscript.js | 68 +--- public/javascripts/link.js | 8 +- public/javascripts/loginscript.js | 2 +- public/javascripts/middle.js | 57 +++ public/javascripts/server.js | 73 ++++ public/javascripts/service.js | 161 +------- public/stylesheets/style.css | 188 ++++++++- routes/login.js | 2 +- views/index.ejs | 64 ++-- 17 files changed, 1121 insertions(+), 384 deletions(-) create mode 100644 bin/server-metrics.js rename bin/{server.js => servers.js} (85%) create mode 100644 public/javascripts/middle.js create mode 100644 public/javascripts/server.js diff --git a/bin/files.js b/bin/files.js index 18266f1..b9f255f 100644 --- a/bin/files.js +++ b/bin/files.js @@ -6,7 +6,7 @@ const clog = new LogType("Fichier") const os = require("os"); const uuid = require('uuid'); var mime = require('mime-types'); -const { set } = require("../main") + // check if shared folder exist, if not create it if(!fs.existsSync(__glob.SHARED)) { @@ -229,4 +229,27 @@ module.exports.newFile = function(settings) { return "EXIST" } - } \ No newline at end of file + } + +module.exports.pasteFile = function(settings) { + if(settings.action == "cut") { + + try { + + fs.renameSync(settings.file.fileDirectory, settings.newPath + path.sep + settings.name) + return "OK" + } catch(err) { + console.log(err) + return "NOT_PERMITTED" + } + } else if(settings.action == "copy") { + + try { + fs.copyFileSync(settings.file.fileDirectory, settings.newPath + path.sep + settings.name) + return "OK" + } catch(err) { + console.log(err) + return "NOT_PERMITTED" + } + } +} \ No newline at end of file diff --git a/bin/server-metrics.js b/bin/server-metrics.js new file mode 100644 index 0000000..5ac68b9 --- /dev/null +++ b/bin/server-metrics.js @@ -0,0 +1,74 @@ +const { LogType } = require("loguix") +const fs = require("fs") +const path = require("path") +const { __glob } = require("./global-variables") +const clog = new LogType("Serveur Metrics") +const osutils = require("os-utils") +const os = require("os") +const { statfs } = require("fs") +const config = require("./config") + + + +module.exports.getMetrics = async function(server) { + + return new Promise((resolve, reject) => { + if(server == "Alpha") { + var resp = "NULL" + const space = statfs("/", (err, stats) => { + if (err) { + throw err + } + + + + osutils.cpuUsage(function(cpuUsage) { + resp = { + cpu: Math.round(cpuUsage * 1000), + usedram: osutils.totalmem() - osutils.freemem(), + totalram: osutils.totalmem(), + usedisk: stats.blocks - stats.bfree, + totaldisk: stats.blocks, + name: server + } + + resolve(resp) + + + }) + + }) + + + } else if(server == "Omega") { + + const key = config.getFile().OMEGA_KEY; + + fetch("http://omega.raphix.fr:4000/metrics?key="+key, { + method: "GET", + headers: { + "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", + "Accept-Encoding": "gzip, deflate", + "Accept-Language": "fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7", + "Cache-Control": "no-cache", + "Connection": "keep-alive" + } + }) + .then(response => response.json()) + .then(raw => { + raw.name = server; + resolve(raw); + }) + .catch(error => { + + reject(error); + }); + + + + } + + }) + + +} \ No newline at end of file diff --git a/bin/server.js b/bin/servers.js similarity index 85% rename from bin/server.js rename to bin/servers.js index feaeb66..cf72414 100644 --- a/bin/server.js +++ b/bin/servers.js @@ -1,14 +1,15 @@ const { LogType } = require("loguix") const fs = require("fs") const path = require("path") -const { __glob } = require("./global-variables") -const auth = require("./auth") -const files = require("./files") +const { __glob } = require("./global-variables.js") +const auth = require("./auth.js") +const files = require("./files.js") const links = require("./links.js") -const service = require("./services") +const service = require("./services.js") const plog = new LogType("Web") const cook = require("cookie") const http = require("http") +const servermetrics = require("./server-metrics.js") /** * NOTE INTERNE @@ -94,6 +95,11 @@ module.exports.serverIO = function(server) { }) + PostRequest("FX_PASTE", (settings) => { + + PostAnswer("FX_PASTE", files.pasteFile(settings)) + }) + } if(user.checkPermission("SERVICES")) { @@ -136,6 +142,15 @@ module.exports.serverIO = function(server) { } + if(user.checkPermission("SERVERS")) { + PostRequest("SERVER_GET_METRICS_Alpha", async (settings) => { + PostAnswer("SERVER_GET_METRICS_Alpha", {answer: "OK", metrics: await servermetrics.getMetrics(settings), name: settings}); + }); + PostRequest("SERVER_GET_METRICS_Omega", async (settings) => { + PostAnswer("SERVER_GET_METRICS_Omega", {answer: "OK", metrics: await servermetrics.getMetrics(settings), name: settings}); + }); + } + socket.on("disconnect", () => { plog.log("Déconnexion du panel par '" + user.username + "' avec le socket : " + socket.id) diff --git a/bin/www b/bin/www index 6b9c341..111feaa 100644 --- a/bin/www +++ b/bin/www @@ -20,7 +20,7 @@ wlog.step.init("start_server", "Démarrage du serveur Express JS") var app = require('../main'); var http = require('http'); var config = require("./config") -var serverIO = require("./server") +var serverIO = require("./servers") /** * Get port from environment and store in Express. diff --git a/package-lock.json b/package-lock.json index b7c4b2f..29c53b4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "neutral", - "version": "0.2.0", + "version": "0.4.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "neutral", - "version": "0.2.0", + "version": "0.4.0", "license": "ISC", "dependencies": { "cookie-parser": "~1.4.4", @@ -17,6 +17,7 @@ "http-errors": "~1.6.3", "loguix": "1.4.1", "nodemon": "^3.0.1", + "os-utils": "^0.0.14", "serve-favicon": "^2.0.4", "socket.io": "^4.7.2", "uuid": "^9.0.1" @@ -718,6 +719,14 @@ "node": ">= 0.8" } }, + "node_modules/os-utils": { + "version": "0.0.14", + "resolved": "https://registry.npmjs.org/os-utils/-/os-utils-0.0.14.tgz", + "integrity": "sha512-ajB8csaHLBvJOYsHJkp8YdO2FvlBbf/ZxaYQwXXRDyQ84UoE+uTuLXxqd0shekXMX6Qr/pt/DDyLMRAMsgfWzg==", + "engines": { + "node": "*" + } + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -1635,6 +1644,11 @@ "ee-first": "1.1.1" } }, + "os-utils": { + "version": "0.0.14", + "resolved": "https://registry.npmjs.org/os-utils/-/os-utils-0.0.14.tgz", + "integrity": "sha512-ajB8csaHLBvJOYsHJkp8YdO2FvlBbf/ZxaYQwXXRDyQ84UoE+uTuLXxqd0shekXMX6Qr/pt/DDyLMRAMsgfWzg==" + }, "parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", diff --git a/package.json b/package.json index 0ae1333..1a2d616 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "neutral", - "version": "0.3.4", + "version": "0.4.0", "description": "Panel d'administration de Raphix", "main": "index.js", "scripts": { @@ -25,10 +25,11 @@ "debug": "~2.6.9", "ejs": "~2.6.1", "express": "~4.16.1", - "serve-favicon": "^2.0.4", "http-errors": "~1.6.3", "loguix": "1.4.1", "nodemon": "^3.0.1", + "os-utils": "^0.0.14", + "serve-favicon": "^2.0.4", "socket.io": "^4.7.2", "uuid": "^9.0.1" }, diff --git a/public/javascripts/basics.js b/public/javascripts/basics.js index c4fb625..4c9b221 100644 --- a/public/javascripts/basics.js +++ b/public/javascripts/basics.js @@ -1,7 +1,19 @@ +var xMousePos = null; +var yMousePos = null; -// Get Document ID +document.onmousemove = function(e) { + xMousePos = e.clientX + window.scrollX; + yMousePos = e.clientY + window.scrollY; +} + +document.oncontextmenu = function(e) { + + xMousePos = e.clientX + window.scrollX; + yMousePos = e.clientY + window.scrollY; + +} /** * Récupère depuis le document l'identifiant de l'élément @@ -13,10 +25,50 @@ function getID(id) { return document.getElementById(id) } +/** + * + * @param {Date} GetDate + * @returns + */ +function getFormattedDate(GetDate) { + + const date = new Date(GetDate) + + var gmonth = date.getMonth() + 1 + var gday = date.getDate() + var gHour = date.getHours() + var gMinute = date.getMinutes() + var gSecondes = date.getSeconds() + + + if(date.getMonth() + 1 < 10) { + gmonth = "0" + (date.getMonth() + 1) + } + + if(date.getDate() + 1 <= 10) { + gday = "0" + date.getDate() + } + + if(date.getHours() + 1 <= 10) { + gHour = "0" + date.getHours() + } + + if(date.getMinutes() + 1 <= 10) { + gMinute = "0" + date.getMinutes() + } + + if(date.getSeconds() + 1 <= 10) { + gSecondes = "0" + date.getSeconds() + } + + return gday + "/" + gmonth + "/" + date.getFullYear() + " - " + gHour + ":" + gMinute +} + + /** * Permet de faire une pop-up automatique */ -class InfoPop { +class TextResponse { constructor(name) { this.name = name this.element = getID(this.name) @@ -54,38 +106,30 @@ class InfoPop { } -const viewsAccessible = new Map() - -var xMousePos = null; -var yMousePos = null; - -document.onmousemove = function(e) { - xMousePos = e.clientX + window.scrollX; - yMousePos = e.clientY + window.scrollY; - -} - -document.oncontextmenu = function(e) { - - xMousePos = e.clientX + window.scrollX; - yMousePos = e.clientY + window.scrollY; - -} - +const AllViews = new Map() var zIndex = 5 + +/** + * Permet de créer une fenêtre + * @param {object} properties Propriétés de la fenêtre + */ class ViewWindow { ViewHTML = null - ViewProperties =null + ViewWindowDiv + ViewProperties = null ViewSpanInteger = null ViewPopupSpanInteger = null ViewPopupHTML = null ViewPopupTitle = null + ViewItem = new ViewItem(this) constructor(properties) { - if(!viewsAccessible.has(properties.title)) { + if(!AllViews.has(properties.title)) { this.ViewProperties = properties - viewsAccessible.set(properties.title, true) + AllViews.set(properties.title, true) + + this.ViewHTML = `
@@ -93,8 +137,12 @@ class ViewWindow {

${properties.title}

+
+ +
+
@@ -105,15 +153,49 @@ class ViewWindow { document.body.appendChild(this.ViewSpanInteger); this.ViewSpanInteger.outerHTML = this.ViewHTML + const header = document.getElementById(properties.title + "_header") + const windowDiv = document.getElementById(properties.title + "_window") + this.ViewWindowDiv = windowDiv const closeWindow = document.getElementById(properties.title + "_close") + const minimizeWindow = document.getElementById(properties.title + "_minimize") + const reduceWindow = document.getElementById(properties.title + "_reduce") + closeWindow.addEventListener("click", () => { this.destroy() }) + + reduceWindow.addEventListener("click", () => { + windowDiv.style.display = "none" + + }) + + minimizeWindow.addEventListener("click", () => { + + const windowDiv = document.getElementById(properties.title + "_window") + const contentDiv = document.getElementById(properties.title + "_content") + const minimizeIcon = document.getElementById(properties.title + "_minimize").children[0] + + + if(windowDiv.classList.contains("minimized")) { + windowDiv.classList.remove("minimized") + contentDiv.style.display = "unset" + windowDiv.style.backgroundColor = "#605e58c1" + minimizeIcon.classList.remove("fa-window-restore") + minimizeIcon.classList.add("fa-window-maximize") + } else { + windowDiv.classList.add("minimized") + contentDiv.style.display = "none" + windowDiv.style.backgroundColor = "transparent" + minimizeIcon.classList.remove("fa-window-maximize") + minimizeIcon.classList.add("fa-window-restore") + this.destroyPopup() + } + }) + - const header = document.getElementById(properties.title + "_header") - const windowDiv = document.getElementById(properties.title + "_window") + let isDragging = false; let offsetX, offsetY; @@ -160,12 +242,15 @@ class ViewWindow { } + this.ViewItem.show() + } destroy() { const win = getID(`${this.ViewProperties.title}_window`) win.outerHTML = " " - viewsAccessible.delete(this.ViewProperties.title) + AllViews.delete(this.ViewProperties.title) + this.ViewItem.hide() } setContent(text) { @@ -225,49 +310,105 @@ class ViewWindow { } destroyPopup() { - - const contentDiv = getID(this.ViewProperties.title + "_content") - for(var child of contentDiv.children) { - child.style.pointerEvents = "unset" - } - contentDiv.classList.remove("blur") - const popup = getID(this.ViewPopupTitle + "_popup") - popup.outerHTML = "" + + if(popup) { + const contentDiv = getID(this.ViewProperties.title + "_content") + for(var child of contentDiv.children) { + child.style.pointerEvents = "unset" + } + contentDiv.classList.remove("blur") + + + popup.outerHTML = "" + + } + } } -function createView(viewType) { - if(viewType == 'files_explorer') { - - generateFileExplorerView() +var AllComponents = new Array() + +/** + * Permet de créer un composant de vue + * @param {object} properties Propriétés du composant de vue + */ +class ViewComponent { + name; + icon; + permission; + window; + constructor (properties) { + this.name = properties.name + this.icon = properties.icon + this.permission = properties.permission + + AllComponents.push(this) } - if(viewType == 'service') { - generateServiceView() - } - if(viewType == "links") { + inject(array) { - generateLinksView() + array.push(`
+ +

${this.name}

+
`) + + } - + + createWindow(functionToExecute) { + + this.window = functionToExecute + } + + bindView() { + + const component = getID(this.name) + if(component) { + component.addEventListener("click", () => { + console.log(component) + if(this.window) { + this.window() + } + }) + + } + + } + + forceWindow() { + + if(this.window) { + this.window() + } + } + + + } +/** + * Permet de créer un menu déroulant + * @param {object} properties Propriétés du menu déroulant + */ + +var ActualDroppableMenu = null class DroppableMenu { options = new Array() id = null DMSpanInteger = null - constructor(properties) { + #enableHide = false + constructor() { - this.id = properties.id + this.id = Math.random().toString(36).substring(7) this.options.push(`
`) - + } add(action, string) { @@ -277,13 +418,18 @@ class DroppableMenu { } show() { - - + console.log("DROPPABLE MENU - " + this.id) + if(ActualDroppableMenu) { + ActualDroppableMenu.hide() + } + ActualDroppableMenu = this + this.options.push(`
`) if(xMousePos && yMousePos) { - + this.DMSpanInteger = document.createElement("span") + document.body.appendChild(this.DMSpanInteger); this.DMSpanInteger.outerHTML = this.options.join('') @@ -292,22 +438,21 @@ class DroppableMenu { menu.style.zIndex = zIndex + 2 zIndex+=1 - menu.style.left = (xMousePos - 40) + "px" menu.style.top = (yMousePos - 40) + "px" - - menu.addEventListener('mouseleave', () => { - - menu.outerHTML = "" - - }) - - + } - + this.#enableHide = false - + document.addEventListener("click", () => { + + this.hide() + + }) + + + } get(action) { @@ -316,45 +461,331 @@ class DroppableMenu { } hide() { - + const menu = getID(`dm-${this.id}`) - menu.outerHTML = "" - + if(menu) { + menu.outerHTML = "" + } + } } - - -function getFormattedDate(GetDate) { - - const date = new Date(GetDate) - - var gmonth = date.getMonth() + 1 - var gday = date.getDate() - var gHour = date.getHours() - var gMinute = date.getMinutes() - var gSecondes = date.getSeconds() - - - if(date.getMonth() + 1 < 10) { - gmonth = "0" + (date.getMonth() + 1) - } - - if(date.getDate() + 1 <= 10) { - gday = "0" + date.getDate() +/** + * Permet de créer un composant de type "Serveur" + */ +class Server { + constructor(properties) { + this.name = properties.name + this.description = properties.description + this.icon = properties.icon } - if(date.getHours() + 1 <= 10) { - gHour = "0" + date.getHours() + generateHTML() { + return ` +
+
+
+ +

${this.name}

+ +
+

${this.description}

+
+
+
+
+
+ +

RAM

+
+

-- Mo / -- Mo

+
+
+
+ +

CPU

+
+

---%

+
+
+
+ +

DISK

+
+

-- Go / -- Go

+
+
+
+
+ + ` } - if(date.getMinutes() + 1 <= 10) { - gMinute = "0" + date.getMinutes() + + loadScript() { + + const ramSpan = getID(`${this.name}_ram`) + const cpuSpan = getID(`${this.name}_cpu`) + const diskSpan = getID(`${this.name}_disk`) + + + setInterval(() => { + + if(getID(`${this.name}_ram`)) { + + const request = post(`SERVER_GET_METRICS_` + this.name, this.name ) + console.log(this.name) + + + request.then((answer) => { + console.log(answer) + console.log(this.name) + //Transform all metrics in mb to answer.metrics to Go or % + answer.metrics.usedram = Math.round(answer.metrics.usedram) + answer.metrics.totalram = Math.round(answer.metrics.totalram) + + //Transform all metrics in blocks to Go + answer.metrics.usedisk = Math.round((answer.metrics.usedisk * 3.814697265625) / 1000000) + answer.metrics.totaldisk = Math.round((answer.metrics.totaldisk * 3.814697265625) / 1000000) + + if(answer.metrics.name == this.name) { + ramSpan.innerHTML = `${answer.metrics.usedram} Mo / ${answer.metrics.totalram} Mo` + cpuSpan.innerHTML = answer.metrics.cpu + "%" + diskSpan.innerHTML = `${answer.metrics.usedisk} Go / ${answer.metrics.totaldisk} Go` + + } + + }) + } + + + + }, 1000) + + + } +} + +/** + * Créer un composant de vue de type "Service" + * @param {object} properties Propriétés du composant de vue + */ +class Service { + name = null + description = null + icon = null + url = null + canAccess = false + isOnline = false + constructor(properties) { + this.name = properties.name + this.description = properties.description + this.icon = properties.icon + this.url = properties.url + this.canAccess = properties.canAccess } - if(date.getSeconds() + 1 <= 10) { - gSecondes = "0" + date.getSeconds() + generateHTML() { + return ` +
+
+ ${this.name} +
+

${this.name}

+

${this.description}

+

Etat : Vérification en cours ...

+
+
+ +
+ ${this.canAccess ? `` : ""} + +
+
+ ` + + } - return gday + "/" + gmonth + "/" + date.getFullYear() + " - " + gHour + ":" + gMinute -} \ No newline at end of file + loadScript() { + + return new Promise((resolve, reject) => { + const statusSpan = getID(`${this.name}_status`) + const request = post(`SV_GET_SERVICE_STATUS`, this.url) + + + request.then((answer) => { + if(answer.name == this.url) { + if(answer.answer == "ONLINE") { + statusSpan.innerHTML = ' En ligne' + this.isOnline = true + } else { + statusSpan.innerHTML = ' Hors ligne' + + } + resolve("LOADED") + } + + }) + + const powerButton = getID(`${this.name}_svpower`) + + // Make a popup of View to select if you want to start, stop or restart the service by doing a request + + powerButton.addEventListener("click", () => { + View.createPopup({ + title: ` Gestion de l'alimentation du service`, + content: ` + +

${this.name}

+

+
+ + + +
+ ` + }) + + const startButton = getID(`${this.name}_start`) + const stopButton = getID(`${this.name}_stop`) + const restartButton = getID(`${this.name}_restart`) + const info = new InfoPop("sv-power-info") + + + + if(this.isOnline) { + startButton.style.display = "none" + info.info("Verifiez que le service n'est pas utilisé par quelqu'un d'autre avant de le redémarrer ou de l'arrêter") + } else { + stopButton.style.display = "none" + restartButton.style.display = "none" + info.info("Si le service ne démarre pas, vérifiez l'intégrité du service") + } + + startButton.addEventListener("click", () => { + const request = post(`SV_START_SERVICE`, this.url) + + + request.then((answer) => { + if(answer.answer == "OK") { + statusSpan.innerHTML = ' En ligne' + View.destroyPopup("` Gestion de l'alimentation du service`") + this.isOnline = true + } else { + info.err("Impossible de démarrer le service") + + } + }) + + }) + + stopButton.addEventListener("click", () => { + const request = post(`SV_STOP_SERVICE`, this.url) + + request.then((answer) => { + if(answer.answer == "OK") { + statusSpan.innerHTML = ' Hors ligne' + this.isOnline = false + View.destroyPopup("` Gestion de l'alimentation du service`") + + } else { + info.err("Impossible d'arrêter le service") + + } + + }) + }) + + restartButton.addEventListener("click", () => { + + console.log("RESTART") + + const request = post(`SV_RESTART_SERVICE`, this.url) + + request.then((answer) => { + if(answer.answer == "OK") { + statusSpan.innerHTML = ' En ligne' + View.destroyPopup("` Gestion de l'alimentation du service`") + this.isOnline = true + } else { + info.err("Impossible de redémarrer le service") + + } + + }) + }) + + + }) + + }) + } + +} + + +/** + * Permet de créer un item de la barre des tâches + * @param {ViewWindow} window ViewWindow associé à l'item + */ +class ViewItem { + /** + * + * @param {ViewWindow} window + */ + constructor(window) { + this.window = window + } + + show() { + const viewItems = getID("views-items") + + const item = document.createElement("div") + item.id = `${this.window.ViewProperties.title}_item` + item.classList.add("view-item") + item.innerHTML = this.window.ViewProperties.title + + viewItems.appendChild(item) + + item.addEventListener("click", () => { + zIndex+=1 + this.window.ViewWindowDiv.style.zIndex = zIndex + 1 + this.window.ViewWindowDiv.style.display = "unset" + }) + + item.addEventListener("contextmenu", () => { + const dp = new DroppableMenu() + + dp.add("index", ` Afficher`) + dp.add("close", ` Fermer`) + dp.show() + + const index = dp.get("index") + const close = dp.get("close") + + index.addEventListener("click", () => { + zIndex+=1 + this.window.ViewWindowDiv.style.display = "unset" + this.window.ViewWindowDiv.style.zIndex = zIndex + 1 + dp.hide() + }) + + close.addEventListener("click", () => { + this.window.destroy() + dp.hide() + }) + + }) + + } + + hide() { + const viewItems = getID("views-items") + const item = getID(`${this.window.ViewProperties.title}_item`) + + item.outerHTML = "" + } + +} + diff --git a/public/javascripts/filexplorer.js b/public/javascripts/filexplorer.js index 3da9ab2..c287a62 100644 --- a/public/javascripts/filexplorer.js +++ b/public/javascripts/filexplorer.js @@ -3,7 +3,9 @@ document.addEventListener("contextmenu", (e) => { e.preventDefault() }) -function generateFileExplorerView() { +explorer.createWindow(() => { + + var inCopyOrCut = null; const View = new ViewWindow({ title: ` Gestionnaire de fichiers`, @@ -11,6 +13,15 @@ function generateFileExplorerView() { height: "600px" }) + + console.log("") + + + + + + + goHomePath() function goHomePath() { const rFiles = post("FX_GET", "homepath") @@ -53,6 +64,57 @@ function generateFileExplorerView() { const home = getID(View.getViewTitle() + '_home') const sharebtn = getID(View.getViewTitle() + '_sharebtn') + + + View.ViewWindowDiv.addEventListener("contextmenu", () => { + + + if(inCopyOrCut != null) { + + const dMenu = new DroppableMenu() + dMenu.add("paste", " 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: ` Erreur`, + content: `

Vous n'avez pas les permissions pour coller ce fichier.

` + }) + } else { + const reqFiles = post("FX_GET", rootInput.value) + reqFiles.then((result) => { + loadFiles(result) + }) + View.createPopup({ + title: ` Erreur`, + content: `

Une erreur est survenue.

` + }) + } + }) + + inCopyOrCut = null + }) + } else { + console.log("LISTENER : " + rootInput.value) + + } + + }) + home.addEventListener("click", () => { goHomePath() @@ -77,7 +139,7 @@ function generateFileExplorerView() { const foldername = getID(View.getViewTitle() + "_foldername") const foldercreate = getID(View.getViewTitle() + "_foldercreate") - const folderInfo = new InfoPop(View.getViewTitle() + "_folderInfo") + const folderInfo = new TextResponse(View.getViewTitle() + "_folderInfo") folderInfo.setSize("13px") @@ -137,7 +199,7 @@ function generateFileExplorerView() { const filename = getID(View.getViewTitle() + "_filename") const filecreate = getID(View.getViewTitle() + "_filecreate") const fileupload = getID(View.getViewTitle() + "_fileupload") - const fileInfo = new InfoPop(View.getViewTitle() + "_fileInfo") + const fileInfo = new TextResponse(View.getViewTitle() + "_fileInfo") fileInfo.setSize("13px") @@ -190,7 +252,7 @@ function generateFileExplorerView() { const fileuploadInput = getID(View.getViewTitle() + "_fileuploadInput") const fileuploadBtn = getID(View.getViewTitle() + "_fileuploadBtn") - const fileuploadInfo = new InfoPop(View.getViewTitle() + "_fileuploadInfo") + const fileuploadInfo = new TextResponse(View.getViewTitle() + "_fileuploadInfo") fileuploadBtn.addEventListener("click", () => { @@ -324,9 +386,7 @@ function generateFileExplorerView() { for(const file of files.content) { - const dropMenu = new DroppableMenu({ - "id": file.id - }) + const element = document.getElementById(file.id) @@ -347,18 +407,41 @@ function generateFileExplorerView() { editFile() }) - dropMenu.add("edit", " Editer") - dropMenu.add("share", " Partager") - dropMenu.add("download", " Télécharger") + } - dropMenu.add("rename", " Renommer") + + - dropMenu.add("delete", " Supprimer") - + getID(file.id).addEventListener("contextmenu", () => { + + const dropMenu = new DroppableMenu() + + dropMenu.add("copy", " Copier") + dropMenu.add("cut", " Couper") + dropMenu.add("rename", " Renommer") + dropMenu.add("delete", " Supprimer") + + if(!file.directory) { + dropMenu.add("edit", " Editer") + dropMenu.add("share", " Partager") + dropMenu.add("download", " Télécharger") + } dropMenu.show() + + + 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) @@ -403,7 +486,7 @@ function generateFileExplorerView() { const rename = getID(View.getViewTitle() + "_rename") const renameBtn = getID(View.getViewTitle() + "_renameBtn") - const renameInfo = new InfoPop(View.getViewTitle() + "_renameInfo") + const renameInfo = new TextResponse(View.getViewTitle() + "_renameInfo") renameInfo.setSize("13px") rename.value = file.name rename.focus() @@ -465,7 +548,7 @@ function generateFileExplorerView() { const sharelink = getID(View.getViewTitle() + "_sharelink") const shareBtn = getID(View.getViewTitle() + "_shareBtn") - const shareInfo = new InfoPop(View.getViewTitle() + "_shareInfo") + const shareInfo = new TextResponse(View.getViewTitle() + "_shareInfo") shareInfo.setSize("13px") sharelink.value = result sharelink.focus() @@ -583,10 +666,7 @@ function generateFileExplorerView() { editorContent.style.resize = "none" - editorClose.addEventListener("click", () => { - - editor.destroy() - }) + } @@ -603,7 +683,7 @@ function generateFileExplorerView() { -} +}) function getIcon(file) { diff --git a/public/javascripts/indexscript.js b/public/javascripts/indexscript.js index a934865..5441228 100644 --- a/public/javascripts/indexscript.js +++ b/public/javascripts/indexscript.js @@ -3,6 +3,8 @@ const infoUserimage = getID("infoUserimage") const infoDisplayname = getID("infoDisplayname") const views = getID("views") + + // User Request const REQ_user = get("USERINFO") @@ -17,55 +19,12 @@ REQ_user.then((ANS_user) => { const AvailableViews = new Array() permissions.forEach((permValue) => { - - if(permValue == "FILES_EXPLORER") { - AvailableViews.push(`
- -

Gestionnaire de fichiers

-
`) - } - if(permValue == "SERVICES") { - AvailableViews.push(`
- -

Gestion des services

-
`) - } - if(permValue == "SERVERS") { - AvailableViews.push(`
- -

Gestion des serveurs

-
`) - } - if(permValue == "PIPELINES") { - AvailableViews.push(`
- -

Gestion des pipelines

-
`) - } - if(permValue == "METRICS") { - AvailableViews.push(`
- -

Web Metrics

-
`) - } - if(permValue == "USERS") { - AvailableViews.push(`
- -

Gestion des utilisateurs

-
`) - } - if(permValue == "LINKS") { - AvailableViews.push(`
- -

Générateur de lien

-
`) - } - if(permValue == "SETTINGS") { - AvailableViews.push(`
- -

Paramètres

-
`) - } + + AllComponents.forEach((component) => { + if(component.permission == permValue) { + component.inject(AvailableViews) + } + }) }) @@ -73,7 +32,7 @@ REQ_user.then((ANS_user) => { if(AvailableViews.join("") == "") { - AvailableViews.push("

Aucune permission ne semble vous êtes accordée
Demandez à Raphix afin de résoudre ce problème

") + AvailableViews.push("

Aucune permission ne semble vous êtes accordée
Demandez à Raphix afin de résoudre ce problème

") views.classList.remove("views-box") } else { @@ -82,5 +41,14 @@ REQ_user.then((ANS_user) => { views.innerHTML = AvailableViews.join("") + // BindView + + AllComponents.forEach((component) => { + component.bindView() + }) + + servers.forceWindow() + + }) diff --git a/public/javascripts/link.js b/public/javascripts/link.js index a8c54be..7a4adbb 100644 --- a/public/javascripts/link.js +++ b/public/javascripts/link.js @@ -1,4 +1,4 @@ -function generateLinksView() { +links.createWindow(() => { const View = new ViewWindow({ title: ` Générateur de liens`, @@ -40,7 +40,7 @@ function generateLinksView() { const titleInput = getID(`${View.getViewTitle()}_title`) const urlInput = getID(`${View.getViewTitle()}_url`) const addBtn = getID(`${View.getViewTitle()}_confirm`) - const info = new InfoPop(`${View.getViewTitle()}_info`) + const info = new TextResponse(`${View.getViewTitle()}_info`) const ablink = getID(`${View.getViewTitle()}_ablink`) const newlinkSpan = getID(`${View.getViewTitle()}_newlink_span`) @@ -206,7 +206,7 @@ function generateLinksView() { const titleInput = getID(`${View.getViewTitle()}_edittitle`) const urlInput = getID(`${View.getViewTitle()}_editurl`) const editBtnConfirm = getID(`${View.getViewTitle()}_editconfirm`) - const info = new InfoPop(`${View.getViewTitle()}_editinfo`) + const info = new TextResponse(`${View.getViewTitle()}_editinfo`) titleInput.value = link.title urlInput.value = link.url @@ -294,4 +294,4 @@ function generateLinksView() { } -} \ No newline at end of file +}) \ No newline at end of file diff --git a/public/javascripts/loginscript.js b/public/javascripts/loginscript.js index 8a5c204..a8dd172 100644 --- a/public/javascripts/loginscript.js +++ b/public/javascripts/loginscript.js @@ -2,7 +2,7 @@ const username = getID("username") const password = getID("password") const submit = getID("submit") -const loginInfo = new InfoPop("login-info") +const loginInfo = new TextResponse("login-info") loginInfo.clear() diff --git a/public/javascripts/middle.js b/public/javascripts/middle.js new file mode 100644 index 0000000..78f40a4 --- /dev/null +++ b/public/javascripts/middle.js @@ -0,0 +1,57 @@ +// My View Component + + + +const explorer = new ViewComponent({ + name: "Explorateur de fichier", + icon: "fa-solid fa-folder", + permission: "FILES_EXPLORER" + }) + + const services = new ViewComponent({ + name: "Gestion des services", + icon: "fa-solid fa-layer-group", + permission: "SERVICES" + }) + + const servers = new ViewComponent({ + name: "Gestion des serveurs", + icon: "fa fa-server", + permission: "SERVERS" + }) + + const pipelines = new ViewComponent({ + name: "Gestion des pipelines", + icon: "fa-solid fa-code-merge", + permission: "PIPELINES" + }) + + const metrics = new ViewComponent({ + name: "Web Metrics", + icon: "fa-solid fa-square-poll-vertical", + permission: "METRICS" + }) + + const users = new ViewComponent({ + name: "Gestion des utilisateurs", + icon: "fa-solid fa-users", + permission: "USERS" + + }) + + const links = new ViewComponent({ + name: "Gestion des liens", + icon: "fa-solid fa-link", + permission: "LINKS" + }) + + const settings = new ViewComponent({ + name: "Paramètres", + icon: "fa-solid fa-cog", + permission: "SETTINGS" + }) + + + + + diff --git a/public/javascripts/server.js b/public/javascripts/server.js new file mode 100644 index 0000000..b2b1699 --- /dev/null +++ b/public/javascripts/server.js @@ -0,0 +1,73 @@ +servers.createWindow(async () => { + const View = new ViewWindow({ + title: ` Gestion des serveurs`, + width: "1000px", + height: "450px" + }) + + const serversList = new Array() + + + const alpha = new Server({ + name: "Alpha", + description: "Serveur principal", + icon: "fa-solid fa-hourglass-start", + }) + + const omega = new Server({ + name: "Omega", + description: "Serveur secondaire", + icon: "fa-solid fa-stop", + }) + + serversList.push(alpha.generateHTML()) + serversList.push(omega.generateHTML()) + + + View.setContent(` +
+ ${serversList.join("")} +
`) + + await alpha.loadScript() + await omega.loadScript() + +}) + + +/** +
+
+
+ +

Alpha

+
+ +
+
+
+
+
+ +

RAM

+
+

1.5 Go / 2 Go

+
+
+
+ +

CPU

+
+

1.5 Go / 2 Go

+
+
+
+ +

DISK

+
+

1.5 Go / 2 Go

+
+
+
+
+ */ \ No newline at end of file diff --git a/public/javascripts/service.js b/public/javascripts/service.js index 1263c38..3b5acf0 100644 --- a/public/javascripts/service.js +++ b/public/javascripts/service.js @@ -1,164 +1,7 @@ -async function generateServiceView() { - - class Service { - name = null - description = null - icon = null - url = null - canAccess = false - isOnline = false - constructor(properties) { - this.name = properties.name - this.description = properties.description - this.icon = properties.icon - this.url = properties.url - this.canAccess = properties.canAccess - } - - generateHTML() { - return ` -
-
- ${this.name} -
-

${this.name}

-

${this.description}

-

Etat : Vérification en cours ...

-
-
- -
- ${this.canAccess ? `` : ""} - -
-
- ` - - - } - - loadScript() { - - return new Promise((resolve, reject) => { - const statusSpan = getID(`${this.name}_status`) - const request = post(`SV_GET_SERVICE_STATUS`, this.url) - - - request.then((answer) => { - if(answer.name == this.url) { - if(answer.answer == "ONLINE") { - statusSpan.innerHTML = ' En ligne' - this.isOnline = true - } else { - statusSpan.innerHTML = ' Hors ligne' - - } - resolve("LOADED") - } - - }) - - const powerButton = getID(`${this.name}_svpower`) - - // Make a popup of View to select if you want to start, stop or restart the service by doing a request - - powerButton.addEventListener("click", () => { - View.createPopup({ - title: ` Gestion de l'alimentation du service`, - content: ` - -

${this.name}

-

-
- - - -
- ` - }) - - const startButton = getID(`${this.name}_start`) - const stopButton = getID(`${this.name}_stop`) - const restartButton = getID(`${this.name}_restart`) - const info = new InfoPop("sv-power-info") - - - - if(this.isOnline) { - startButton.style.display = "none" - info.info("Verifiez que le service n'est pas utilisé par quelqu'un d'autre avant de le redémarrer ou de l'arrêter") - } else { - stopButton.style.display = "none" - restartButton.style.display = "none" - info.info("Si le service ne démarre pas, vérifiez l'intégrité du service") - } - - startButton.addEventListener("click", () => { - const request = post(`SV_START_SERVICE`, this.url) - - - request.then((answer) => { - if(answer.answer == "OK") { - statusSpan.innerHTML = ' En ligne' - View.destroyPopup("` Gestion de l'alimentation du service`") - this.isOnline = true - } else { - info.err("Impossible de démarrer le service") - - } - }) - - }) - - stopButton.addEventListener("click", () => { - const request = post(`SV_STOP_SERVICE`, this.url) - - request.then((answer) => { - if(answer.answer == "OK") { - statusSpan.innerHTML = ' Hors ligne' - this.isOnline = false - View.destroyPopup("` Gestion de l'alimentation du service`") - - } else { - info.err("Impossible d'arrêter le service") - - } - - }) - }) - - restartButton.addEventListener("click", () => { - - console.log("RESTART") - - const request = post(`SV_RESTART_SERVICE`, this.url) - - request.then((answer) => { - if(answer.answer == "OK") { - statusSpan.innerHTML = ' En ligne' - View.destroyPopup("` Gestion de l'alimentation du service`") - this.isOnline = true - } else { - info.err("Impossible de redémarrer le service") - - } - - }) - }) - - - }) - - }) - } - - } - - +services.createWindow(async () => { /** * CODE OF SERVICE.JS */ - const allServices = new Array() const View = new ViewWindow({ @@ -236,5 +79,5 @@ async function generateServiceView() { await cvraphix.loadScript() await lavalink.loadScript() -} +}) diff --git a/public/stylesheets/style.css b/public/stylesheets/style.css index a6a74a9..c7746a5 100644 --- a/public/stylesheets/style.css +++ b/public/stylesheets/style.css @@ -293,14 +293,21 @@ a { .subpanel-box { - width: 900px; - height: 50px; - border-radius: 10px; - padding: 2%; + width: 100%; + position: absolute; + background-color: #09090963; + backdrop-filter: blur(10px); + bottom: 0; + align-items: center; + + +} + +.subpanel-content { + display: flex; justify-content: space-between; - background-color: #605e5863; - backdrop-filter: blur(10px); + padding: 20px; } .subpanel-image { @@ -310,6 +317,16 @@ a { border-radius: 100%; } +.subpanel-logo { + width: 50px; + + transition: 0.3s; +} + +.subpanel-logo:hover { + transform: scale(0.9); +} + .subpanel-user { display: flex; @@ -319,12 +336,21 @@ a { } .subpanel-userinfo { - text-align: start; + text-align: end; display: flex; flex-direction: column; gap: 5px; } +.subpanel-actions { + + display: flex; + flex-direction: row; + gap: 20px; + align-items: center; + +} + .subpanel-username { font-size: 14px; @@ -332,6 +358,66 @@ a { margin-block: 0 !important; } +.views-items { + + width: 100%; + display: flex; + flex-direction: row; + gap: 15px; +} + +.view-item { + + + display: flex; + align-items: center; + flex-direction: row; + gap: 10px; + font-size: 14px; + background-color: #3230319d; + padding: 5px; + padding-left: 10px; + padding-right: 10px; + border-radius: 15px; + transition: 0.3s; + user-select: none; + +} + +.view-item:hover { + + background-color: #4e4b4d9d; + cursor: pointer; + transform: scale(1.05); + +} + +.view-item:active { + + background-color: #4e4b4d9d; + cursor: pointer; + transform: scale(0.975); + +} + +.view-item p { + + text-align: start; +} +.menu-signout { + + color: #ff5d51; + cursor: pointer; + font-size: 14px; + display: grid; + grid-template-columns: 0.2fr 0.8fr; + gap: 10px; +} + +.dm-element:hover .menu-signout { + color: black; +} + .subpanel-dispname { @@ -513,6 +599,17 @@ a { color: #ff5d51; } +.view-closediv { + + display: flex; + flex-direction: row; + gap: 20px; +} + +.minimized { + + height: 7% !important; +} /* Files Explorer */ @@ -792,4 +889,81 @@ a { .ln-link-url { font-size: 12px; +} + +/* SERVERS */ + +.servers { + + display: flex; + flex-direction: row; + justify-content: space-between; + padding: 20px; + user-select: none; + gap: 30px; + -webkit-user-select: none; +} + +.servers-box { + + display: flex; + flex-direction: column; + + height: 100%; + width: 100%; +} + +.servers-box-title { + + display: flex; + flex-direction: row; + gap: 10px; + align-items: center; + padding: 10px; + border-radius: 10px; + background-color: #1b1b1bc1; + transition: 0.1s; + justify-content: space-between; +} + +.servers-box-title-info { + + display: flex; + flex-direction: row; + gap: 10px; + align-items: center; +} + +.servers-metrics { + + display: grid; + grid-template-columns: 1fr 1fr; + gap: 10px; +} + +.servers-box-content { + + padding: 10px; + background-color: #3D3B3C; + margin-top: 20px; + border-radius: 10px; +} + +.servers-metrics-box { + + display: flex; + flex-direction: column; + gap: 10px; + padding: 10px; + border-radius: 10px; + background-color: #1b1b1bc1; + transition: 0.1s; +} + +.servers-metrics-box div { + + display: flex; + align-items: center; + gap: 10px; + } \ No newline at end of file diff --git a/routes/login.js b/routes/login.js index a73480d..921d943 100644 --- a/routes/login.js +++ b/routes/login.js @@ -10,7 +10,7 @@ router.get('/', function(req, res, next) { res.redirect(302, "/") } else { res.clearCookie('token') - res.render('login', {version: process.env.npm_package_version}); + res.render('login', {version: require("../package.json").version}); } diff --git a/views/index.ejs b/views/index.ejs index c733f4a..b7e13ca 100644 --- a/views/index.ejs +++ b/views/index.ejs @@ -8,58 +8,42 @@
-
- -

Gestionnaire de fichiers

-
-
- -

Gestion des services

-
-
- -

Gestion des serveurs

-
-
- -

Gestion des pipelines

-
-
- -

Web Metrics

-
-
- -

Gestion des utilisateurs

-
-
- -

Générateur de lien

-
-
- -

Paramètres

-
+

Aucune permission ne semble vous êtes accordée
Demandez à Raphix afin de résoudre ce problème

-
- -
-

DisplayName

-

Username

+
+
+ +
+ +
- + +
+
+

DisplayName

+

Username

+
+ + +
+
- +
+ + + -