Version 0.3.3 - Add of links
All checks were successful
Neutral/pipeline/head This commit looks good

This commit is contained in:
CICD - Pipeline 2023-11-05 12:12:18 +01:00
parent fb053d9897
commit adfb626dd7
11 changed files with 525 additions and 7 deletions

106
bin/links.js Normal file
View File

@ -0,0 +1,106 @@
const { LogType } = require("loguix")
const fs = require("fs")
const path = require("path")
const { __glob } = require("./global-variables")
const ulog = new LogType("Links")
const uuid = require("uuid")
const config = require("./config")
const {ApplyLinks} = require("../routes/link")
if(!fs.existsSync(__glob.DATA + path.sep + "links.json")) {
fs.writeFileSync(__glob.DATA + path.sep + "links.json", JSON.stringify([], null, 2))
}
module.exports.getLinks = function() {
return JSON.parse(fs.readFileSync(__glob.DATA + path.sep + "links.json"))
}
const FirstLinkManager = new ApplyLinks(this.getLinks())
module.exports.addLink = function(settings) {
var canDo = true
const links = this.getLinks()
var id = makeid(8)
if(settings.abstractLink) {
settings.dest = id.toString()
}
// Check if a destination already exists between links and if it's the case, we return an error "ALREADY_EXiST"
links.forEach((link) => {
if(link.dest == settings.dest) {
canDo = false
}
})
const link = {
id: id,
title: settings.title,
url: settings.url,
dest: settings.dest,
}
if(canDo) {
links.push(link)
fs.writeFileSync(__glob.DATA + path.sep + "links.json", JSON.stringify(links, null, 2))
const LinkManager = new ApplyLinks(this.getLinks())
return "OK"
} else {
return "ALREADY_EXIST"
}
}
module.exports.removeLink = function(id) {
const links = this.getLinks()
const newLinks = []
links.forEach((link) => {
if(link.id != id) {
newLinks.push(link)
}
})
fs.writeFileSync(__glob.DATA + path.sep + "links.json", JSON.stringify(newLinks, null, 2))
const LinkManager = new ApplyLinks(this.getLinks())
return "OK"
}
module.exports.updateLink = function(id, settings) {
const links = this.getLinks()
const newLinks = []
links.forEach((link) => {
if(link.id == id) {
link.title = settings.title
link.url = settings.url
}
newLinks.push(link)
})
fs.writeFileSync(__glob.DATA + path.sep + "links.json", JSON.stringify(newLinks, null, 2))
const LinkManager = new ApplyLinks(this.getLinks())
return "OK"
}
function makeid(length) {
let result = '';
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
const charactersLength = characters.length;
let counter = 0;
while (counter < length) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
counter += 1;
}
return result;
}

View File

@ -4,6 +4,7 @@ const path = require("path")
const { __glob } = require("./global-variables")
const auth = require("./auth")
const files = require("./files")
const links = require("./links.js")
const service = require("./services")
const plog = new LogType("Web")
const cook = require("cookie")
@ -113,6 +114,24 @@ module.exports.serverIO = function(server) {
PostAnswer("SV_RESTART_SERVICE", {answer: await service.restartService(sv), name: sv})
})
}
if(user.checkPermission("LINKS")) {
PostRequest("LINKS_GET_ALL", () => {
PostAnswer("LINKS_GET_ALL", {answer: "OK", links: links.getLinks()})
})
PostRequest("LINKS_ADD", (settings) => {
PostAnswer("LINKS_ADD", {answer: links.addLink(settings)})
})
PostRequest("LINKS_DELETE", (id) => {
PostAnswer("LINKS_DELETE", links.removeLink(id))
})
PostRequest("LINKS_EDIT", (settings) => {
PostAnswer("LINKS_EDIT", links.updateLink(settings.id, settings))
})
}

View File

