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 {
@@ -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(`
`)
+
+
}
-
+
+ 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(``)
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.description}
+
+
+
+
+ `
}
- 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.description}
+
Etat : Vérification en cours ...
+
+
+
+
+
+ `
+
+
}
- 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", ``)
+ 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(`
`)
- }
- if(permValue == "USERS") {
- AvailableViews.push(`
-
-
Gestion des utilisateurs
-
`)
- }
- if(permValue == "LINKS") {
- AvailableViews.push(`
`)
- }
- if(permValue == "SETTINGS") {
- AvailableViews.push(`
`)
- }
+
+ 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()
+
+})
+
+
+/**
+
+ */
\ 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.description}
-
Etat : Vérification en cours ...
-
-
-
-
-
- `
-
-
- }
-
- 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 @@
Neutral
-
-
-
Gestionnaire de fichiers
-
-
-
-
Gestion des services
-
-
-
-
Gestion des serveurs
-
-
-
-
Gestion des pipelines
-
-
-
-
-
Gestion des utilisateurs
-
-
-
+
Aucune permission ne semble vous êtes accordée
Demandez à Raphix afin de résoudre ce problème
-
-
-
-
DisplayName
-
Username
+
+
-
+
+
+
+
DisplayName
+
Username
+
+
+
+
+
-
+
+
+
+
-