// src/renderers/AdminRenderer.js export function renderAdminData(adminData, language) { const container = document.getElementById('adminData'); container.innerHTML = ''; // Title const title = document.createElement('h2'); title.textContent = `Administrative Data (${language})`; container.appendChild(title); // ----- CORE DATA SECTION ----- if (adminData['dcc:coreData']) { const coreData = adminData['dcc:coreData']; const coreContainer = document.createElement('div'); coreContainer.style.marginBottom = '20px'; coreContainer.style.border = '1px solid #ccc'; coreContainer.style.padding = '8px'; // Unique Identifier const uuidDiv = document.createElement('div'); uuidDiv.innerHTML = `<strong>Unique Identifier:</strong> ${coreData['dcc:uniqueIdentifier'] || 'N/A'}`; uuidDiv.style.marginBottom = '10px'; coreContainer.appendChild(uuidDiv); // Identifications table if (coreData['dcc:identifications'] && coreData['dcc:identifications']['dcc:identification']) { let identifications = coreData['dcc:identifications']['dcc:identification']; if (!Array.isArray(identifications)) { identifications = [identifications]; } const idTable = document.createElement('table'); idTable.style.width = '100%'; idTable.style.borderCollapse = 'collapse'; identifications.forEach(id => { const tr = document.createElement('tr'); tr.style.borderBottom = '1px solid #ccc'; // Identification Name (language-aware) let idName = ''; if (id['dcc:name'] && id['dcc:name']['dcc:content']) { const content = id['dcc:name']['dcc:content']; idName = Array.isArray(content) ? (content.find(item => item.$ && item.$.lang === language) || content[0])._ || '' : content._ || ''; } const tdName = document.createElement('td'); tdName.style.padding = '4px'; tdName.innerHTML = `<strong>${idName}</strong>`; tr.appendChild(tdName); // Issuer and Value const tdIssuerValue = document.createElement('td'); tdIssuerValue.style.padding = '4px'; tdIssuerValue.innerHTML = `<em>${id['dcc:issuer'] || ''}</em>: ${id['dcc:value'] || ''}`; tr.appendChild(tdIssuerValue); idTable.appendChild(tr); }); coreContainer.appendChild(idTable); } container.appendChild(coreContainer); } // ----- ADDRESSES SECTION ----- const addressesContainer = document.createElement('div'); addressesContainer.style.display = 'flex'; addressesContainer.style.justifyContent = 'space-between'; addressesContainer.style.marginBottom = '20px'; // Mapping for Calibration Laboratory and Customer static labels. const labLabelMapping = { de: 'Kalibrierlabor', en: 'Calibration Laboratory', fr: "Laboratoire d'étalonnage", es: 'Laboratorio de calibración' }; const custLabelMapping = { de: 'Kunde', en: 'Customer', fr: 'Client', es: 'Cliente' }; // Calibration Laboratory (left side) if (adminData['dcc:calibrationLaboratory'] && adminData['dcc:calibrationLaboratory']['dcc:contact']) { const calLab = adminData['dcc:calibrationLaboratory']['dcc:contact']; const labDiv = document.createElement('div'); labDiv.style.width = '45%'; labDiv.style.border = '1px solid #ccc'; labDiv.style.padding = '8px'; // Render logo from descriptionData if available: if (calLab['dcc:descriptionData']) { const descData = calLab['dcc:descriptionData']; let logoImg = ''; if (descData['dcc:dataBase64'] && descData['dcc:mimeType']) { logoImg = `<img src="data:${descData['dcc:mimeType']};base64,${descData['dcc:dataBase64']}" style="max-width:150px; max-height:150px; display:block; margin-bottom:8px;" />`; } labDiv.innerHTML += logoImg; } // Use static label based on language const labLabelMapping = { de: 'Kalibrierlabor', en: 'Calibration Laboratory', fr: "Laboratoire d'étalonnage", es: 'Laboratorio de calibración' }; labDiv.innerHTML += `<strong>${labLabelMapping[language] || 'Calibration Laboratory'}:</strong><br>`; labDiv.innerHTML += renderAddress(calLab); addressesContainer.appendChild(labDiv); } // Customer (left side) if (adminData['dcc:customer']) { const customer = adminData['dcc:customer']; const custDiv = document.createElement('div'); custDiv.style.width = '45%'; custDiv.style.border = '1px solid #ccc'; custDiv.style.padding = '8px'; custDiv.innerHTML = `<strong>${custLabelMapping[language] || 'Customer'}:</strong><br>`; custDiv.innerHTML += renderAddress(customer); addressesContainer.appendChild(custDiv); } container.appendChild(addressesContainer); // ----- ITEMS SECTION (Updated for inline image with mouseover enlargement) ----- if (adminData['dcc:items'] && adminData['dcc:items']['dcc:item']) { let items = adminData['dcc:items']['dcc:item']; if (!Array.isArray(items)) items = [items]; const itemsContainer = document.createElement('div'); itemsContainer.style.marginBottom = '20px'; itemsContainer.innerHTML = `<h3>Items</h3>`; items.forEach(item => { // Create a flex container for the item details and image. const itemDiv = document.createElement('div'); itemDiv.style.border = '1px solid #ccc'; itemDiv.style.padding = '8px'; itemDiv.style.marginBottom = '10px'; itemDiv.style.display = 'flex'; itemDiv.style.justifyContent = 'space-between'; itemDiv.style.alignItems = 'center'; // Left side: textual details const detailsDiv = document.createElement('div'); detailsDiv.style.flex = '1'; detailsDiv.style.marginRight = '10px'; // Item Name (language-aware) let itemName = ''; if (item['dcc:name'] && item['dcc:name']['dcc:content']) { const content = item['dcc:name']['dcc:content']; itemName = Array.isArray(content) ? (content.find(c => c.$ && c.$.lang === language) || content[0])._ || '' : content._ || ''; } detailsDiv.innerHTML += `<strong>Item:</strong> ${itemName}<br>`; // Manufacturer details if (item['dcc:manufacturer']) { const manu = item['dcc:manufacturer']; let manuName = ''; if (manu['dcc:name'] && manu['dcc:name']['dcc:content']) { const content = manu['dcc:name']['dcc:content']; manuName = Array.isArray(content) ? (content.find(c => c.$ && c.$.lang === language) || content[0])._ || '' : content._ || ''; } detailsDiv.innerHTML += `<strong>Manufacturer:</strong> ${manuName}<br>`; if (manu['dcc:location']) { detailsDiv.innerHTML += `<strong>Location:</strong> ${renderAddress(manu['dcc:location'])}<br>`; } } // Model if (item['dcc:model']) { detailsDiv.innerHTML += `<strong>Model:</strong> ${item['dcc:model']}<br>`; } // Item Identifications if (item['dcc:identifications'] && item['dcc:identifications']['dcc:identification']) { let identifications = item['dcc:identifications']['dcc:identification']; if (!Array.isArray(identifications)) identifications = [identifications]; detailsDiv.innerHTML += `<strong>Identifications:</strong><br>`; identifications.forEach(id => { let idName = ''; if (id['dcc:name'] && id['dcc:name']['dcc:content']) { const content = id['dcc:name']['dcc:content']; idName = Array.isArray(content) ? (content.find(item => item.$ && item.$.lang === language) || content[0])._ || '' : content._ || ''; } detailsDiv.innerHTML += `<em>${id['dcc:issuer'] || ''}</em> - ${idName}: ${id['dcc:value'] || ''}<br>`; }); } itemDiv.appendChild(detailsDiv); // Right side: always display image (if available) as an inline thumbnail if (item['dcc:description'] && item['dcc:description']['dcc:file']) { let file = item['dcc:description']['dcc:file']; if (!Array.isArray(file)) file = [file]; const firstFile = file[0]; if (firstFile['dcc:dataBase64'] && firstFile['dcc:mimeType']) { const img = document.createElement('img'); img.src = `data:${firstFile['dcc:mimeType']};base64,${firstFile['dcc:dataBase64']}`; img.style.maxWidth = '150px'; img.style.maxHeight = '150px'; img.style.transition = 'transform 0.3s'; img.style.cursor = 'pointer'; // Enlarge on mouse over img.addEventListener('mouseover', () => { img.style.transform = 'scale(1.5)'; }); img.addEventListener('mouseout', () => { img.style.transform = 'scale(1)'; }); itemDiv.appendChild(img); } } itemsContainer.appendChild(itemDiv); }); container.appendChild(itemsContainer); } // ----- STATEMENTS SECTION ----- if (adminData['dcc:statements'] && adminData['dcc:statements']['dcc:statement']) { let statements = adminData['dcc:statements']['dcc:statement']; if (!Array.isArray(statements)) { statements = [statements]; } const statementsContainer = document.createElement('div'); statementsContainer.style.marginBottom = '20px'; statementsContainer.innerHTML = `<h3>Statements</h3>`; statements.forEach(stmt => { const details = document.createElement('details'); details.style.border = '1px solid #ccc'; details.style.padding = '8px'; details.style.marginBottom = '10px'; // Summary: use dcc:name if available; if not, fallback to declaration's name let stmtName = ''; if (stmt['dcc:name'] && stmt['dcc:name']['dcc:content']) { const content = stmt['dcc:name']['dcc:content']; stmtName = Array.isArray(content) ? (content.find(item => item.$ && item.$.lang === language) || content[0])._ || '' : content._ || ''; } else if (stmt['dcc:declaration'] && stmt['dcc:declaration']['dcc:name'] && stmt['dcc:declaration']['dcc:name']['dcc:content']) { const content = stmt['dcc:declaration']['dcc:name']['dcc:content']; stmtName = Array.isArray(content) ? (content.find(item => item.$ && item.$.lang === language) || content[0])._ || '' : content._ || ''; } // If thumbnail available, render it let thumbHtml = ''; if (stmt['dcc:declaration'] && stmt['dcc:declaration']['dcc:file']) { let file = stmt['dcc:declaration']['dcc:file']; if (!Array.isArray(file)) file = [file]; const firstFile = file[0]; if (firstFile['dcc:dataBase64'] && firstFile['dcc:mimeType']) { thumbHtml = `<img src="data:${firstFile['dcc:mimeType']};base64,${firstFile['dcc:dataBase64']}" style="max-height:30px; vertical-align:middle; margin-right:8px;" />`; } } const summary = document.createElement('summary'); summary.innerHTML = thumbHtml + stmtName; details.appendChild(summary); // Expanded content const contentDiv = document.createElement('div'); contentDiv.style.marginTop = '8px'; contentDiv.style.fontFamily = 'sans-serif'; // Decision rule statements: render quantities in a table with merged value/unit if (stmt.$ && stmt.$.refType && stmt.$.refType.includes('basic_decisionRule')) { const table = document.createElement('table'); table.style.width = '100%'; table.style.borderCollapse = 'collapse'; // Header: Quantity, Value, Description const headerRow = document.createElement('tr'); ['Quantity', 'Value', 'Description'].forEach(text => { const th = document.createElement('th'); th.style.border = '1px solid #ccc'; th.style.padding = '4px'; th.textContent = text; headerRow.appendChild(th); }); table.appendChild(headerRow); if (stmt['dcc:data'] && stmt['dcc:data']['dcc:quantity']) { let quantities = stmt['dcc:data']['dcc:quantity']; if (!Array.isArray(quantities)) quantities = [quantities]; quantities.forEach(q => { const row = document.createElement('tr'); // Quantity Name let qtyName = ''; if (q['dcc:name'] && q['dcc:name']['dcc:content']) { const content = q['dcc:name']['dcc:content']; qtyName = Array.isArray(content) ? (content.find(item => item.$ && item.$.lang === language) || content[0])._ || '' : content._ || ''; } // Value and Unit merged let value = (q['si:real'] && q['si:real']['si:value']) || (q['si:realListXMLList'] && q['si:realListXMLList']['si:valueXMLList']) || ''; let unit = ''; if (q['si:real'] && q['si:real']['si:unit']) { unit = q['si:real']['si:unit'].trim(); } else if (q['si:realListXMLList'] && q['si:realListXMLList']['si:unitXMLList']) { unit = q['si:realListXMLList']['si:unitXMLList'].trim(); } const valueWithUnit = unit ? `${value} ${unit}` : value; // Description let description = ''; if (q['dcc:description'] && q['dcc:description']['dcc:content']) { const desc = q['dcc:description']['dcc:content']; description = Array.isArray(desc) ? (desc.find(item => item.$ && item.$.lang === language) || desc[0])._ || '' : desc._ || ''; } [qtyName, valueWithUnit, description].forEach(cellText => { const td = document.createElement('td'); td.style.border = '1px solid #ccc'; td.style.padding = '4px'; td.textContent = cellText; row.appendChild(td); }); table.appendChild(row); }); } contentDiv.appendChild(table); } else { // For other statements, show declaration content (language-specific) let declText = ''; if (stmt['dcc:declaration'] && stmt['dcc:declaration']['dcc:content']) { const decl = stmt['dcc:declaration']['dcc:content']; declText = Array.isArray(decl) ? (decl.find(c => c.$ && c.$.lang === language) || decl[0])._ || '' : decl._ || ''; } contentDiv.innerHTML = declText; } details.appendChild(contentDiv); statementsContainer.appendChild(details); }); container.appendChild(statementsContainer); } // ----- SOFTWARE SECTION ----- if (adminData['dcc:dccSoftware'] && adminData['dcc:dccSoftware']['dcc:software']) { let softwares = adminData['dcc:dccSoftware']['dcc:software']; if (!Array.isArray(softwares)) softwares = [softwares]; const softwareDiv = document.createElement('div'); softwareDiv.style.border = '1px solid #ccc'; softwareDiv.style.padding = '8px'; softwareDiv.style.marginBottom = '20px'; softwareDiv.innerHTML = '<strong>Used Software:</strong><br>'; softwares.forEach(sw => { let swName = ''; if (sw['dcc:name'] && sw['dcc:name']['dcc:content']) { const content = sw['dcc:name']['dcc:content']; swName = Array.isArray(content) ? (content.find(c => c.$ && c.$.lang === language) || content[0])._ || '' : content._ || ''; } softwareDiv.innerHTML += `${swName} (Release: ${sw['dcc:release'] || ''}, Type: ${sw['dcc:type'] || ''})<br>`; }); container.appendChild(softwareDiv); } } // Helper function to render a full address from a location/contact object function renderAddress(addressObj) { let addressStr = ''; // If the object has a 'dcc:location', use that; otherwise use the object directly. const loc = addressObj['dcc:location'] || addressObj; if (loc) { if (loc['dcc:street']) { addressStr += loc['dcc:street'] + ' '; } if (loc['dcc:streetNo']) { addressStr += loc['dcc:streetNo'] + '<br>'; } if (loc['dcc:postCode']) { addressStr += loc['dcc:postCode'] + ' '; } if (loc['dcc:city']) { addressStr += loc['dcc:city'] + '<br>'; } if (loc['dcc:countryCode']) { addressStr += loc['dcc:countryCode'] + '<br>'; } } // Also add email/phone if present if (addressObj['dcc:eMail']) { addressStr += addressObj['dcc:eMail'] + '<br>'; } if (addressObj['dcc:phone']) { addressStr += addressObj['dcc:phone'] + '<br>'; } return addressStr; }