From ae41ae459c433b2d5acea0457190da922d51e9b8 Mon Sep 17 00:00:00 2001 From: Benedikt Seeger <benedikt.seeger@ptb.de> Date: Fri, 21 Mar 2025 10:36:54 +0100 Subject: [PATCH] admindata aktualisiert --- package.json | 2 +- src/app.js | 17 ++++- src/renderers/AdminRenderer.js | 133 +++++++++++++++++++++++++++------ src/styles.css | 17 +++++ 4 files changed, 144 insertions(+), 25 deletions(-) diff --git a/package.json b/package.json index 61e981a..be6e561 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dccviewer-js", - "version": "0.1.4", + "version": "0.1.5", "description": "A JS application for displaying digital calibration certificates.", "main": "dist/dccviewer-js.bundle.js", "files": [ diff --git a/src/app.js b/src/app.js index 22c847f..a4a70e5 100644 --- a/src/app.js +++ b/src/app.js @@ -50,14 +50,29 @@ export function init(xmlStr, options = {}) { : (languages.length ? languages[0] : 'en'); // Build a dynamic language dropdown based on the extracted languages +// Build a dynamic language dropdown based on the extracted languages const langSelect = document.createElement('select'); + langSelect.classList.add('lang-select'); + +// Mapping for custom option text with flag symbols for language codes + const languageOptionText = { + de: '🇩🇪 DE Sprache wechseln', + en: '🇺🇸 EN Change Language', + fr: '🇫🇷 FR Changer de langue', + es: '🇪🇸 ES Cambiar idioma', + ru: '🇷🇺 RU Изменить язык', + cn: '🇨🇳 CN 切换语言' + }; + languages.forEach(lang => { const option = document.createElement('option'); option.value = lang; - option.textContent = lang; + // Use custom text if available; otherwise, fallback to the language code. + option.textContent = languageOptionText[lang] || lang; if (lang === selectedLanguage) option.selected = true; langSelect.appendChild(option); }); + // When the language is changed, reinitialize the app with the same XML but new language. langSelect.addEventListener('change', (e) => { init(xmlStr, { containerId, language: e.target.value }); diff --git a/src/renderers/AdminRenderer.js b/src/renderers/AdminRenderer.js index 815fab4..ce1b88e 100644 --- a/src/renderers/AdminRenderer.js +++ b/src/renderers/AdminRenderer.js @@ -28,9 +28,13 @@ export function renderAdminData(adminData, language) { const container = document.getElementById('adminData'); container.innerHTML = ''; - // Title + // Localized title for Administrative Data. + const adminTitleMapping = { + de: 'Administrative Daten', + en: 'Administrative Data' + }; const title = document.createElement('h2'); - title.textContent = `Administrative Data`; + title.textContent = adminTitleMapping[language] || adminTitleMapping.en; container.appendChild(title); // ----- CORE DATA SECTION ----- @@ -41,14 +45,14 @@ export function renderAdminData(adminData, language) { coreContainer.style.border = '1px solid #ccc'; coreContainer.style.padding = '8px'; -// Get the UUID from coreData. + // Get the UUID from coreData. const uuid = coreData['dcc:uniqueIdentifier']; -// If a UUID exists, format it using renderUUID; otherwise use 'N/A' + // If a UUID exists, format it using renderUUID; otherwise use 'N/A' const formattedUUID = uuid ? renderUUID(uuid) : 'N/A'; const uuidDivText = document.createElement('div'); uuidDivText.innerHTML = `<strong>UUID:</strong> ${formattedUUID}`; -// Increase font size and boldness + // Increase font size and boldness uuidDivText.style.marginBottom = '10px'; uuidDivText.style.fontSize = '24px'; uuidDivText.style.fontWeight = 'bold'; @@ -130,19 +134,53 @@ export function renderAdminData(adminData, language) { } 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); + + // ----- RESPONSIBLE PERSONS SECTION ----- + if (adminData['dcc:respPersons'] && adminData['dcc:respPersons']['dcc:respPerson']) { + // Separation line + const hr = document.createElement('hr'); + labDiv.appendChild(hr); + // Header for Responsible Persons (localized) + const respPersonsHeader = document.createElement('h3'); + const respPersonsMapping = { + de: "Verantwortliche Personen", + en: "Responsible Persons" + }; + respPersonsHeader.textContent = respPersonsMapping[language] || respPersonsMapping.en; + labDiv.appendChild(respPersonsHeader); + let respPersons = adminData['dcc:respPersons']['dcc:respPerson']; + if (!Array.isArray(respPersons)) { + respPersons = [respPersons]; + } + respPersons.forEach(respPerson => { + let personName = ""; + if (respPerson['dcc:person'] && + respPerson['dcc:person']['dcc:name'] && + respPerson['dcc:person']['dcc:name']['dcc:content']) { + const content = respPerson['dcc:person']['dcc:name']['dcc:content']; + personName = Array.isArray(content) + ? (content.find(c => c.$ && c.$.lang === language) || content[0])._ || '' + : content._ || content; + } + const personDiv = document.createElement('div'); + personDiv.textContent = personName; + // Mark main signer if applicable. + if (respPerson['dcc:mainSigner'] === 'true' || respPerson['dcc:mainSigner'] === true) { + const mainSignerMapping = { + de: " (Hauptunterzeichner)", + en: " (Main Signer)" + }; + personDiv.textContent += mainSignerMapping[language] || mainSignerMapping.en; + } + labDiv.appendChild(personDiv); + }); + } addressesContainer.appendChild(labDiv); } - // Customer (left side) + // Customer (right side) if (adminData['dcc:customer']) { const customer = adminData['dcc:customer']; const custDiv = document.createElement('div'); @@ -155,7 +193,44 @@ export function renderAdminData(adminData, language) { } container.appendChild(addressesContainer); -// ----- ITEMS SECTION (Updated for inline image with mouseover enlargement) ----- + // ----- PERFORMANCE FIELDS SECTION ----- + if (adminData['dcc:coreData']) { + const coreData = adminData['dcc:coreData']; + const performanceContainer = document.createElement('div'); + performanceContainer.style.marginBottom = '20px'; + performanceContainer.style.border = '1px solid #ccc'; + performanceContainer.style.padding = '8px'; + // Mapping for performance fields. + const performanceLabels = { + 'dcc:beginPerformanceDate': { + de: 'Begin der Kalibrierung', + en: 'Calibration Start' + }, + 'dcc:endPerformanceDate': { + de: 'Ende der Kalibrierung', + en: 'Calibration End' + }, + 'dcc:performanceLocation': { + de: 'Prüfungsort', + en: 'Performance Location' + }, + 'dcc:issueDate': { + de: 'Ausstellungsdatum', + en: 'Issue Date' + } + }; + // Loop through each performance field and render if available. + Object.keys(performanceLabels).forEach(key => { + if (coreData[key]) { + const fieldDiv = document.createElement('div'); + fieldDiv.innerHTML = `<strong>${performanceLabels[key][language] || performanceLabels[key].en}:</strong> ${coreData[key]}`; + performanceContainer.appendChild(fieldDiv); + } + }); + container.appendChild(performanceContainer); + } + + // ----- 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]; @@ -187,22 +262,19 @@ export function renderAdminData(adminData, language) { } detailsDiv.innerHTML += `<strong>Item:</strong> ${itemName}<br>`; -// Manufacturer details + // 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']; if (Array.isArray(content)) { - // Try to find an element matching the desired language. let found = content.find(c => c.$ && c.$.lang === language); - // If not found, look for an element without a language attribute. if (!found) { found = content.find(c => !c.$ || !c.$.lang); } manuName = found ? (typeof found === 'string' ? found : found._ || '') : ''; } else { - // Handle the case where content is a plain string or an object. manuName = typeof content === 'string' ? content : content._ || ''; } } @@ -384,7 +456,7 @@ export function renderAdminData(adminData, language) { container.appendChild(statementsContainer); } - // ----- SOFTWARE SECTION ----- +// ----- SOFTWARE SECTION (Updated) ----- if (adminData['dcc:dccSoftware'] && adminData['dcc:dccSoftware']['dcc:software']) { let softwares = adminData['dcc:dccSoftware']['dcc:software']; if (!Array.isArray(softwares)) softwares = [softwares]; @@ -392,19 +464,34 @@ export function renderAdminData(adminData, language) { softwareDiv.style.border = '1px solid #ccc'; softwareDiv.style.padding = '8px'; softwareDiv.style.marginBottom = '20px'; - softwareDiv.innerHTML = '<strong>Used Software:</strong><br>'; + const softwareTitleMapping = { + de: 'Verwendete Software', + en: 'Used Software' + }; + softwareDiv.innerHTML = `<strong>${softwareTitleMapping[language] || softwareTitleMapping.en}:</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._ || ''; + if (Array.isArray(content)) { + // Try to find an entry with a matching language. + const matching = content.find(c => c.$ && c.$.lang === language); + if (matching && matching._) { + swName = matching._; + } else { + // If no matching lang is found, use the first element regardless of its language attribute. + swName = (typeof content[0] === 'object' ? (content[0]._ || '') : content[0]); + } + } else { + // If content is not an array, check if it's an object with a "_" property or a plain string. + swName = typeof content === 'object' ? (content._ || '') : 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 diff --git a/src/styles.css b/src/styles.css index 2525970..39c419b 100644 --- a/src/styles.css +++ b/src/styles.css @@ -38,3 +38,20 @@ th, td { padding: 10px !important; /* Increase padding */ font-size: 14px; /* Adjust font size if needed */ } + +.lang-select { + font-size: 16px; /* Increase font size for better readability */ + padding: 8px; /* More padding makes it more touch-friendly */ + width: 100%; /* Use the available width */ + max-width: 200px; /* Optionally, limit the maximum width */ + box-sizing: border-box; /* Ensure padding doesn't affect total width */ + border: 1px solid #ccc; /* Add a light border */ + border-radius: 4px; /* Soften the corners */ +} + +@media (max-width: 600px) { + .lang-select { + font-size: 18px; /* Slightly larger on mobile devices */ + padding: 10px; + } +} \ No newline at end of file -- GitLab