934 lines
30 KiB
JavaScript
Executable File
934 lines
30 KiB
JavaScript
Executable File
/**
|
|
* Linux BenchTools - Peripheral Detail Page
|
|
*/
|
|
|
|
let peripheralId = null;
|
|
let peripheral = null;
|
|
let editMode = false;
|
|
|
|
// Initialize
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
// Get peripheral ID from URL
|
|
const urlParams = new URLSearchParams(window.location.search);
|
|
peripheralId = parseInt(urlParams.get('id'));
|
|
|
|
if (!peripheralId) {
|
|
showError('ID périphérique invalide');
|
|
setTimeout(() => window.location.href = 'peripherals.html', 2000);
|
|
return;
|
|
}
|
|
|
|
loadPeripheral();
|
|
loadPhotos();
|
|
loadDocuments();
|
|
loadLinks();
|
|
loadHistory();
|
|
|
|
const photoUrlInput = document.getElementById('photo-url');
|
|
if (photoUrlInput) {
|
|
photoUrlInput.addEventListener('input', updatePhotoUrlButton);
|
|
}
|
|
|
|
const editUtilisation = document.getElementById('edit-utilisation');
|
|
if (editUtilisation) {
|
|
editUtilisation.addEventListener('change', updateEditUtilisationFields);
|
|
}
|
|
});
|
|
|
|
// Load peripheral details
|
|
async function loadPeripheral() {
|
|
try {
|
|
peripheral = await apiRequest(`/peripherals/${peripheralId}`);
|
|
displayPeripheral(peripheral);
|
|
} catch (error) {
|
|
console.error('Error loading peripheral:', error);
|
|
showError('Erreur lors du chargement du périphérique');
|
|
}
|
|
}
|
|
|
|
// Display peripheral information
|
|
function displayPeripheral(p) {
|
|
// Update page title
|
|
document.getElementById('peripheral-name').textContent = p.nom;
|
|
document.title = `${p.nom} - Linux BenchTools`;
|
|
|
|
// Main info
|
|
document.getElementById('type_principal').textContent = p.type_principal || '-';
|
|
document.getElementById('sous_type').textContent = p.sous_type || '-';
|
|
document.getElementById('marque').textContent = p.marque || '-';
|
|
document.getElementById('modele').textContent = p.modele || '-';
|
|
document.getElementById('numero_serie').textContent = p.numero_serie || '-';
|
|
|
|
// USB info - show only if present
|
|
if (p.vendor_id) {
|
|
document.getElementById('vendor_id').textContent = p.vendor_id;
|
|
document.getElementById('vendor-id-item').style.display = 'block';
|
|
} else {
|
|
document.getElementById('vendor-id-item').style.display = 'none';
|
|
}
|
|
|
|
if (p.product_id) {
|
|
document.getElementById('product_id').textContent = p.product_id;
|
|
document.getElementById('product-id-item').style.display = 'block';
|
|
} else {
|
|
document.getElementById('product-id-item').style.display = 'none';
|
|
}
|
|
|
|
if (p.usb_device_id) {
|
|
document.getElementById('usb_device_id').textContent = p.usb_device_id;
|
|
document.getElementById('usb-device-id-item').style.display = 'block';
|
|
} else {
|
|
document.getElementById('usb-device-id-item').style.display = 'none';
|
|
}
|
|
|
|
if (p.fabricant) {
|
|
document.getElementById('fabricant').textContent = p.fabricant;
|
|
document.getElementById('fabricant-item').style.display = 'block';
|
|
} else {
|
|
document.getElementById('fabricant-item').style.display = 'none';
|
|
}
|
|
|
|
if (p.produit) {
|
|
document.getElementById('produit').textContent = p.produit;
|
|
document.getElementById('produit-item').style.display = 'block';
|
|
} else {
|
|
document.getElementById('produit-item').style.display = 'none';
|
|
}
|
|
|
|
const etatSpan = document.getElementById('etat');
|
|
if (p.etat) {
|
|
etatSpan.innerHTML = `<span class="badge badge-${getEtatClass(p.etat)}">${p.etat}</span>`;
|
|
} else {
|
|
etatSpan.textContent = '-';
|
|
}
|
|
|
|
document.getElementById('rating').innerHTML = renderStars(p.rating || 0);
|
|
document.getElementById('quantite_disponible').textContent =
|
|
`${p.quantite_disponible || 0} / ${p.quantite_totale || 0}`;
|
|
|
|
// Purchase info
|
|
document.getElementById('boutique').textContent = p.boutique || '-';
|
|
document.getElementById('date_achat').textContent = p.date_achat ? formatDate(p.date_achat) : '-';
|
|
document.getElementById('prix').textContent = p.prix ? `${p.prix.toFixed(2)} ${p.devise || 'EUR'}` : '-';
|
|
|
|
let garantieText = '-';
|
|
if (p.garantie_duree_mois) {
|
|
garantieText = `${p.garantie_duree_mois} mois`;
|
|
if (p.garantie_expiration) {
|
|
garantieText += ` (exp: ${formatDate(p.garantie_expiration)})`;
|
|
}
|
|
}
|
|
document.getElementById('garantie').textContent = garantieText;
|
|
|
|
// Location
|
|
if (p.location_id) {
|
|
document.getElementById('location').textContent = `Location #${p.location_id}`;
|
|
} else if (p.location_details) {
|
|
document.getElementById('location').textContent = p.location_details;
|
|
} else {
|
|
document.getElementById('location').textContent = '-';
|
|
}
|
|
document.getElementById('location_details').textContent = p.location_details || '-';
|
|
if (p.connecte_a) {
|
|
document.getElementById('connecte_a').textContent = p.connecte_a;
|
|
document.getElementById('connecte_a-item').style.display = 'block';
|
|
} else {
|
|
document.getElementById('connecte_a-item').style.display = 'none';
|
|
}
|
|
|
|
// Notes
|
|
document.getElementById('notes').textContent = p.notes || 'Aucune note';
|
|
|
|
attachCopyButtons();
|
|
}
|
|
|
|
// Load photos
|
|
async function loadPhotos() {
|
|
try {
|
|
const photos = await apiRequest(`/peripherals/${peripheralId}/photos`);
|
|
displayPhotos(photos);
|
|
} catch (error) {
|
|
console.error('Error loading photos:', error);
|
|
}
|
|
}
|
|
|
|
// Display photos
|
|
function displayPhotos(photos) {
|
|
const grid = document.getElementById('photos-grid');
|
|
|
|
if (photos.length === 0) {
|
|
grid.innerHTML = '<p class="text-muted">Aucune photo</p>';
|
|
return;
|
|
}
|
|
|
|
grid.innerHTML = photos.map(photo => `
|
|
<div class="photo-item">
|
|
<img src="${photo.stored_path}" alt="${escapeHtml(photo.description || 'Photo')}">
|
|
${photo.is_primary ? '<span class="badge badge-primary"><i class="fas fa-star"></i> Principale</span>' : ''}
|
|
<button class="photo-primary-toggle ${photo.is_primary ? 'active' : ''}"
|
|
onclick="setPrimaryPhoto(${photo.id})"
|
|
title="${photo.is_primary ? 'Photo principale' : 'Définir comme photo principale'}">
|
|
<i class="fas fa-${photo.is_primary ? 'check-circle' : 'circle'}"></i>
|
|
</button>
|
|
<div class="photo-actions">
|
|
<button class="btn-icon" onclick="deletePhoto(${photo.id})" title="Supprimer">
|
|
<i class="fas fa-trash"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
`).join('');
|
|
}
|
|
|
|
// Load documents
|
|
async function loadDocuments() {
|
|
try {
|
|
const documents = await apiRequest(`/peripherals/${peripheralId}/documents`);
|
|
displayDocuments(documents);
|
|
} catch (error) {
|
|
console.error('Error loading documents:', error);
|
|
}
|
|
}
|
|
|
|
// Display documents
|
|
function displayDocuments(documents) {
|
|
const list = document.getElementById('documents-list');
|
|
|
|
if (documents.length === 0) {
|
|
list.innerHTML = '<p class="text-muted">Aucun document</p>';
|
|
return;
|
|
}
|
|
|
|
list.innerHTML = documents.map(doc => `
|
|
<div class="document-item">
|
|
<div class="document-icon">
|
|
<i class="fas fa-file-${getDocIcon(doc.doc_type)}"></i>
|
|
</div>
|
|
<div class="document-info">
|
|
<strong>${escapeHtml(doc.filename)}</strong>
|
|
<span class="text-muted">${getDocTypeLabel(doc.doc_type)} - ${formatBytes(doc.size_bytes || 0)}</span>
|
|
${doc.description ? `<p>${escapeHtml(doc.description)}</p>` : ''}
|
|
</div>
|
|
<div class="document-actions">
|
|
<a href="${doc.stored_path}" target="_blank" class="btn-icon" title="Télécharger">
|
|
<i class="fas fa-download"></i>
|
|
</a>
|
|
<button class="btn-icon" onclick="deleteDocument(${doc.id})" title="Supprimer">
|
|
<i class="fas fa-trash"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
`).join('');
|
|
}
|
|
|
|
// Load links
|
|
async function loadLinks() {
|
|
try {
|
|
const links = await apiRequest(`/peripherals/${peripheralId}/links`);
|
|
displayLinks(links);
|
|
} catch (error) {
|
|
console.error('Error loading links:', error);
|
|
}
|
|
}
|
|
|
|
// Display links
|
|
function displayLinks(links) {
|
|
const list = document.getElementById('links-list');
|
|
|
|
if (links.length === 0) {
|
|
list.innerHTML = '<p class="text-muted">Aucun lien</p>';
|
|
return;
|
|
}
|
|
|
|
list.innerHTML = links.map(link => `
|
|
<div class="link-item">
|
|
<div class="link-icon">
|
|
<i class="fas fa-${getLinkIcon(link.link_type)}"></i>
|
|
</div>
|
|
<div class="link-info">
|
|
<strong>${escapeHtml(link.label)}</strong>
|
|
<span class="text-muted">${getLinkTypeLabel(link.link_type)}</span>
|
|
<a href="${escapeHtml(link.url)}" target="_blank" class="link-url">${escapeHtml(link.url)}</a>
|
|
</div>
|
|
<div class="link-actions">
|
|
<button class="btn-icon" onclick="deleteLink(${link.id})" title="Supprimer">
|
|
<i class="fas fa-trash"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
`).join('');
|
|
}
|
|
|
|
// Load history
|
|
async function loadHistory() {
|
|
try {
|
|
const history = await apiRequest(`/peripherals/${peripheralId}/history`);
|
|
displayHistory(history);
|
|
} catch (error) {
|
|
console.error('Error loading history:', error);
|
|
}
|
|
}
|
|
|
|
// Display history
|
|
function displayHistory(history) {
|
|
const list = document.getElementById('history-list');
|
|
|
|
if (history.length === 0) {
|
|
list.innerHTML = '<p class="text-muted">Aucun historique</p>';
|
|
return;
|
|
}
|
|
|
|
list.innerHTML = `
|
|
<div class="history-timeline">
|
|
${history.map(h => `
|
|
<div class="history-item">
|
|
<div class="history-icon">
|
|
<i class="fas fa-${getHistoryIcon(h.action)}"></i>
|
|
</div>
|
|
<div class="history-content">
|
|
<strong>${getHistoryActionLabel(h.action)}</strong>
|
|
<span class="text-muted">${formatDateTime(h.timestamp)}</span>
|
|
${h.user ? `<span class="text-muted">par ${escapeHtml(h.user)}</span>` : ''}
|
|
${h.notes ? `<p>${escapeHtml(h.notes)}</p>` : ''}
|
|
</div>
|
|
</div>
|
|
`).join('')}
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
// Set photo as primary
|
|
async function setPrimaryPhoto(photoId) {
|
|
try {
|
|
await apiRequest(`/peripherals/${peripheralId}/photos/${photoId}/set-primary`, {
|
|
method: 'POST'
|
|
});
|
|
|
|
showSuccess('Photo principale définie');
|
|
loadPhotos(); // Reload to update icons
|
|
} catch (error) {
|
|
console.error('Error setting primary photo:', error);
|
|
showError('Erreur lors de la définition de la photo principale');
|
|
}
|
|
}
|
|
|
|
// Upload photo
|
|
async function uploadPhoto(event) {
|
|
event.preventDefault();
|
|
|
|
const formData = new FormData(event.target);
|
|
const file = document.getElementById('photo-file').files[0];
|
|
const imageUrl = (document.getElementById('photo-url').value || '').trim();
|
|
|
|
if (!file && !imageUrl) {
|
|
showError('Veuillez choisir un fichier ou fournir une URL');
|
|
return;
|
|
}
|
|
|
|
if (imageUrl && !file) {
|
|
await uploadPhotoFromUrl();
|
|
return;
|
|
}
|
|
|
|
try {
|
|
await apiRequest(`/peripherals/${peripheralId}/photos`, {
|
|
method: 'POST',
|
|
body: formData
|
|
});
|
|
|
|
closeModal('modal-upload-photo');
|
|
showSuccess('Photo ajoutée avec succès');
|
|
loadPhotos();
|
|
} catch (error) {
|
|
console.error('Error uploading photo:', error);
|
|
showError('Erreur lors de l\'upload de la photo');
|
|
}
|
|
}
|
|
|
|
function updatePhotoUrlButton() {
|
|
const imageUrl = (document.getElementById('photo-url').value || '').trim();
|
|
const button = document.getElementById('btn-upload-url');
|
|
if (!button) return;
|
|
button.disabled = !/^https?:\/\//i.test(imageUrl);
|
|
}
|
|
|
|
async function uploadPhotoFromUrl() {
|
|
const imageUrl = (document.getElementById('photo-url').value || '').trim();
|
|
if (!/^https?:\/\//i.test(imageUrl)) {
|
|
showError('URL invalide (http/https requis)');
|
|
return;
|
|
}
|
|
|
|
const formData = new FormData();
|
|
formData.append('image_url', imageUrl);
|
|
formData.append('description', document.getElementById('photo-description').value || '');
|
|
formData.append('is_primary', document.getElementById('photo-primary').checked ? 'true' : 'false');
|
|
|
|
try {
|
|
await apiRequest(`/peripherals/${peripheralId}/photos/from-url`, {
|
|
method: 'POST',
|
|
body: formData
|
|
});
|
|
|
|
closeModal('modal-upload-photo');
|
|
document.getElementById('form-upload-photo').reset();
|
|
updatePhotoUrlButton();
|
|
showSuccess('Photo importée depuis URL');
|
|
loadPhotos();
|
|
} catch (error) {
|
|
console.error('Error importing photo from URL:', error);
|
|
showError(error.message || 'Erreur lors de l\'import de l\'URL');
|
|
}
|
|
}
|
|
|
|
// Upload document
|
|
async function uploadDocument(event) {
|
|
event.preventDefault();
|
|
|
|
const formData = new FormData(event.target);
|
|
|
|
try {
|
|
await apiRequest(`/peripherals/${peripheralId}/documents`, {
|
|
method: 'POST',
|
|
body: formData
|
|
});
|
|
|
|
closeModal('modal-upload-document');
|
|
showSuccess('Document ajouté avec succès');
|
|
loadDocuments();
|
|
} catch (error) {
|
|
console.error('Error uploading document:', error);
|
|
showError('Erreur lors de l\'upload du document');
|
|
}
|
|
}
|
|
|
|
// Add link
|
|
async function addLink(event) {
|
|
event.preventDefault();
|
|
|
|
const formData = new FormData(event.target);
|
|
const data = {
|
|
peripheral_id: peripheralId
|
|
};
|
|
|
|
for (let [key, value] of formData.entries()) {
|
|
data[key] = value;
|
|
}
|
|
|
|
try {
|
|
await apiRequest(`/peripherals/${peripheralId}/links`, {
|
|
method: 'POST',
|
|
body: JSON.stringify(data)
|
|
});
|
|
|
|
closeModal('modal-add-link');
|
|
showSuccess('Lien ajouté avec succès');
|
|
loadLinks();
|
|
} catch (error) {
|
|
console.error('Error adding link:', error);
|
|
showError('Erreur lors de l\'ajout du lien');
|
|
}
|
|
}
|
|
|
|
// Delete functions
|
|
async function deletePhoto(photoId) {
|
|
if (!confirm('Supprimer cette photo ?')) return;
|
|
|
|
try {
|
|
await apiRequest(`/peripherals/photos/${photoId}`, { method: 'DELETE' });
|
|
showSuccess('Photo supprimée');
|
|
loadPhotos();
|
|
} catch (error) {
|
|
showError('Erreur lors de la suppression');
|
|
}
|
|
}
|
|
|
|
async function deleteDocument(docId) {
|
|
if (!confirm('Supprimer ce document ?')) return;
|
|
|
|
try {
|
|
await apiRequest(`/peripherals/documents/${docId}`, { method: 'DELETE' });
|
|
showSuccess('Document supprimé');
|
|
loadDocuments();
|
|
} catch (error) {
|
|
showError('Erreur lors de la suppression');
|
|
}
|
|
}
|
|
|
|
async function deleteLink(linkId) {
|
|
if (!confirm('Supprimer ce lien ?')) return;
|
|
|
|
try {
|
|
await apiRequest(`/peripherals/links/${linkId}`, { method: 'DELETE' });
|
|
showSuccess('Lien supprimé');
|
|
loadLinks();
|
|
} catch (error) {
|
|
showError('Erreur lors de la suppression');
|
|
}
|
|
}
|
|
|
|
async function deletePeripheral() {
|
|
if (!confirm('Êtes-vous sûr de vouloir supprimer ce périphérique ?')) return;
|
|
|
|
try {
|
|
await apiRequest(`/peripherals/${peripheralId}`, { method: 'DELETE' });
|
|
showSuccess('Périphérique supprimé');
|
|
setTimeout(() => window.location.href = 'peripherals.html', 1500);
|
|
} catch (error) {
|
|
showError('Erreur lors de la suppression');
|
|
}
|
|
}
|
|
|
|
// Modal functions
|
|
function showUploadPhotoModal() {
|
|
document.getElementById('modal-upload-photo').style.display = 'block';
|
|
}
|
|
|
|
function showUploadDocumentModal() {
|
|
document.getElementById('modal-upload-document').style.display = 'block';
|
|
}
|
|
|
|
function showAddLinkModal() {
|
|
document.getElementById('modal-add-link').style.display = 'block';
|
|
}
|
|
|
|
function closeModal(modalId) {
|
|
document.getElementById(modalId).style.display = 'none';
|
|
}
|
|
|
|
// Helper functions
|
|
function getEtatClass(etat) {
|
|
const classes = {
|
|
'Neuf': 'success',
|
|
'Bon': 'info',
|
|
'Usagé': 'warning',
|
|
'Défectueux': 'danger',
|
|
'Retiré': 'secondary'
|
|
};
|
|
return classes[etat] || 'secondary';
|
|
}
|
|
|
|
function renderStars(rating) {
|
|
const fullStars = Math.floor(rating);
|
|
const hasHalfStar = rating % 1 >= 0.5;
|
|
const emptyStars = 5 - fullStars - (hasHalfStar ? 1 : 0);
|
|
|
|
let html = '';
|
|
for (let i = 0; i < fullStars; i++) html += '<i class="fas fa-star text-warning"></i>';
|
|
if (hasHalfStar) html += '<i class="fas fa-star-half-alt text-warning"></i>';
|
|
for (let i = 0; i < emptyStars; i++) html += '<i class="far fa-star text-muted"></i>';
|
|
|
|
return html;
|
|
}
|
|
|
|
function attachCopyButtons() {
|
|
const items = document.querySelectorAll('.info-item');
|
|
items.forEach(item => {
|
|
const existing = item.querySelector('.copy-field-btn');
|
|
if (existing) existing.remove();
|
|
|
|
if (item.style.display === 'none') {
|
|
return;
|
|
}
|
|
|
|
const valueEl = item.querySelector('span');
|
|
if (!valueEl) return;
|
|
|
|
const btn = document.createElement('button');
|
|
btn.type = 'button';
|
|
btn.className = 'copy-field-btn';
|
|
btn.innerHTML = '<i class="fas fa-copy"></i><span class="tooltip-copied">Copié</span>';
|
|
|
|
btn.addEventListener('click', async (event) => {
|
|
event.stopPropagation();
|
|
const text = (valueEl.innerText || '').trim();
|
|
if (!text || text === '-') {
|
|
showError('Rien à copier');
|
|
return;
|
|
}
|
|
|
|
try {
|
|
await copyTextToClipboard(text);
|
|
btn.classList.add('copied');
|
|
setTimeout(() => btn.classList.remove('copied'), 1500);
|
|
showSuccess('Copié');
|
|
} catch (error) {
|
|
console.error('Copy failed:', error);
|
|
showError('Copie impossible');
|
|
}
|
|
});
|
|
|
|
item.appendChild(btn);
|
|
});
|
|
}
|
|
|
|
async function copyTextToClipboard(text) {
|
|
if (navigator.clipboard && window.isSecureContext) {
|
|
await navigator.clipboard.writeText(text);
|
|
return;
|
|
}
|
|
|
|
// Fallback for non-HTTPS / older browsers
|
|
const input = document.createElement('input');
|
|
input.value = text;
|
|
document.body.appendChild(input);
|
|
input.select();
|
|
input.setSelectionRange(0, input.value.length);
|
|
const ok = document.execCommand('copy');
|
|
document.body.removeChild(input);
|
|
if (!ok) {
|
|
throw new Error('execCommand copy failed');
|
|
}
|
|
}
|
|
|
|
function getDocIcon(docType) {
|
|
const icons = {
|
|
'manual': 'pdf',
|
|
'warranty': 'certificate',
|
|
'invoice': 'file-invoice',
|
|
'datasheet': 'file-code',
|
|
'other': 'file'
|
|
};
|
|
return icons[docType] || 'file';
|
|
}
|
|
|
|
function getDocTypeLabel(docType) {
|
|
const labels = {
|
|
'manual': 'Manuel',
|
|
'warranty': 'Garantie',
|
|
'invoice': 'Facture',
|
|
'datasheet': 'Fiche technique',
|
|
'other': 'Autre'
|
|
};
|
|
return labels[docType] || docType;
|
|
}
|
|
|
|
function getLinkIcon(linkType) {
|
|
const icons = {
|
|
'manufacturer': 'industry',
|
|
'support': 'life-ring',
|
|
'drivers': 'download',
|
|
'documentation': 'book',
|
|
'custom': 'link'
|
|
};
|
|
return icons[linkType] || 'link';
|
|
}
|
|
|
|
function getLinkTypeLabel(linkType) {
|
|
const labels = {
|
|
'manufacturer': 'Fabricant',
|
|
'support': 'Support',
|
|
'drivers': 'Drivers',
|
|
'documentation': 'Documentation',
|
|
'custom': 'Personnalisé'
|
|
};
|
|
return labels[linkType] || linkType;
|
|
}
|
|
|
|
function getHistoryIcon(action) {
|
|
const icons = {
|
|
'created': 'plus',
|
|
'moved': 'arrows-alt',
|
|
'assigned': 'link',
|
|
'unassigned': 'unlink',
|
|
'stored': 'box'
|
|
};
|
|
return icons[action] || 'circle';
|
|
}
|
|
|
|
function getHistoryActionLabel(action) {
|
|
const labels = {
|
|
'created': 'Créé',
|
|
'moved': 'Déplacé',
|
|
'assigned': 'Assigné',
|
|
'unassigned': 'Désassigné',
|
|
'stored': 'Stocké'
|
|
};
|
|
return labels[action] || action;
|
|
}
|
|
|
|
function toggleEditMode() {
|
|
if (!peripheral) {
|
|
showError('Aucun périphérique chargé');
|
|
return;
|
|
}
|
|
|
|
// Populate form with peripheral data
|
|
document.getElementById('edit-nom').value = peripheral.nom || '';
|
|
document.getElementById('edit-type_principal').value = peripheral.type_principal || '';
|
|
document.getElementById('edit-sous_type').value = peripheral.sous_type || '';
|
|
document.getElementById('edit-marque').value = peripheral.marque || '';
|
|
document.getElementById('edit-modele').value = peripheral.modele || '';
|
|
document.getElementById('edit-numero_serie').value = peripheral.numero_serie || '';
|
|
|
|
// USB info
|
|
document.getElementById('edit-vendor_id').value = peripheral.vendor_id || '';
|
|
document.getElementById('edit-product_id').value = peripheral.product_id || '';
|
|
document.getElementById('edit-usb_device_id').value = peripheral.usb_device_id || '';
|
|
document.getElementById('edit-fabricant').value = peripheral.fabricant || '';
|
|
document.getElementById('edit-produit').value = peripheral.produit || '';
|
|
|
|
document.getElementById('edit-boutique').value = peripheral.boutique || '';
|
|
document.getElementById('edit-date_achat').value = peripheral.date_achat || '';
|
|
document.getElementById('edit-prix').value = peripheral.prix || '';
|
|
document.getElementById('edit-devise').value = peripheral.devise || 'EUR';
|
|
document.getElementById('edit-garantie_duree_mois').value = peripheral.garantie_duree_mois || '';
|
|
|
|
document.getElementById('edit-etat').value = peripheral.etat || 'Neuf';
|
|
setEditRating(peripheral.rating || 0);
|
|
document.getElementById('edit-quantite_totale').value = peripheral.quantite_totale || 1;
|
|
document.getElementById('edit-quantite_disponible').value = peripheral.quantite_disponible || 1;
|
|
|
|
const utilisationValue = peripheral.connecte_a ? 'utilise' : 'non_utilise';
|
|
document.getElementById('edit-utilisation').value = utilisationValue;
|
|
|
|
document.getElementById('edit-synthese').value = peripheral.synthese || '';
|
|
document.getElementById('edit-cli_yaml').value = peripheral.cli_yaml || '';
|
|
document.getElementById('edit-cli_raw').value = peripheral.cli_raw || '';
|
|
document.getElementById('edit-specifications').value = peripheral.specifications || '';
|
|
document.getElementById('edit-notes').value = peripheral.notes || '';
|
|
|
|
// Load and set location
|
|
loadEditLocations(peripheral.location_id);
|
|
|
|
// Load and set boutique
|
|
loadEditBoutiques(peripheral.boutique);
|
|
|
|
// Load and set host
|
|
loadEditHosts(peripheral.connecte_a);
|
|
updateEditUtilisationFields();
|
|
loadEditStockageLocations(peripheral.location_details);
|
|
|
|
// Show modal
|
|
document.getElementById('modal-edit').style.display = 'block';
|
|
}
|
|
|
|
// Load hosts for edit modal
|
|
async function loadEditHosts(selectedHost) {
|
|
try {
|
|
const result = await apiRequest('/peripherals/config/hosts');
|
|
if (!result.success) return;
|
|
|
|
const select = document.getElementById('edit-connecte_a');
|
|
if (!select) return;
|
|
|
|
select.innerHTML = '<option value="">Non défini</option>';
|
|
|
|
result.hosts.forEach(host => {
|
|
const option = document.createElement('option');
|
|
option.value = host.nom;
|
|
option.textContent = host.localisation ? `${host.nom} (${host.localisation})` : host.nom;
|
|
if (host.nom === selectedHost) {
|
|
option.selected = true;
|
|
}
|
|
select.appendChild(option);
|
|
});
|
|
|
|
if (selectedHost && !result.hosts.find(h => h.nom === selectedHost)) {
|
|
const option = document.createElement('option');
|
|
option.value = selectedHost;
|
|
option.textContent = selectedHost;
|
|
option.selected = true;
|
|
select.appendChild(option);
|
|
}
|
|
} catch (error) {
|
|
console.error('Error loading hosts:', error);
|
|
}
|
|
}
|
|
|
|
// Load storage locations for edit modal
|
|
async function loadEditStockageLocations(selectedLocation) {
|
|
try {
|
|
const result = await apiRequest('/peripherals/config/stockage-locations');
|
|
if (!result.success) return;
|
|
|
|
const select = document.getElementById('edit-stockage_location');
|
|
if (!select) return;
|
|
|
|
select.innerHTML = '<option value="">Non défini</option>';
|
|
|
|
result.locations.forEach(name => {
|
|
const option = document.createElement('option');
|
|
option.value = name;
|
|
option.textContent = name;
|
|
if (name === selectedLocation) {
|
|
option.selected = true;
|
|
}
|
|
select.appendChild(option);
|
|
});
|
|
|
|
if (selectedLocation && !result.locations.includes(selectedLocation)) {
|
|
const option = document.createElement('option');
|
|
option.value = selectedLocation;
|
|
option.textContent = selectedLocation;
|
|
option.selected = true;
|
|
select.appendChild(option);
|
|
}
|
|
} catch (error) {
|
|
console.error('Error loading storage locations:', error);
|
|
}
|
|
}
|
|
|
|
function updateEditUtilisationFields() {
|
|
const utilisation = document.getElementById('edit-utilisation')?.value || 'non_utilise';
|
|
const hostGroup = document.getElementById('edit-group-connecte_a');
|
|
const locationGroup = document.getElementById('edit-group-location_id');
|
|
const stockageGroup = document.getElementById('edit-group-stockage_location');
|
|
|
|
if (utilisation === 'utilise') {
|
|
if (hostGroup) hostGroup.style.display = 'block';
|
|
if (locationGroup) locationGroup.style.display = 'none';
|
|
if (stockageGroup) stockageGroup.style.display = 'none';
|
|
} else {
|
|
if (hostGroup) hostGroup.style.display = 'none';
|
|
if (locationGroup) locationGroup.style.display = 'none';
|
|
if (stockageGroup) stockageGroup.style.display = 'block';
|
|
}
|
|
}
|
|
|
|
// Load boutiques for edit modal
|
|
async function loadEditBoutiques(selectedBoutique) {
|
|
try {
|
|
const result = await apiRequest('/peripherals/config/boutiques');
|
|
if (!result.success) return;
|
|
|
|
const select = document.getElementById('edit-boutique');
|
|
if (!select) return;
|
|
|
|
select.innerHTML = '<option value="">Non définie</option>';
|
|
|
|
result.boutiques.forEach(name => {
|
|
const option = document.createElement('option');
|
|
option.value = name;
|
|
option.textContent = name;
|
|
if (name === selectedBoutique) {
|
|
option.selected = true;
|
|
}
|
|
select.appendChild(option);
|
|
});
|
|
|
|
if (selectedBoutique && !result.boutiques.includes(selectedBoutique)) {
|
|
const option = document.createElement('option');
|
|
option.value = selectedBoutique;
|
|
option.textContent = selectedBoutique;
|
|
option.selected = true;
|
|
select.appendChild(option);
|
|
}
|
|
} catch (error) {
|
|
console.error('Error loading boutiques:', error);
|
|
}
|
|
}
|
|
|
|
// Load locations for edit modal
|
|
async function loadEditLocations(selectedLocationId) {
|
|
try {
|
|
const locations = await apiRequest('/locations/');
|
|
const select = document.getElementById('edit-location_id');
|
|
|
|
select.innerHTML = '<option value="">Non définie</option>';
|
|
|
|
locations.forEach(location => {
|
|
const option = document.createElement('option');
|
|
option.value = location.id;
|
|
option.textContent = location.nom;
|
|
if (location.id === selectedLocationId) {
|
|
option.selected = true;
|
|
}
|
|
select.appendChild(option);
|
|
});
|
|
} catch (error) {
|
|
console.error('Error loading locations:', error);
|
|
}
|
|
}
|
|
|
|
function closeEditModal() {
|
|
document.getElementById('modal-edit').style.display = 'none';
|
|
}
|
|
|
|
function setEditRating(rating) {
|
|
const stars = document.querySelectorAll('#edit-star-rating .fa-star');
|
|
const ratingInput = document.getElementById('edit-rating');
|
|
|
|
ratingInput.value = rating;
|
|
|
|
stars.forEach((star, index) => {
|
|
if (index < rating) {
|
|
star.classList.add('active');
|
|
} else {
|
|
star.classList.remove('active');
|
|
}
|
|
});
|
|
}
|
|
|
|
// Star rating click handler for edit form
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
const editStars = document.querySelectorAll('#edit-star-rating .fa-star');
|
|
|
|
editStars.forEach(star => {
|
|
star.addEventListener('click', () => {
|
|
const rating = parseInt(star.getAttribute('data-rating'));
|
|
setEditRating(rating);
|
|
});
|
|
});
|
|
});
|
|
|
|
async function savePeripheral(event) {
|
|
event.preventDefault();
|
|
|
|
const form = event.target;
|
|
const formData = new FormData(form);
|
|
const data = {};
|
|
|
|
// Convert FormData to object
|
|
for (let [key, value] of formData.entries()) {
|
|
// Convert numeric fields
|
|
if (key === 'utilisation') {
|
|
continue;
|
|
} else if (['prix', 'garantie_duree_mois', 'quantite_totale', 'quantite_disponible', 'rating'].includes(key)) {
|
|
data[key] = value ? parseFloat(value) : null;
|
|
} else {
|
|
data[key] = value || null;
|
|
}
|
|
}
|
|
|
|
const utilisation = document.getElementById('edit-utilisation')?.value || 'non_utilise';
|
|
if (utilisation === 'utilise') {
|
|
data.connecte_a = document.getElementById('edit-connecte_a')?.value || null;
|
|
data.location_id = null;
|
|
const hostSelect = document.getElementById('edit-connecte_a');
|
|
const hostText = hostSelect?.selectedOptions?.[0]?.textContent || '';
|
|
const match = hostText.match(/\((.+)\)$/);
|
|
if (match && match[1]) {
|
|
data.location_details = match[1];
|
|
}
|
|
} else {
|
|
data.connecte_a = null;
|
|
data.location_details = null;
|
|
data.location_id = null;
|
|
const stockage = document.getElementById('edit-stockage_location')?.value || null;
|
|
data.location_details = stockage;
|
|
}
|
|
|
|
try {
|
|
const response = await apiRequest(`/peripherals/${peripheralId}`, {
|
|
method: 'PUT',
|
|
body: JSON.stringify(data)
|
|
});
|
|
|
|
showSuccess('Périphérique mis à jour avec succès');
|
|
closeEditModal();
|
|
|
|
// Reload peripheral data
|
|
await loadPeripheral();
|
|
} catch (error) {
|
|
console.error('Error updating peripheral:', error);
|
|
showError('Erreur lors de la mise à jour du périphérique');
|
|
}
|
|
}
|
|
|
|
// Close modal when clicking outside
|
|
window.onclick = function(event) {
|
|
if (event.target.classList.contains('modal')) {
|
|
event.target.style.display = 'none';
|
|
}
|
|
}
|