Files
Enclume/enclume/static/editeur.js
T
hcornet de7a691861
Construction et publication / verifier (push) Successful in 41s
Construction et publication / verifier (pull_request) Successful in 11s
Construction et publication / publier (pull_request) Skipped
Construction et publication / publier (push) Failing after 6m3s
Enclume : editeur CLAPI, catalogue de 26 packs, empaquetage Docker
2026-09-10 11:32:03 +02:00

745 lines
30 KiB
JavaScript

/* Editeur de projet Enclume.
Aucune dependance : le projet vit dans le navigateur, le serveur ne fait que
valider et generer. */
'use strict';
var CLE = 'enclume.projet';
var TYPES = JSON.parse(document.getElementById('donnees-types').textContent);
var projet = charger();
var selection = { type: 'reglages', index: 0 };
var packsCache = null;
// ------------------------------------------------------------------ modele
function projetVide() {
return {
name: 'Nouveau projet',
centreon_version: '24.x',
prefix: '',
plugins_dir: '/usr/lib/centreon/plugins',
poller: 'Central',
apply_config: true,
commands: [],
service_templates: [],
host_templates: [],
hosts: []
};
}
function charger() {
try {
var brut = localStorage.getItem(CLE);
if (!brut) return projetVide();
var p = JSON.parse(brut);
var vide = projetVide();
Object.keys(vide).forEach(function (k) { if (p[k] === undefined) p[k] = vide[k]; });
return p;
} catch (e) {
return projetVide();
}
}
var minuteurSauvegarde = null;
function sauver() {
clearTimeout(minuteurSauvegarde);
minuteurSauvegarde = setTimeout(function () {
try {
localStorage.setItem(CLE, JSON.stringify(projet));
etat('Enregistre dans ce navigateur');
} catch (e) {
etat('Enregistrement impossible : espace du navigateur sature');
}
}, 250);
}
function etat(message) {
var cible = document.getElementById('etat-sauvegarde');
cible.textContent = message;
clearTimeout(etat.minuteur);
etat.minuteur = setTimeout(function () { cible.textContent = ''; }, 2500);
}
var LISTES = {
command: { cle: 'commands', titre: 'Commandes', singulier: 'commande' },
stpl: { cle: 'service_templates', titre: 'Modeles de service', singulier: 'modele de service' },
htpl: { cle: 'host_templates', titre: "Modeles d'hote", singulier: "modele d'hote" },
host: { cle: 'hosts', titre: 'Hotes', singulier: 'hote' }
};
function liste(type) { return projet[LISTES[type].cle]; }
function nouvelObjet(type) {
if (type === 'command') return { name: '', type: 'check', line: '', comment: '' };
if (type === 'stpl') return {
name: '', alias: '', parent: 'generic-active-service-custom', command: '', command_args: '',
check_interval: 5, retry_interval: 1, max_attempts: 3, active_checks: 1, passive_checks: 0,
host_templates: [], macros: []
};
if (type === 'htpl') return {
name: '', alias: '', parents: ['generic-active-host-custom'], check_command: '',
check_command_args: '', snmp_version: '', snmp_community: '', timezone: '', macros: []
};
return { name: '', alias: '', address: '', templates: [], poller: projet.poller, hostgroups: '', macros: [] };
}
// -------------------------------------------------------------------- rail
function rendreRail() {
var rail = document.getElementById('rail');
rail.innerHTML = '';
rail.appendChild(elt('button', {
className: 'rail-reglages' + (selection.type === 'reglages' ? ' actif' : ''),
type: 'button',
textContent: 'Reglages du projet',
onclick: function () { selection = { type: 'reglages', index: 0 }; rendre(); }
}));
Object.keys(LISTES).forEach(function (type) {
var section = elt('section', { className: 'rail-groupe' });
var head = elt('div', { className: 'rail-head' });
head.appendChild(elt('h2', { textContent: LISTES[type].titre }));
head.appendChild(elt('span', { className: 'count', textContent: liste(type).length }));
head.appendChild(elt('button', {
className: 'small', type: 'button', textContent: '+', title: 'Ajouter un ' + LISTES[type].singulier,
onclick: function () {
liste(type).push(nouvelObjet(type));
selection = { type: type, index: liste(type).length - 1 };
sauver(); rendre();
}
}));
section.appendChild(head);
liste(type).forEach(function (objet, index) {
var actif = selection.type === type && selection.index === index;
var item = elt('button', {
className: 'rail-item' + (actif ? ' actif' : ''),
type: 'button',
onclick: function () { selection = { type: type, index: index }; rendre(); }
});
item.appendChild(elt('span', {
className: 'nom', textContent: objet.name || '(sans nom)',
dataset: { railNom: type + ':' + index }
}));
if (type === 'stpl' && objet.host_templates.length === 0) {
item.appendChild(elt('span', { className: 'tag warn', textContent: 'non rattache' }));
}
section.appendChild(item);
});
rail.appendChild(section);
});
}
// -------------------------------------------------------------------- main
function rendreMain() {
var main = document.getElementById('main');
main.innerHTML = '';
if (selection.type === 'generation') return rendreGeneration(main);
if (selection.type === 'reglages') return rendreReglages(main);
var items = liste(selection.type);
if (!items.length) {
if (projetTotal() === 0) {
main.appendChild(document.getElementById('tpl-vide').content.cloneNode(true));
} else {
main.appendChild(elt('p', { className: 'lede', textContent: 'Aucun objet dans cette liste.' }));
}
return;
}
if (selection.index >= items.length) selection.index = items.length - 1;
var objet = items[selection.index];
var entete = elt('div', { className: 'objet-head' });
entete.appendChild(elt('h2', { textContent: LISTES[selection.type].titre }));
entete.appendChild(elt('span', { className: 'grow' }));
entete.appendChild(elt('button', {
className: 'small', type: 'button', textContent: 'Dupliquer',
onclick: function () {
var copie = JSON.parse(JSON.stringify(objet));
copie.name = copie.name + '-copie';
items.splice(selection.index + 1, 0, copie);
selection.index += 1; sauver(); rendre();
}
}));
entete.appendChild(elt('button', {
className: 'small danger', type: 'button', textContent: 'Supprimer',
onclick: function () {
if (!confirm('Supprimer ' + (objet.name || 'cet objet') + ' ?')) return;
items.splice(selection.index, 1);
selection.index = Math.max(0, selection.index - 1);
sauver(); rendre();
}
}));
main.appendChild(entete);
if (selection.type === 'command') rendreCommande(main, objet);
if (selection.type === 'stpl') rendreStpl(main, objet);
if (selection.type === 'htpl') rendreHtpl(main, objet);
if (selection.type === 'host') rendreHost(main, objet);
}
function projetTotal() {
return projet.commands.length + projet.service_templates.length +
projet.host_templates.length + projet.hosts.length;
}
function rendreReglages(main) {
main.appendChild(elt('h2', { textContent: 'Reglages du projet' }));
main.appendChild(elt('p', {
className: 'lede',
textContent: "Ces valeurs s'appliquent a l'ensemble du code genere. Le prefixe evite les collisions " +
'avec les packs officiels deja installes sur votre central.'
}));
var grille = elt('div', { className: 'grille' });
grille.appendChild(champ('Prefixe applique aux objets crees', projet, 'prefix', { placeholder: 'ex. ACME-' }));
grille.appendChild(champ('Repertoire des plugins', projet, 'plugins_dir'));
grille.appendChild(champ('Collecteur cible', projet, 'poller'));
main.appendChild(grille);
main.appendChild(caseACocher("Ajouter APPLYCFG a la fin des scripts", projet, 'apply_config'));
var info = elt('div', { className: 'notice' });
info.appendChild(elt('p', {
textContent: 'Le projet est conserve dans ce navigateur uniquement. Rien n\u2019est envoye au serveur ' +
'tant que vous ne demandez pas la generation, et aucune macro de type mot de passe n\u2019est stockee ' +
'ni partagee.'
}));
main.appendChild(info);
}
function rendreCommande(main, cmd) {
var grille = elt('div', { className: 'grille' });
grille.appendChild(champ('Nom de la commande', cmd, 'name', { rail: true, placeholder: 'OS-Linux-SNMP-Cpu' }));
grille.appendChild(champSelect('Type', cmd, 'type', TYPES));
main.appendChild(grille);
main.appendChild(champ('Commentaire', cmd, 'comment'));
main.appendChild(champZone('Ligne de commande', cmd, 'line', {
aide: '$CENTREONPLUGINS$ sera remplace par le repertoire des plugins. ' +
'Utilisez $HOSTADDRESS$, $_HOSTMACRO$ et $_SERVICEMACRO$ comme dans Centreon.'
}));
var barre = elt('div', { className: 'barre' });
barre.appendChild(elt('button', {
type: 'button', className: 'small', textContent: 'Creer un modele de service depuis cette commande',
onclick: function () {
var stpl = nouvelObjet('stpl');
stpl.name = cmd.name;
stpl.alias = cmd.name.split('-').pop();
stpl.command = cmd.name;
stpl.macros = macrosDepuisLigne(cmd.line).service;
projet.service_templates.push(stpl);
selection = { type: 'stpl', index: projet.service_templates.length - 1 };
sauver(); rendre();
}
}));
main.appendChild(barre);
}
function macrosDepuisLigne(ligne) {
var service = (ligne.match(/\$_SERVICE([A-Z0-9_]+)\$/g) || []).map(function (m) {
return m.replace('$_SERVICE', '').replace('$', '');
});
var host = (ligne.match(/\$_HOST([A-Z0-9_]+)\$/g) || []).map(function (m) {
return m.replace('$_HOST', '').replace('$', '');
});
var uniq = function (noms) {
var vus = {}, sortie = [];
noms.forEach(function (n) {
if (vus[n]) return;
vus[n] = 1;
sortie.push({ name: n, value: '', description: '', is_password: /(PASSWORD|SECRET|TOKEN|APIKEY)/.test(n) });
});
return sortie;
};
return { service: uniq(service), host: uniq(host) };
}
function rendreStpl(main, stpl) {
var grille = elt('div', { className: 'grille' });
grille.appendChild(champ('Nom du modele', stpl, 'name', { rail: true }));
grille.appendChild(champ('Alias', stpl, 'alias'));
grille.appendChild(champ('Modele parent', stpl, 'parent'));
grille.appendChild(champSelectListe('Commande de controle', stpl, 'command',
projet.commands.map(function (c) { return c.name; })));
main.appendChild(grille);
var grille2 = elt('div', { className: 'grille quatre' });
grille2.appendChild(champ('Intervalle', stpl, 'check_interval', { type: 'number' }));
grille2.appendChild(champ('Intervalle de reprise', stpl, 'retry_interval', { type: 'number' }));
grille2.appendChild(champ('Tentatives', stpl, 'max_attempts', { type: 'number' }));
grille2.appendChild(champ('Arguments', stpl, 'command_args', { placeholder: '!80!90' }));
main.appendChild(grille2);
main.appendChild(sousTitre("Rattachement aux modeles d'hote",
"Un hote heritant d'un de ces modeles recevra ce service."));
if (!projet.host_templates.length) {
main.appendChild(elt('p', { className: 'lede', textContent: "Aucun modele d'hote dans le projet." }));
} else {
var cases = elt('div', { className: 'cases' });
projet.host_templates.forEach(function (htpl) {
cases.appendChild(caseListe(htpl.name || '(sans nom)', stpl.host_templates, htpl.name));
});
main.appendChild(cases);
}
main.appendChild(sousTitre('Macros du service', 'Seuils et parametres propres a cette sonde.'));
main.appendChild(editeurMacros(stpl, function () {
var cmd = projet.commands.filter(function (c) { return c.name === stpl.command; })[0];
return cmd ? macrosDepuisLigne(cmd.line).service : [];
}));
}
function rendreHtpl(main, htpl) {
var grille = elt('div', { className: 'grille' });
grille.appendChild(champ('Nom du modele', htpl, 'name', { rail: true, placeholder: 'OS-Linux-SNMP-custom' }));
grille.appendChild(champ('Alias', htpl, 'alias'));
grille.appendChild(champListe('Modeles parents', htpl, 'parents'));
grille.appendChild(champ('Fuseau horaire', htpl, 'timezone', { placeholder: ':Europe/Paris' }));
main.appendChild(grille);
var grille2 = elt('div', { className: 'grille' });
grille2.appendChild(champ('Commande de verification', htpl, 'check_command', { placeholder: 'check_centreon_ping' }));
grille2.appendChild(champ('Arguments', htpl, 'check_command_args', { placeholder: '!3!200,20%!400,50%' }));
grille2.appendChild(champ('Version SNMP', htpl, 'snmp_version', { placeholder: '2c' }));
grille2.appendChild(champ('Communaute SNMP', htpl, 'snmp_community'));
main.appendChild(grille2);
main.appendChild(sousTitre("Macros du modele d'hote",
'Heritees par tous les hotes rattaches : identifiants, ports, options du plugin.'));
main.appendChild(editeurMacros(htpl, function () { return []; }));
var services = projet.service_templates.filter(function (s) {
return s.host_templates.indexOf(htpl.name) !== -1;
});
main.appendChild(sousTitre('Services deployes par ce modele', services.length + ' modele(s) de service'));
var liste_ = elt('div', { className: 'puces' });
services.forEach(function (s) { liste_.appendChild(elt('span', { className: 'puce', textContent: s.name })); });
main.appendChild(liste_);
}
function rendreHost(main, host) {
var grille = elt('div', { className: 'grille' });
grille.appendChild(champ("Nom de l'hote", host, 'name', { rail: true }));
grille.appendChild(champ('Alias', host, 'alias'));
grille.appendChild(champ('Adresse IP ou DNS', host, 'address'));
grille.appendChild(champ('Collecteur', host, 'poller'));
grille.appendChild(champ("Groupes d'hotes", host, 'hostgroups'));
main.appendChild(grille);
main.appendChild(sousTitre("Modeles d'hote appliques", ''));
var cases = elt('div', { className: 'cases' });
projet.host_templates.forEach(function (htpl) {
cases.appendChild(caseListe(htpl.name || '(sans nom)', host.templates, htpl.name));
});
main.appendChild(cases);
main.appendChild(sousTitre("Macros propres a l'hote", 'Elles surchargent celles du modele.'));
main.appendChild(editeurMacros(host, function () { return []; }));
}
// --------------------------------------------------------------- generation
function rendreGeneration(main) {
main.appendChild(elt('h2', { textContent: 'Code CLAPI' }));
var zone = elt('div', { id: 'zone-generation' });
zone.appendChild(elt('p', { className: 'lede', textContent: 'Generation en cours...' }));
main.appendChild(zone);
fetch('/api/generer', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ project: projet })
}).then(function (r) { return r.json(); }).then(function (data) {
zone.innerHTML = '';
var resume = elt('div', { className: 'resume' });
Object.keys(data.summary).forEach(function (cle) {
var bloc = elt('div');
bloc.appendChild(elt('b', { textContent: data.summary[cle] }));
bloc.appendChild(elt('span', { textContent: cle }));
resume.appendChild(bloc);
});
zone.appendChild(resume);
if (data.issues.length) {
var erreurs = data.issues.filter(function (i) { return i.level === 'error'; });
var note = elt('div', { className: 'notice' + (erreurs.length ? ' bad' : '') });
note.appendChild(elt('b', {
textContent: erreurs.length
? erreurs.length + ' erreur(s) a corriger avant de deployer'
: data.issues.length + ' point(s) de vigilance'
}));
var ul = elt('ul');
data.issues.forEach(function (i) {
ul.appendChild(elt('li', { textContent: i.message, className: i.level }));
});
note.appendChild(ul);
zone.appendChild(note);
}
var noms = Object.keys(data.files);
var onglets = elt('div', { className: 'tabs' });
var panneaux = {};
noms.forEach(function (nom, i) {
var bouton = elt('button', {
type: 'button', textContent: nom,
onclick: function () {
noms.forEach(function (n) {
panneaux[n].hidden = n !== nom;
onglets.querySelectorAll('button').forEach(function (b) {
b.setAttribute('aria-selected', String(b.textContent === nom));
});
});
}
});
bouton.setAttribute('aria-selected', String(i === 0));
onglets.appendChild(bouton);
});
zone.appendChild(onglets);
noms.forEach(function (nom, i) {
var pre = elt('pre', { className: 'code', textContent: data.files[nom] });
pre.hidden = i !== 0;
panneaux[nom] = pre;
zone.appendChild(pre);
});
var barre = elt('div', { className: 'barre' });
noms.forEach(function (nom) {
barre.appendChild(elt('button', {
type: 'button', textContent: nom,
onclick: function () { telecharger(nom, data.files[nom]); }
}));
});
barre.appendChild(elt('button', {
type: 'button', className: 'primary auto', textContent: 'Archive complete (.zip)',
onclick: function () {
document.getElementById('form-zip-project').value = JSON.stringify(projet);
document.getElementById('form-zip').submit();
}
}));
zone.appendChild(barre);
}).catch(function () {
zone.innerHTML = '';
zone.appendChild(elt('div', { className: 'notice bad', textContent: 'La generation a echoue. Reessayez.' }));
});
}
function telecharger(nom, contenu) {
var blob = new Blob([contenu], { type: 'text/plain;charset=utf-8' });
var url = URL.createObjectURL(blob);
var a = elt('a', { href: url, download: nom });
document.body.appendChild(a); a.click(); a.remove();
setTimeout(function () { URL.revokeObjectURL(url); }, 1000);
}
// ------------------------------------------------------------- composants
function elt(tag, props) {
var noeud = document.createElement(tag);
Object.keys(props || {}).forEach(function (cle) {
if (cle === 'dataset') Object.assign(noeud.dataset, props[cle]);
else if (cle === 'onclick') noeud.addEventListener('click', props[cle]);
else noeud[cle] = props[cle];
});
return noeud;
}
function champ(libelle, objet, cle, options) {
options = options || {};
var label = elt('label', { className: 'field' });
label.appendChild(elt('span', { textContent: libelle }));
var input = elt('input', { type: options.type || 'text', value: objet[cle] });
if (options.placeholder) input.placeholder = options.placeholder;
input.addEventListener('input', function () {
objet[cle] = options.type === 'number' ? parseInt(input.value || '0', 10) : input.value;
if (options.rail) majNomRail();
sauver();
});
label.appendChild(input);
return label;
}
function champZone(libelle, objet, cle, options) {
options = options || {};
var label = elt('label', { className: 'field' });
label.appendChild(elt('span', { textContent: libelle }));
var zone = elt('textarea', { rows: 5, value: objet[cle] });
zone.addEventListener('input', function () { objet[cle] = zone.value; sauver(); });
label.appendChild(zone);
if (options.aide) label.appendChild(elt('small', { textContent: options.aide }));
return label;
}
function champSelect(libelle, objet, cle, choix) {
var label = elt('label', { className: 'field' });
label.appendChild(elt('span', { textContent: libelle }));
var select = elt('select');
Object.keys(choix).forEach(function (valeur) {
var option = elt('option', { value: valeur, textContent: choix[valeur] });
if (objet[cle] === valeur) option.selected = true;
select.appendChild(option);
});
select.addEventListener('change', function () { objet[cle] = select.value; sauver(); });
label.appendChild(select);
return label;
}
function champSelectListe(libelle, objet, cle, valeurs) {
var label = elt('label', { className: 'field' });
label.appendChild(elt('span', { textContent: libelle }));
var input = elt('input', { type: 'text', value: objet[cle], list: 'liste-' + cle });
var datalist = elt('datalist', { id: 'liste-' + cle });
valeurs.forEach(function (v) { datalist.appendChild(elt('option', { value: v })); });
input.addEventListener('input', function () { objet[cle] = input.value; sauver(); });
label.appendChild(input);
label.appendChild(datalist);
return label;
}
function champListe(libelle, objet, cle) {
var label = elt('label', { className: 'field' });
label.appendChild(elt('span', { textContent: libelle + ' (separes par une virgule)' }));
var input = elt('input', { type: 'text', value: (objet[cle] || []).join(', ') });
input.addEventListener('input', function () {
objet[cle] = input.value.split(',').map(function (v) { return v.trim(); }).filter(Boolean);
sauver();
});
label.appendChild(input);
return label;
}
function caseACocher(libelle, objet, cle) {
var label = elt('label', { className: 'check' });
var input = elt('input', { type: 'checkbox', checked: !!objet[cle] });
input.addEventListener('change', function () { objet[cle] = input.checked; sauver(); });
label.appendChild(input);
label.appendChild(elt('span', { textContent: libelle }));
return label;
}
function caseListe(libelle, tableau, valeur) {
var label = elt('label', { className: 'check' });
var input = elt('input', { type: 'checkbox', checked: tableau.indexOf(valeur) !== -1 });
input.addEventListener('change', function () {
var i = tableau.indexOf(valeur);
if (input.checked && i === -1) tableau.push(valeur);
if (!input.checked && i !== -1) tableau.splice(i, 1);
sauver(); rendreRail();
});
label.appendChild(input);
label.appendChild(elt('span', { textContent: libelle }));
return label;
}
function sousTitre(titre, aide) {
var bloc = elt('div', { className: 'sous-titre' });
bloc.appendChild(elt('h3', { textContent: titre }));
if (aide) bloc.appendChild(elt('span', { textContent: aide }));
return bloc;
}
function editeurMacros(objet, suggestions) {
var bloc = elt('div');
var table = elt('div', { className: 'macros-table' });
objet.macros.forEach(function (macro, index) {
var ligne = elt('div', { className: 'macro-ligne' });
var nom = elt('input', { type: 'text', value: macro.name, placeholder: 'NOM' });
nom.addEventListener('input', function () { macro.name = nom.value.toUpperCase(); nom.value = macro.name; sauver(); });
var valeur = elt('input', { type: 'text', value: macro.value, placeholder: 'valeur' });
valeur.addEventListener('input', function () { macro.value = valeur.value; sauver(); });
var desc = elt('input', { type: 'text', value: macro.description, placeholder: 'description' });
desc.addEventListener('input', function () { macro.description = desc.value; sauver(); });
var mdp = elt('label', { className: 'check', title: 'Macro de type mot de passe' });
var coche = elt('input', { type: 'checkbox', checked: !!macro.is_password });
coche.addEventListener('change', function () { macro.is_password = coche.checked; sauver(); rendreMain(); });
mdp.appendChild(coche);
mdp.appendChild(elt('span', { textContent: 'mdp' }));
var sup = elt('button', {
type: 'button', className: 'small danger', textContent: 'x',
onclick: function () { objet.macros.splice(index, 1); sauver(); rendreMain(); }
});
ligne.appendChild(nom); ligne.appendChild(valeur); ligne.appendChild(desc);
ligne.appendChild(mdp); ligne.appendChild(sup);
if (macro.is_password && macro.value) {
ligne.appendChild(elt('small', { className: 'avert', textContent: 'sortira en clair dans les fichiers' }));
}
table.appendChild(ligne);
});
bloc.appendChild(table);
var barre = elt('div', { className: 'barre' });
barre.appendChild(elt('button', {
type: 'button', className: 'small', textContent: 'Ajouter une macro',
onclick: function () {
objet.macros.push({ name: '', value: '', description: '', is_password: false });
sauver(); rendreMain();
}
}));
var manquantes = suggestions().filter(function (m) {
return !objet.macros.some(function (existante) { return existante.name === m.name; });
});
if (manquantes.length) {
barre.appendChild(elt('button', {
type: 'button', className: 'small', textContent: 'Creer les macros de la commande (' + manquantes.length + ')',
onclick: function () { manquantes.forEach(function (m) { objet.macros.push(m); }); sauver(); rendreMain(); }
}));
}
bloc.appendChild(barre);
return bloc;
}
function majNomRail() {
var cible = document.querySelector('[data-rail-nom="' + selection.type + ':' + selection.index + '"]');
if (cible) cible.textContent = liste(selection.type)[selection.index].name || '(sans nom)';
}
// ------------------------------------------------------------------ modale
function ouvrirModale(titre, construire) {
document.getElementById('modal-titre').textContent = titre;
var corps = document.getElementById('modal-corps');
corps.innerHTML = '';
construire(corps);
document.getElementById('modal').hidden = false;
}
function fermerModale() { document.getElementById('modal').hidden = true; }
function ouvrirCataloguePacks() {
ouvrirModale('Importer un pack', function (corps) {
var recherche = elt('input', { type: 'text', placeholder: 'Filtrer par nom, technologie, plugin...' });
corps.appendChild(recherche);
var resultats = elt('div', { className: 'packs' });
corps.appendChild(resultats);
function afficher(packs) {
resultats.innerHTML = '';
packs.forEach(function (pack) {
var ligne = elt('div', { className: 'pack-ligne' });
var texte = elt('div');
texte.appendChild(elt('b', { textContent: pack.name }));
if (pack.status !== 'verified') {
texte.appendChild(elt('span', { className: 'tag warn', textContent: 'a valider' }));
}
texte.appendChild(elt('div', { className: 'desc', textContent: pack.description }));
texte.appendChild(elt('div', { className: 'plugin', textContent: pack.plugin + ' | ' + pack.services.length + ' sondes' }));
ligne.appendChild(texte);
var actions = elt('div', { className: 'barre' });
actions.appendChild(elt('button', {
type: 'button', className: 'small', textContent: 'Sondes par defaut',
onclick: function () { importerPack(pack.id, false); }
}));
actions.appendChild(elt('button', {
type: 'button', className: 'small', textContent: 'Toutes les sondes',
onclick: function () { importerPack(pack.id, true); }
}));
ligne.appendChild(actions);
resultats.appendChild(ligne);
});
if (!packs.length) resultats.appendChild(elt('p', { className: 'lede', textContent: 'Aucun pack ne correspond.' }));
}
function filtrer() {
var q = recherche.value.toLowerCase();
afficher(packsCache.filter(function (p) {
return (p.name + ' ' + p.description + ' ' + p.plugin + ' ' + p.category_label).toLowerCase().indexOf(q) !== -1;
}));
}
recherche.addEventListener('input', filtrer);
if (packsCache) { afficher(packsCache); }
else {
resultats.appendChild(elt('p', { className: 'lede', textContent: 'Chargement du catalogue...' }));
fetch('/api/packs').then(function (r) { return r.json(); }).then(function (packs) {
packsCache = packs; afficher(packs);
});
}
});
}
function importerPack(id, tout) {
fetch('/api/packs/' + id + '/projet' + (tout ? '?tout=1' : ''))
.then(function (r) { return r.json(); })
.then(function (fragment) {
var ignores = [];
['commands', 'service_templates', 'host_templates'].forEach(function (cle) {
var existants = {};
projet[cle].forEach(function (o) { existants[o.name] = true; });
fragment[cle].forEach(function (o) {
if (existants[o.name]) { ignores.push(o.name); return; }
projet[cle].push(o);
});
});
fermerModale();
selection = { type: 'htpl', index: Math.max(0, projet.host_templates.length - 1) };
sauver(); rendre();
etat(ignores.length ? ignores.length + ' objet(s) deja present(s), ignore(s)' : 'Pack importe');
});
}
// ------------------------------------------------------------------ actions
function rendre() {
rendreRail();
rendreMain();
document.getElementById('projet-nom').value = projet.name;
document.getElementById('projet-version').value = projet.centreon_version;
}
document.getElementById('projet-nom').addEventListener('input', function (e) {
projet.name = e.target.value; sauver();
});
document.getElementById('projet-version').addEventListener('change', function (e) {
projet.centreon_version = e.target.value; sauver();
});
document.getElementById('btn-pack').addEventListener('click', ouvrirCataloguePacks);
document.getElementById('btn-generer').addEventListener('click', function () {
selection = { type: 'generation', index: 0 }; rendre();
});
document.getElementById('btn-export').addEventListener('click', function () {
telecharger((projet.name || 'projet').replace(/[^\w-]+/g, '-') + '.json', JSON.stringify(projet, null, 2));
});
document.getElementById('btn-import').addEventListener('click', function () {
var input = elt('input', { type: 'file', accept: '.json,application/json' });
input.addEventListener('change', function () {
var fichier = input.files[0];
if (!fichier) return;
var lecteur = new FileReader();
lecteur.onload = function () {
try {
var charge = JSON.parse(lecteur.result);
var vide = projetVide();
Object.keys(vide).forEach(function (k) { if (charge[k] === undefined) charge[k] = vide[k]; });
projet = charge;
selection = { type: 'reglages', index: 0 };
sauver(); rendre();
etat('Projet ouvert');
} catch (e) {
alert("Ce fichier n'est pas un projet valide.");
}
};
lecteur.readAsText(fichier);
});
input.click();
});
document.getElementById('btn-vider').addEventListener('click', function () {
if (!confirm('Vider le projet en cours ? Cette action est definitive.')) return;
projet = projetVide();
selection = { type: 'reglages', index: 0 };
sauver(); rendre();
});
document.querySelectorAll('[data-fermer-modal]').forEach(function (b) {
b.addEventListener('click', fermerModale);
});
document.getElementById('modal').addEventListener('click', function (e) {
if (e.target.id === 'modal') fermerModale();
});
document.addEventListener('keydown', function (e) {
if (e.key === 'Escape') fermerModale();
});
rendre();