Project 'Seeger/dccviewer-js' was moved to 'digitaldynamicmeasurement/dccviewer-js'. Please update any links and bookmarks that may still have the old path.
AdminRenderer.js 16.40 KiB
// 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;
}