// ============================================
// GIT PUSHER - MAIN JAVASCRIPT
// Version 2.0 avec système de licence par fichier
// ============================================
// Configuration
const GIT_PUSHER_CONFIG = {
serverUrl: window.location.protocol + '//' + window.location.hostname + ':9999',
credentialsKey: 'git_pusher_credentials',
version: '2.0.0'
};
// État global
let selectedApps = [];
let isProcessing = false;
// ============================================
// INITIALISATION
// ============================================
require([
'jquery',
'splunkjs/mvc',
'splunkjs/mvc/searchmanager',
'splunkjs/mvc/simplexml/ready!'
], function($, mvc, SearchManager) {
console.log("Git Pusher v2.0 initializing...");
// Initialiser le système de licence
if (typeof initializeLicense === 'function') {
initializeLicense();
} else {
console.warn("License system not loaded");
}
// Charger les credentials sauvegardés
loadSavedCredentials();
// Récupérer les résultats de recherche pour les apps
const searchManager = mvc.Components.get('dsearch');
if (searchManager) {
searchManager.on('search:done', function() {
const results = searchManager.data('results');
if (results) {
results.on('data', function() {
const rows = results.data().rows;
const fields = results.data().fields;
renderAppsList(rows, fields);
});
}
});
}
// Exposer les fonctions globalement
window.pushDashboards = pushDashboards;
window.resetForm = resetForm;
window.toggleSelectAll = toggleSelectAll;
});
// Attacher l'événement au bouton après chargement du DOM
document.addEventListener('DOMContentLoaded', function() {
setTimeout(function() {
var pushBtn = document.getElementById('push-btn');
if (pushBtn) {
pushBtn.onclick = function() {
if (typeof pushDashboards === 'function') {
pushDashboards();
} else if (typeof window.pushDashboards === 'function') {
window.pushDashboards();
}
};
console.log("Push button event attached");
}
}, 2000); // Attendre 2 secondes que tout soit chargé
});
// ============================================
// RENDU DE LA LISTE DES APPLICATIONS
// ============================================
function renderAppsList(rows, fields) {
const container = document.getElementById('dashboard-list');
if (!container) return;
console.log("Fields:", fields);
console.log("First row:", rows[0]);
// Trouver les index des colonnes
const nameIdx = fields.indexOf('name');
const labelIdx = fields.indexOf('label');
const descIdx = fields.indexOf('description');
console.log("Index - name:", nameIdx, "label:", labelIdx);
// Générer le HTML
let html = `
${rows.length} apps
`;
let validApps = 0;
rows.forEach((row, index) => {
// Récupérer le nom - essayer plusieurs méthodes
let name = '';
if (nameIdx >= 0 && row[nameIdx]) {
name = row[nameIdx];
} else if (labelIdx >= 0 && row[labelIdx]) {
// Si name est null, utiliser label comme fallback temporaire
// On va chercher le vrai nom via l'API
name = row[labelIdx];
} else if (row[0]) {
name = row[0];
} else if (row[1]) {
name = row[1]; // Deuxième élément si premier est null
}
const label = (labelIdx >= 0 && row[labelIdx]) ? row[labelIdx] : name;
console.log(`Row ${index}: name="${name}", label="${label}"`);
// Ignorer si pas de nom ou apps système
if (!name || name.startsWith('splunk_') || name === 'learned' || name === 'launcher') {
return;
}
validApps++;
html += `
`;
});
container.innerHTML = html;
console.log(`Rendered ${validApps} valid applications out of ${rows.length}`);
}
// ============================================
// GESTION DE LA SÉLECTION
// ============================================
function updateSelectedApps() {
const checkboxes = document.querySelectorAll('#dashboard-list input[type="checkbox"][data-app-id]');
selectedApps = [];
checkboxes.forEach(cb => {
if (cb.checked) {
selectedApps.push({
id: cb.getAttribute('data-app-id'),
label: cb.getAttribute('data-app-label')
});
}
});
// Mettre à jour le "Select All"
const selectAll = document.getElementById('select-all');
if (selectAll) {
const allChecked = Array.from(checkboxes).every(cb => cb.checked);
const someChecked = Array.from(checkboxes).some(cb => cb.checked);
selectAll.checked = allChecked;
selectAll.indeterminate = someChecked && !allChecked;
}
console.log(`Selected ${selectedApps.length} apps`);
}
function toggleSelectAll(checked) {
const checkboxes = document.querySelectorAll('#dashboard-list input[type="checkbox"][data-app-id]');
checkboxes.forEach(cb => {
cb.checked = checked;
});
updateSelectedApps();
}
// ============================================
// PUSH VERS GIT
// ============================================
async function pushDashboards() {
console.log("Starting push process...");
// Vérifier si déjà en cours
if (isProcessing) {
console.log("Push already in progress");
return;
}
// Récupérer les apps sélectionnées directement depuis le DOM
var apps = [];
var checkboxes = document.querySelectorAll('#dashboard-list input[type="checkbox"][data-app-id]:checked');
checkboxes.forEach(function(cb) {
apps.push({
id: cb.getAttribute('data-app-id'),
label: cb.getAttribute('data-app-label') || cb.getAttribute('data-app-id')
});
});
console.log("Apps selected from DOM:", apps);
// Mettre à jour selectedApps
selectedApps = apps;
// Vérifier si déjà en cours
if (isProcessing) {
console.log("Push already in progress");
return;
}
// Vérifier la licence AVANT tout
if (typeof checkLicenseBeforePush === 'function') {
const licenseOk = await checkLicenseBeforePush();
if (!licenseOk) {
console.log("License check failed");
return;
}
}
// Récupérer les valeurs du formulaire
const gitUrl = document.getElementById('git-url')?.value?.trim();
const gitBranch = document.getElementById('git-branch')?.value?.trim() || 'main';
const gitToken = document.getElementById('git-token')?.value?.trim();
const commitMessage = document.getElementById('commit-message')?.value?.trim();
const saveCredentials = document.getElementById('save-credentials')?.checked;
// Mettre à jour la liste des apps sélectionnées
updateSelectedApps();
// Validation
if (!gitUrl) {
showMessage('error', 'Please enter a Git repository URL');
return;
}
if (!gitToken) {
showMessage('error', 'Please enter a Git token or password');
return;
}
if (!commitMessage) {
showMessage('error', 'Please enter a commit message');
return;
}
if (selectedApps.length === 0) {
showMessage('error', 'Please select at least one application to deploy');
return;
}
// Sauvegarder les credentials si demandé
if (saveCredentials) {
saveCredentialsToStorage(gitUrl, gitBranch, gitToken);
}
// Démarrer le push
isProcessing = true;
showLoading(true);
hideMessages();
try {
// Récupérer l'utilisateur courant
const currentUser = await getCurrentUser();
// Construire les paramètres
const params = new URLSearchParams({
git_url: gitUrl,
git_branch: gitBranch,
git_token: gitToken,
commit_message: commitMessage,
apps: JSON.stringify(selectedApps),
user: currentUser
});
console.log(`Pushing ${selectedApps.length} apps to ${gitUrl}`);
// Appeler le serveur
const response = await fetch(`${GIT_PUSHER_CONFIG.serverUrl}/push?${params.toString()}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
});
const result = await response.json();
console.log("Push result:", result);
if (result.status === 'success') {
showMessage('success', `✅ Successfully deployed ${result.apps_pushed || selectedApps.length} application(s) to Git!`);
// Reset la sélection après succès
setTimeout(() => {
toggleSelectAll(false);
}, 2000);
} else if (result.error_code === 'LICENSE_ERROR') {
showMessage('error', `🔐 ${result.message}`);
// Afficher le modal de licence
if (typeof showLicenseModal === 'function') {
showLicenseModal(result.message, result.error_code);
}
} else if (result.error_code === 'APP_LIMIT') {
showMessage('error', `📦 ${result.message}`);
} else {
showMessage('error', result.message || 'Unknown error occurred');
}
} catch (error) {
console.error("Push error:", error);
showMessage('error', `Connection error: ${error.message}. Is the Git Pusher server running?`);
} finally {
isProcessing = false;
showLoading(false);
}
}
// ============================================
// UTILITAIRES UI
// ============================================
function showLoading(show) {
const loading = document.getElementById('loading');
const pushBtn = document.getElementById('push-btn');
if (loading) {
loading.classList.toggle('active', show);
}
if (pushBtn) {
pushBtn.disabled = show;
pushBtn.textContent = show ? '⏳ Deploying...' : '✈️ Deploy to Git';
}
}
function showMessage(type, text) {
hideMessages();
const successMsg = document.getElementById('success-msg');
const errorMsg = document.getElementById('error-msg');
const successText = document.getElementById('success-text');
const errorText = document.getElementById('error-text');
if (type === 'success' && successMsg && successText) {
successText.textContent = text;
successMsg.classList.add('active');
// Auto-hide après 5 secondes
setTimeout(() => {
successMsg.classList.remove('active');
}, 5000);
} else if (type === 'error' && errorMsg && errorText) {
errorText.textContent = text;
errorMsg.classList.add('active');
}
}
function hideMessages() {
const successMsg = document.getElementById('success-msg');
const errorMsg = document.getElementById('error-msg');
if (successMsg) successMsg.classList.remove('active');
if (errorMsg) errorMsg.classList.remove('active');
}
function resetForm(clearCredentials = false) {
// Reset les champs
const commitMessage = document.getElementById('commit-message');
if (commitMessage) commitMessage.value = '';
if (clearCredentials) {
const gitUrl = document.getElementById('git-url');
const gitToken = document.getElementById('git-token');
const saveCredentials = document.getElementById('save-credentials');
if (gitUrl) gitUrl.value = '';
if (gitToken) gitToken.value = '';
if (saveCredentials) saveCredentials.checked = false;
// Supprimer les credentials sauvegardés
localStorage.removeItem(GIT_PUSHER_CONFIG.credentialsKey);
}
// Reset la sélection
toggleSelectAll(false);
// Cacher les messages
hideMessages();
console.log("Form reset" + (clearCredentials ? " (with credentials)" : ""));
}
// ============================================
// GESTION DES CREDENTIALS
// ============================================
function saveCredentialsToStorage(gitUrl, gitBranch, gitToken) {
try {
const credentials = {
gitUrl: gitUrl,
gitBranch: gitBranch,
// Note: En production, envisager une solution plus sécurisée
gitToken: btoa(gitToken), // Encodage basique (pas sécurisé, juste pour l'obfuscation)
savedAt: new Date().toISOString()
};
localStorage.setItem(GIT_PUSHER_CONFIG.credentialsKey, JSON.stringify(credentials));
console.log("Credentials saved");
} catch (error) {
console.error("Error saving credentials:", error);
}
}
function loadSavedCredentials() {
try {
const saved = localStorage.getItem(GIT_PUSHER_CONFIG.credentialsKey);
if (!saved) return;
const credentials = JSON.parse(saved);
const gitUrl = document.getElementById('git-url');
const gitBranch = document.getElementById('git-branch');
const gitToken = document.getElementById('git-token');
const saveCredentials = document.getElementById('save-credentials');
if (gitUrl && credentials.gitUrl) {
gitUrl.value = credentials.gitUrl;
}
if (gitBranch && credentials.gitBranch) {
gitBranch.value = credentials.gitBranch;
}
if (gitToken && credentials.gitToken) {
gitToken.value = atob(credentials.gitToken);
}
if (saveCredentials) {
saveCredentials.checked = true;
}
console.log("Credentials loaded from storage");
} catch (error) {
console.error("Error loading credentials:", error);
}
}
// ============================================
// RÉCUPÉRATION DE L'UTILISATEUR SPLUNK
// ============================================
async function getCurrentUser() {
try {
const response = await fetch('/en-US/splunkd/__raw/services/authentication/current-context?output_mode=json');
const data = await response.json();
return data.entry?.[0]?.content?.username || 'unknown';
} catch (error) {
console.error("Error getting current user:", error);
return 'unknown';
}
}
// ============================================
// VÉRIFICATION DU SERVEUR
// ============================================
async function checkServerHealth() {
try {
const response = await fetch(`${GIT_PUSHER_CONFIG.serverUrl}/health`, {
method: 'GET',
timeout: 5000
});
const data = await response.json();
return data.status === 'ok';
} catch (error) {
console.error("Server health check failed:", error);
return false;
}
}
// Vérifier la santé du serveur au démarrage
setTimeout(async () => {
const healthy = await checkServerHealth();
if (!healthy) {
console.warn("Git Pusher server may not be running");
} else {
console.log("Git Pusher server is healthy");
}
}, 1000);
// ============================================
// EXPORT POUR DEBUG
// ============================================
window.GitPusher = {
config: GIT_PUSHER_CONFIG,
getSelectedApps: () => selectedApps,
checkServer: checkServerHealth,
version: GIT_PUSHER_CONFIG.version
};
// ============================================
// FIX: Attacher les événements aux boutons
// ============================================
(function attachButtonEvents() {
function tryAttach() {
var pushBtn = document.getElementById('push-btn');
if (pushBtn) {
pushBtn.addEventListener('click', function(e) {
e.preventDefault();
console.log("Push button clicked");
pushDashboards();
});
console.log("✓ Push button event attached");
} else {
// Réessayer dans 500ms
setTimeout(tryAttach, 500);
}
}
// Démarrer après un délai
if (document.readyState === 'complete') {
setTimeout(tryAttach, 1000);
} else {
window.addEventListener('load', function() {
setTimeout(tryAttach, 1000);
});
}
})();