@ -49,6 +49,7 @@ function setup() {
app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')))
app.use("/shared", express.static(__glob.SHARED))
getRouters()
users.fetchUsers()

View File

@ -1,6 +1,6 @@
{
"name": "neutral",
"version": "0.3.2",
"version": "0.3.3",
"description": "Panel d'administration de Raphix",
"main": "index.js",
"scripts": {

View File

@ -249,7 +249,11 @@ function createView(viewType) {
}
if(viewType == 'service') {
generateServiceView()
generateServiceView()
}
if(viewType == "links") {
generateLinksView()
}
}

View File

@ -55,7 +55,7 @@ REQ_user.then((ANS_user) => {
</div>`)
}
if(permValue == "LINKS") {
AvailableViews.push(` <div class="view">
AvailableViews.push(` <div onclick="createView('links')" class="view">
<span class="view-image"><i class="fa-solid fa-link"></i></span>
<p class="view-text">Générateur de lien</p>
</div>`)

295
public/javascripts/link.js Normal file
View File

@ -0,0 +1,295 @@
function generateLinksView() {
const View = new ViewWindow({
title: `<i class="fa-solid fa-link"></i> Générateur de liens`,
width: "600px",
height: "600px",
})
View.setContent(`
<div class='ln-bar'>
<button id='${View.getViewTitle()}_add' class='btn blue'><span><i class='fa fa-add'></i> Ajouter un lien</span></button>
</div>
<div class='ln-links' id='${View.getViewTitle()}_links'></div>
`)
const addBtn = getID(`${View.getViewTitle()}_add`)
const linksDiv = getID(`${View.getViewTitle()}_links`)
var links = new Array()
addBtn.addEventListener("click", () => {
View.createPopup({
title: `<i class='fa fa-add'></i> Ajouter un lien`,
content: `
<div class='ln-create'>
<input id='${View.getViewTitle()}_title' class='field' type='text' placeholder='Titre du lien'>
<input id='${View.getViewTitle()}_url' class='field' type='text' placeholder='URL du lien'>
<div class='ln-abstract-div'>
<p class='ln-abstract-label'>Abstraire le lien :</p>
<input id='${View.getViewTitle()}_ablink' type='checkbox'>
</div>
<span id='${View.getViewTitle()}_newlink_span'></span>
<p id='${View.getViewTitle()}_info'></p>
<button id='${View.getViewTitle()}_confirm' class='btn blue'><span><i class='fa fa-add'></i> Ajouter</span></button>
</div>
`
})
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 ablink = getID(`${View.getViewTitle()}_ablink`)
const newlinkSpan = getID(`${View.getViewTitle()}_newlink_span`)
ablink.checked = true
ablink.addEventListener("click", () => {
if(!ablink.checked) {
newlinkSpan.innerHTML = `
<input id='${View.getViewTitle()}_newlink' class='field' type='text' placeholder='URL du nouveau lien'>
`
} else {
newlinkSpan.innerHTML = ""
}
})
addBtn.addEventListener("click", () => {
info.clear()
console.log(ablink.checked)
if(!titleInput.value) {
info.err("Un titre est nécéssaire")
} else if(!urlInput.value) {
info.err("Une URL est nécéssaire")
} else {
var newlink = getID(`${View.getViewTitle()}_newlink`)
if(!newlink) {
newlink = { value: "" }
} else {
if(!newlink.value) {
info.err("Un nouveau lien est nécéssaire")
return false
}
}
if(!newlink.value.match(/^[a-zA-Z0-9-_]+$/)) {
info.err("L'URL n'est pas valide")
return false
}
const request = post(`LINKS_ADD`, {
title: titleInput.value,
url: urlInput.value,
abstractLink: ablink.checked,
dest: newlink.value
})
request.then((answer) => {
if(answer.answer == "OK") {
info.info("Le lien a bien été ajouté")
View.destroyPopup()
getLinks()
} else if(answer.answer == "ALREADY_EXISTS") {
info.err("Ce lien existe déjà")
} else {
info.err("Impossible d'ajouter le lien")
}
})
}
})
})
getLinks()
function getLinks() {
linksDiv.innerHTML = ""
links = new Array()
const request = post(`LINKS_GET_ALL`)
request.then((answer) => {
if(answer.answer == "OK") {
if(answer.links.length == 0) {
linksDiv.innerHTML = `<p class='lightred' style='text-align: center;'>Aucun lien disponible</p>`
}
answer.links.forEach((link) => {
links.push(link)
})
links.forEach((link) => {
linksDiv.innerHTML += `
<div class='ln-link'>
<p class='ln-link-title'>${link.title}</p>
<div>
<p class='ln-link-url'><i class="fa-solid fa-bookmark"></i> Lien original : <a href='${link.url}'>${link.url}</a></p>
<p class='ln-link-url'><i class="fa-solid fa-paperclip"></i> Lien modifié : <a href='https://neutral.raphix.fr/link/${link.dest}'> https://neutral.raphix.fr/link/${link.dest}</a></p>
</div>
<div class='ln-link-actions'>
<button id='${link.id}_edit' class='btn blue'><span><i class='fa fa-edit'></i> Modifier</span></button>
<button id='${link.id}_remove' class='btn red'><span><i class='fa fa-trash'></i> Supprimer</span></button>
</div>
</div>
`
})
links.forEach((link) => {
const editBtn = getID(`${link.id}_edit`)
editBtn.addEventListener("click", () => {
View.createPopup({
title: `<i class='fa fa-edit'></i> Modifier un lien`,
content: `
<div class='ln-create'>
<input id='${View.getViewTitle()}_edittitle' class='field' type='text' placeholder='Titre du lien' value='${link.title}'>
<input id='${View.getViewTitle()}_editurl' class='field' type='text' placeholder='URL du lien' value='${link.url}'>
<p id='${View.getViewTitle()}_editinfo'></p>
<button id='${View.getViewTitle()}_editconfirm' class='btn blue'><span><i class='fa fa-edit'></i> Modifier</span></button>
</div>
`
})
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`)
titleInput.value = link.title
urlInput.value = link.url
editBtnConfirm.addEventListener("click", () => {
if(!titleInput.value) {
info.err("Un titre est nécéssaire")
} else if(!urlInput.value) {
info.err("Une URL est nécéssaire")
} else {
const request = post(`LINKS_EDIT`, {
id: link.id,
title: titleInput.value,
url: urlInput.value
})
request.then((answer) => {
if(answer == "OK") {
info.info("Le lien a bien été modifié")
View.destroyPopup()
getLinks()
} else {
info.err("Impossible de modifier le lien")
}
})
}
})
})
const delBtn = getID(`${link.id}_remove`)
delBtn.addEventListener("click", () => {
const request = post(`LINKS_DELETE`, link.id)
request.then((answer) => {
if(answer != "OK") {
View.createPopup({
title: `<i class='fa fa-warning'></i> Erreur`,
content: `
<p>Impossible de supprimer le lien</p>
`
})
} else {
getLinks()
}
})
})
})
} else {
info.err("Impossible de récupérer les liens")
}
})
}
}

View File

@ -23,7 +23,7 @@ async function generateServiceView() {
<div>
<h1>${this.name}</h1>
<p>${this.description}</p>
<p>Etat : <span id='${this.name}_status' class="sv-status"></span></p>
<p>Etat : <span id='${this.name}_status' class="sv-status">Vérification en cours ...</span></p>
</div>
</div>

View File

@ -593,10 +593,10 @@ a {
}
.fx-editor-content {
border: none;
border-top: 1px solid rgb(70, 67, 67);
background-color: transparent;
color: white;
border: none;
padding: 15px;
height: 100%;
@ -722,4 +722,74 @@ a {
display: flex;
flex-direction: column;
gap: 10px;
}
/* Links */
.ln-bar {
display: flex;
justify-content: right;
padding: 10px;
gap: 10px;
}
.ln-create {
display: flex;
flex-direction: column;
gap: 10px;
}
.ln-abstract-label {
text-align: center;
font-size: 12px;
}
.ln-abstract-div {
display: flex;
flex-direction: row;
text-align: center;
align-items: center;
justify-content: center;
}
.ln-link-actions {
display: flex;
flex-direction: column;
gap: 10px;
align-items: flex-end;
}
.ln-link {
display: grid;
grid-template-columns: 1fr 3fr 1fr;
align-items: center;
justify-content: space-between;
padding: 10px;
border-radius: 10px;
background-color: #1b1b1bc1;
transition: 0.1s;
}
.ln-links {
display: flex;
flex-direction: column;
gap: 10px;
height: 75%;
padding: 10px;
overflow-y: auto;
}
.ln-link-url {
font-size: 12px;
}

23
routes/link.js Normal file
View File

@ -0,0 +1,23 @@
var express = require('express');
var router = express.Router();
var path = require("path")
module.exports = router;
module.exports.ApplyLinks = class {
constructor(links) {
// Remove all routes
router.stack = []
for(var link of links) {
const url = link.url
router.get("/" + link.dest, (req,res,next) => {
res.redirect(302, url)
})
}
module.exports = router;
}
}

View File

@ -53,10 +53,10 @@
</div>
<a href="/login/signout"><button class="btn yellow"><span><i class="fa fa-sign-out"></i> Déconnexion</span></button></a>
</div>
<script src="/socket.io/socket.io.js"></script>
<script defer="" src="https://use.fontawesome.com/releases/v6.4.2/js/all.js" crossorigin="anonymous"></script>
<script src="/javascripts/io.js"></script>
<script src="/javascripts/link.js"></script>
<script src="/javascripts/service.js"></script>
<script src="/javascripts/filexplorer.js"></script>
<script src="/javascripts/basics.js"></script>