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;
}
/**
* Récupère depuis le document l'identifiant de l'élément
* @param {string} id Identifiant de l'élément `id='identifiant'`
* @returns
*/
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 TextResponse {
constructor(name) {
this.name = name
this.element = getID(this.name)
this.element.innerHTML = " "
this.element.style.fontSize = "14px"
this.element.style.textAlign = "center"
}
clear() {
this.element.innerHTML = " "
}
err(text) {
this.element.classList.add("yellow")
this.element.innerHTML = " " + text
}
info(text) {
this.element.classList.remove("yellow")
this.element.innerHTML = " " + text
}
setSize(size) {
this.element.style.fontSize = size
}
setWidth(width) {
this.element.style.width = width
}
}
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
ViewWindowDiv
ViewProperties = null
ViewSpanInteger = null
ViewPopupSpanInteger = null
ViewPopupHTML = null
ViewPopupTitle = null
ViewItem = new ViewItem(this)
constructor (properties) {
if(!AllViews.has(properties.title)) {
this.ViewProperties = properties
AllViews.set(properties.title, true)
this.ViewHTML = `
`
this.ViewSpanInteger = document.createElement("div")
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()
}
})
let isDragging = false;
let offsetX, offsetY;
windowDiv.style.zIndex = zIndex + 1
header.addEventListener('mousedown', (e) => {
isDragging = true;
zIndex+=2
windowDiv.style.zIndex = zIndex
// Enregistrez la position de la souris par rapport à la fenêtre
offsetX = e.clientX - windowDiv.getBoundingClientRect().left;
offsetY = e.clientY - windowDiv.getBoundingClientRect().top;
});
// Gérer le déplacement
document.addEventListener('mousemove', (e) => {
if (isDragging) {
header.style.cursor = "grab"
// Calculez la nouvelle position de la fenêtre en fonction de la position de la souris
const newLeft = e.clientX - offsetX;
const newTop = e.clientY - offsetY;
// Limitation de la position pour éviter un débordement
const maxX = window.innerWidth - windowDiv.offsetWidth;
const maxY = window.innerHeight - windowDiv.offsetHeight;
windowDiv.style.left = Math.min(Math.max(newLeft, 0), maxX) + 'px';
windowDiv.style.top = Math.min(Math.max(newTop, 0), maxY) + 'px';
}
});
// Gérer la fin du glisser-déposer
document.addEventListener('mouseup', () => {
header.style.cursor = "unset"
isDragging = false;
});
}
this.ViewItem.show()
}
destroy() {
const win = getID(`${this.ViewProperties.title}_window`)
win.outerHTML = " "
AllViews.delete(this.ViewProperties.title)
this.ViewItem.hide()
}
setContent(text) {
const contentDiv = document.getElementById(this.ViewProperties.title + "_content")
contentDiv.innerHTML = text
}
getViewTitle() {
return this.ViewProperties.title
}
createPopup(properties) {
this.ViewPopupHTML = ``
const contentDiv = getID(this.ViewProperties.title + "_content")
const popupDiv = getID(this.ViewProperties.title + "_popupDiv")
this.ViewPopupSpanInteger = document.createElement("div")
popupDiv.appendChild(this.ViewPopupSpanInteger);
this.ViewPopupSpanInteger.outerHTML = this.ViewPopupHTML
this.ViewPopupTitle = properties.title
const popup = getID(properties.title + "_popup")
const popupClose = getID(properties.title + "_popupClose")
popupClose.addEventListener("click", () => {
this.destroyPopup()
})
// Center the popup to the window div
popup.style.left = (contentDiv.offsetWidth / 2) - (popup.offsetWidth / 2) + "px"
popup.style.top = (contentDiv.offsetHeight / 2) - (popup.offsetHeight / 2) + "px"
// Render parent element styled blur
contentDiv.classList.add("blur")
// Disable all interractions like click and events with contentDiv children
for(var child of contentDiv.children) {
child.style.pointerEvents = "none"
}
}
destroyPopup() {
const popup = getID(this.ViewPopupTitle + "_popup")
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 = ""
}
}
}
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)
}
inject(array) {
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
#enableHide = false
constructor() {
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('')
const menu = getID(`dm-${this.id}`)
menu.style.zIndex = zIndex + 2
zIndex+=1
menu.style.left = (xMousePos - 40) + "px"
menu.style.top = (yMousePos - 40) + "px"
}
this.#enableHide = false
document.addEventListener("click", () => {
this.hide()
})
}
get(action) {
return getID(this.id + "_" + action)
}
hide() {
const menu = getID(`dm-${this.id}`)
if(menu) {
menu.outerHTML = ""
}
}
}
/**
* 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
}
generateHTML() {
return `
`
}
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
View = null
constructor(properties) {
this.name = properties.name
this.description = properties.description
this.icon = properties.icon
this.url = properties.url
this.canAccess = properties.canAccess
this.View = properties.View
}
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", () => {
this.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 TextResponse("sv-power-info")
info.setWidth("350px")
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'
this.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
this.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'
this.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 composant de vue de type "Pipeline"
* @param {object} properties Propriétés du composant de vue
*/
class Pipeline {
name;
pipe;
class;
url;
View;
constructor(properties) {
this.name = properties.pipeline.name
this.class = properties.pipeline._class
this.url = properties.pipeline.url
this.pipe = properties.pipeline
this.View = properties.View
if(!this.pipe.description) {
this.pipe.description = "Aucune description"
}
}
generateHTML() {
var image = null
var classInfo = null
var lastBuildStatus = ""
if(this.class == "hudson.model.FreeStyleProject") {
image = ``
if(this.pipe.lastBuild) {
lastBuildStatus = ` Construction en cours ... - N°${this.pipe.nextBuildNumber - 1}
`
if(this.pipe.lastSuccessfulBuild) {
if(this.pipe.lastSuccessfulBuild.number == this.pipe.nextBuildNumber - 1) {
lastBuildStatus = ` Dernière construction réussie - N°${this.pipe.nextBuildNumber - 1}
`
}
}
if(this.pipe.lastFailedBuild) {
if(this.pipe.lastFailedBuild.number == this.pipe.nextBuildNumber - 1) {
lastBuildStatus = ` Dernière construction échouée - N°${this.pipe.nextBuildNumber - 1}
`
}
}
} else {
lastBuildStatus = ` Aucune construction
`
}
// TRUE : lastBuildStatus = ` Dernière construction réussie - N°${this.pipe.jobs[0].lastSuccessfulBuild.number}
`
// BUILDING : lastBuildStatus = ` Construction en cours ... - N°${this.pipe.nextBuildNumber - 1}
`
// FAILED : lastBuildStatus = ` Dernière construction échouée - N°${this.pipe.jobs[0].nextBuildNumber - 1}
`
// NOITHING : lastBuildStatus = ` Aucune construction
`
} else {
image = ``
if(this.pipe.jobs[0].lastBuild) {
lastBuildStatus = ` Construction en cours ... - N°${this.pipe.jobs[0].nextBuildNumber - 1}
`
if(this.pipe.jobs[0].lastSuccessfulBuild) {
if(this.pipe.jobs[0].lastSuccessfulBuild.number == this.pipe.jobs[0].nextBuildNumber - 1) {
lastBuildStatus = ` Dernière construction réussie - N°${this.pipe.jobs[0].nextBuildNumber - 1}
`
}
}
if(this.pipe.jobs[0].lastFailedBuild) {
if(this.pipe.jobs[0].lastFailedBuild.number == this.pipe.jobs[0].nextBuildNumber - 1) {
lastBuildStatus = ` Dernière construction échouée - N°${this.pipe.jobs[0].nextBuildNumber - 1}
`
}
}
} else {
lastBuildStatus = ` Aucune construction
`
}
}
return `
${image}
${this.name}
${this.pipe.description}
${lastBuildStatus}
`
}
loadScript() {
const powerButton = getID(`${this.name}_pipelinepower`)
powerButton.addEventListener("click", () => {
if(this.class == "hudson.model.FreeStyleProject" && this.pipe.property[0].parameterDefinitions.length > 0) {
var allProperties = new Array()
for(const property of this.pipe.property[0].parameterDefinitions) {
console.log(property)
if(property.type == "StringParameterDefinition") {
allProperties.push("" + property.name + "
")
}
if(property.type == "ChoiceParameterDefinition") {
var options = new Array()
for(const option of property.choices) {
options.push(``)
}
allProperties.push("" + property.name + "
")
}
}
this.View.createPopup({
title: ` Démarrer la pipeline`,
content: `
${this.name}
${allProperties.join("")}
`
})
const startButton = getID(`${this.name}_start`)
const info = new TextResponse("pl-power-info")
startButton.addEventListener("click", () => {
info.clear()
var allFields = new Array()
for(const property of this.pipe.property[0].parameterDefinitions) {
if(getID(property.name).value == "") {
info.err("Veuillez remplir tous les champs")
return
}
allFields.push({name: property.name,value: getID(property.name).value} )
}
const request = post(`PL_START`, {name: this.name, fields: allFields, url: this.url, type: this.class})
request.then((answer) => {
if(answer == "OK") {
info.info("La pipeline a été démarrée avec succès")
this.View.destroyPopup()
} else {
info.err("Impossible de démarrer la pipeline")
}
})
})
} else {
// Open a confirmation popup to start the pipeline
this.View.createPopup({
title: ` Démarrer la pipeline`,
content: `
${this.name}
`
})
const startButton = getID(`${this.name}_start`)
const info = new TextResponse("pl-power-info")
startButton.addEventListener("click", () => {
info.clear()
const request = post(`PL_START`, {name: this.name, url: this.url, type: this.class, jobname: this.pipe.jobs[0].name})
request.then((answer) => {
console.log(answer)
if(answer == "OK") {
info.info("La pipeline a été démarrée avec succès")
this.View.destroyPopup()
} else {
info.err("Impossible de démarrer la pipeline")
}
})
})
}
})
}
}
class User {
constructor(properties) {
this.username = properties.username
this.display_name = properties.display_name
this.picture = properties.picture
this.permission = properties.permission
this.View = properties.window
this.Component = properties.component
}
generateHTML() {
return `
${this.display_name}
${this.username}
${this.username == "raphix" ? "" : ``}
`
}
loadScript() {
const editButton = getID(`${this.username}_edit`)
const deleteButton = getID(`${this.username}_delete`)
editButton.addEventListener("click", () => {
this.View.createPopup({
title: ` Editer l'utilisateur : ${this.username}`,
content: `
${this.display_name}
${this.username}
`
})
const editCButton = getID(`${this.username}_cedit`)
const editTokensButton = getID(`${this.username}_edittokens`)
const editUsername = getID(`${this.username}_editusername`)
const editDisplay = getID(`${this.username}_editdisplay`)
const editPassword = getID(`${this.username}_editpassword`)
const editPicture = getID(`${this.username}_addpicture`)
const returnInfo = new TextResponse(`${this.username}_returninfo`)
const editPermissions = new Array()
editTokensButton.addEventListener("click", () => {
const request = post(`US_CLEAR_TOKENS`, this.username)
request.then((answer) => {
if(answer == "NO_TOKENS") {
returnInfo.err("Aucun token n'a été généré pour cet utilisateur")
} else {
returnInfo.info("Les tokens ont été éffacés avec succès")
}
})
})
editPermissions.push(getID(`${this.username}_perm_FILES_EXPLORER`))
editPermissions.push(getID(`${this.username}_perm_SERVICES`))
editPermissions.push(getID(`${this.username}_perm_LINKS`))
editPermissions.push(getID(`${this.username}_perm_SERVERS`))
editPermissions.push(getID(`${this.username}_perm_PIPELINES`))
editPermissions.push(getID(`${this.username}_perm_METRICS`))
editPermissions.push(getID(`${this.username}_perm_USERS`))
editPermissions.push(getID(`${this.username}_perm_SETTINGS`))
for(const actualPerm of this.permission) {
getID(`${this.username}_perm_${actualPerm}`).checked = true
}
editUsername.addEventListener("change", () => {
editUsername.value = editUsername.value.replace(/[^a-zA-Z0-9]/g, '')
})
editCButton.addEventListener("click", () => {
const newPerms = new Array()
for(const permission of editPermissions) {
if(permission.checked) {
newPerms.push(permission.id.replace(`${this.username}_perm_`, ""))
}
}
const request = post(`US_EDIT`, {username: this.username, newusername: editUsername.value, display_name: editDisplay.value, password: editPassword.value, permissions: newPerms, picture: editPicture.files[0]})
request.then((answer) => {
if(answer == "ALREADY_EXIST") {
returnInfo.err("L'utilisateur existe déjà !")
} else if(answer == "USERNAME_MISSING") {
returnInfo.err("Le nom d'utilisateur est manquant !")
} else if(answer == "DISPLAY_NAME_MISSING") {
returnInfo.err("Le nom d'affichage est manquant !")
} else if(answer == "PASSWORD_MISSING") {
returnInfo.err("Le mot de passe est manquant !")
} else {
this.View.destroyPopup()
this.View.destroy()
this.Component.forceWindow()
loadUserInfo()
}
})
})
})
if(this.username != "raphix") {
deleteButton.addEventListener("click", () => {
this.View.createPopup({
title: ` Supprimer l'utilisateur : ${this.username}`,
content: `
Voulez-vous vraiment supprimer l'utilisateur ${this.username} ?
`
})
const deleteCButton = getID(`${this.username}_deleteconfirm`)
deleteCButton.addEventListener("click", () => {
const request = post(`US_DELETE`, this.username)
request.then((answer) => {
if(answer == "OK") {
this.View.destroyPopup()
this.View.destroy()
this.Component.forceWindow()
} else {
console.log(answer)
}
})
})
})
}
}
}
/**
* Permet de créer un composant de vue de type "Metrics"
*/
class Metric {
properties;
View;
Component;
data;
constructor(settings) {
this.properties = settings.properties
this.View = settings.View
this.Component = settings.Component
this.data = settings.properties.data
}
generateHTML() {
return `
${this.properties.name}
${this.properties.id}
`
}
loadScript() {
const contentDiv = getID(`${this.properties.id}_content`)
if(this.data == "ERROR") {
contentDiv.innerHTML += `Impossible de charger les données de la métrique
`
} else {
for(const data of this.data) {
contentDiv.innerHTML += `${data.description}
${data.name}
Valeur : ${data.value}
`
}
}
const deleteButton = getID(`${this.properties.id}_metricpower`)
deleteButton.addEventListener("click", () => {
this.View.createPopup({
title: ` Supprimer la métrique : ${this.properties.name}`,
content: `
Voulez-vous vraiment supprimer la métrique ${this.properties.name} ?
`
})
const deleteCButton = getID(`${this.properties.id}_deleteconfirm`)
deleteCButton.addEventListener("click", () => {
const request = post(`MT_DELETE`, this.properties.id)
request.then((answer) => {
if(answer == "OK") {
this.View.destroyPopup()
this.View.destroy()
this.Component.forceWindow()
} else {
console.log(answer)
}
})
})
})
}
}
/**
* 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 = ""
}
}