diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..788049884487f566098fff92d2878803a4b674ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ + +dcc-viewer/node_modules/ diff --git a/dcc-viewer/.idea/workspace.xml b/dcc-viewer/.idea/workspace.xml new file mode 100644 index 0000000000000000000000000000000000000000..85843e948428db446b088b6455620babb8dd2881 --- /dev/null +++ b/dcc-viewer/.idea/workspace.xml @@ -0,0 +1,95 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="AutoImportSettings"> + <option name="autoReloadType" value="SELECTIVE" /> + </component> + <component name="ChangeListManager"> + <list default="true" id="c3d759c9-e9f8-41d4-b9b5-ef12db68e70c" name="Changes" comment=""> + <change afterPath="$PROJECT_DIR$/src/components/accordionComponent.js" afterDir="false" /> + <change afterPath="$PROJECT_DIR$/src/components/tabComponent.js" afterDir="false" /> + <change afterPath="$PROJECT_DIR$/src/ui/adminRenderer.js" afterDir="false" /> + <change afterPath="$PROJECT_DIR$/src/ui/jsonTreeViewer.js" afterDir="false" /> + <change afterPath="$PROJECT_DIR$/src/ui/measurementRenderer.js" afterDir="false" /> + <change beforePath="$PROJECT_DIR$/package.json" beforeDir="false" afterPath="$PROJECT_DIR$/package.json" afterDir="false" /> + <change beforePath="$PROJECT_DIR$/public/index.html" beforeDir="false" afterPath="$PROJECT_DIR$/public/index.html" afterDir="false" /> + <change beforePath="$PROJECT_DIR$/public/styles.css" beforeDir="false" afterPath="$PROJECT_DIR$/public/styles.css" afterDir="false" /> + <change beforePath="$PROJECT_DIR$/src/globalData.js" beforeDir="false" afterPath="$PROJECT_DIR$/src/globalData.js" afterDir="false" /> + <change beforePath="$PROJECT_DIR$/src/main.js" beforeDir="false" afterPath="$PROJECT_DIR$/src/main.js" afterDir="false" /> + <change beforePath="$PROJECT_DIR$/src/xmlToJson.js" beforeDir="false" afterPath="$PROJECT_DIR$/src/xmlToJson.js" afterDir="false" /> + </list> + <option name="SHOW_DIALOG" value="false" /> + <option name="HIGHLIGHT_CONFLICTS" value="true" /> + <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" /> + <option name="LAST_RESOLUTION" value="IGNORE" /> + </component> + <component name="FileTemplateManagerImpl"> + <option name="RECENT_TEMPLATES"> + <list> + <option value="JavaScript File" /> + </list> + </option> + </component> + <component name="Git.Settings"> + <option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$/.." /> + </component> + <component name="ProjectColorInfo">{ + "associatedIndex": 6 +}</component> + <component name="ProjectId" id="2tLWdqlIz5X4SCSwK5EjWvfiZtG" /> + <component name="ProjectViewState"> + <option name="hideEmptyMiddlePackages" value="true" /> + <option name="showLibraryContents" value="true" /> + </component> + <component name="PropertiesComponent"><![CDATA[{ + "keyToString": { + "JavaScript Debug.Debug Vite.executor": "Run", + "JavaScript Debug.dccViewer.executor": "Debug", + "JavaScript Debug.index.html.executor": "Run", + "Node.js.vite.config.js.executor": "Run", + "RunOnceActivity.ShowReadmeOnStart": "true", + "RunOnceActivity.git.unshallow": "true", + "git-widget-placeholder": "main", + "last_opened_file_path": "/home/seeger01/Downloads/de-6.4.jar", + "node.js.detected.package.eslint": "true", + "node.js.detected.package.tslint": "true", + "node.js.selected.package.eslint": "(autodetect)", + "node.js.selected.package.tslint": "(autodetect)", + "nodejs_package_manager_path": "npm", + "settings.editor.selected.configurable": "http.proxy", + "ts.external.directory.path": "/home/seeger01/Downloads/WebStorm-243.24978.60/plugins/javascript-plugin/jsLanguageServicesImpl/external", + "vue.rearranger.settings.migration": "true" + } +}]]></component> + <component name="RunManager"> + <configuration name="dccViewer" type="JavascriptDebugType" uri="http://localhost:5173/"> + <method v="2" /> + </configuration> + </component> + <component name="SharedIndexes"> + <attachedChunks> + <set> + <option value="bundled-js-predefined-d6986cc7102b-76f8388c3a79-JavaScript-WS-243.24978.60" /> + </set> + </attachedChunks> + </component> + <component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" /> + <component name="TaskManager"> + <task active="true" id="Default" summary="Default task"> + <changelist id="c3d759c9-e9f8-41d4-b9b5-ef12db68e70c" name="Changes" comment="" /> + <created>1740131925655</created> + <option name="number" value="Default" /> + <option name="presentableId" value="Default" /> + <updated>1740131925655</updated> + <workItem from="1740131927264" duration="102000" /> + <workItem from="1740132052064" duration="10000" /> + <workItem from="1740132146315" duration="24000" /> + <workItem from="1740132175271" duration="89000" /> + <workItem from="1740158794192" duration="1155000" /> + <workItem from="1740380748268" duration="2676000" /> + </task> + <servers /> + </component> + <component name="TypeScriptGeneratedFilesManager"> + <option name="version" value="3" /> + </component> +</project> \ No newline at end of file diff --git a/dcc-viewer/package-lock.json b/dcc-viewer/package-lock.json new file mode 100644 index 0000000000000000000000000000000000000000..dda2d33b976ae66feeea2876233dc0e720398d85 --- /dev/null +++ b/dcc-viewer/package-lock.json @@ -0,0 +1,33 @@ +{ + "name": "dcc-viewer", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "dcc-viewer", + "version": "1.0.0", + "dependencies": { + "xml-js": "^1.6.11" + } + }, + "node_modules/sax": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", + "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", + "license": "ISC" + }, + "node_modules/xml-js": { + "version": "1.6.11", + "resolved": "https://registry.npmjs.org/xml-js/-/xml-js-1.6.11.tgz", + "integrity": "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==", + "license": "MIT", + "dependencies": { + "sax": "^1.2.4" + }, + "bin": { + "xml-js": "bin/cli.js" + } + } + } +} diff --git a/dcc-viewer/package.json b/dcc-viewer/package.json index 019e6c9a0298027cd7ed9ef21b14057326696d68..68a489dc8aab18cccd57b475af372958a23e721f 100644 --- a/dcc-viewer/package.json +++ b/dcc-viewer/package.json @@ -1,6 +1,10 @@ { "name": "dcc-viewer", "version": "1.0.0", - "scripts": { "dev": "vite" }, - "dependencies": { "xml2js": "^0.4.23" } -} \ No newline at end of file + "scripts": { + "dev": "vite" + }, + "dependencies": { + "xml-js": "^1.6.11" + } +} diff --git a/dcc-viewer/public/index.html b/dcc-viewer/public/index.html index 0c36cb12debc56d206c69cc1efbbce25dcc53786..758d4eae4db7422054073aa4e1caebcdc7e54a8f 100644 --- a/dcc-viewer/public/index.html +++ b/dcc-viewer/public/index.html @@ -1,18 +1,17 @@ <!DOCTYPE html> -<html lang='en'> +<html lang="en"> <head> - <meta charset='UTF-8'> + <meta charset="UTF-8"> <title>DCC Viewer</title> - <script type='module' src='/src/main.js'></script> - <link rel='stylesheet' href='/styles.css'> + <script type="module" src="/src/main.js"></script> + <link rel="stylesheet" href="/public/styles.css"> </head> <body> - <input type='file' id='file-input' accept='.xml'> - <button id='theme-toggle'>Toggle Theme</button> - <select id='language-select'> - <option value='en'>English</option> - <option value='de'>German</option> - </select> - <div id='json-container'></div> +<h1>DCC Viewer</h1> + +<input type="file" id="file-input" accept=".xml"> + +<div id="admin-data-container"></div> +<div id="measurement-data-container"></div> </body> -</html> \ No newline at end of file +</html> diff --git a/dcc-viewer/public/styles.css b/dcc-viewer/public/styles.css index 732e263ee63412da84c8ce55819b38924955edca..79e288827bf7de1111c7ec2ff7233e5c0ed27ec0 100644 --- a/dcc-viewer/public/styles.css +++ b/dcc-viewer/public/styles.css @@ -1,2 +1,32 @@ -body { font-family: Arial, sans-serif; } -.dark-mode { background-color: black; color: white; } \ No newline at end of file +.accordion-header { + background-color: #f0f0f0; + border: none; + padding: 10px; + cursor: pointer; + width: 100%; + text-align: left; +} + +.accordion-content { + display: none; + padding: 10px; +} + +.accordion-content.open { + display: block; +} + +.tabs { + display: flex; + gap: 10px; +} + +.tabs button { + padding: 5px 10px; + cursor: pointer; +} + +.tab-content { + border: 1px solid #ddd; + padding: 10px; +} diff --git a/dcc-viewer/src/components/accordionComponent.js b/dcc-viewer/src/components/accordionComponent.js new file mode 100644 index 0000000000000000000000000000000000000000..bc77325372fe67fe6cacb284434c31b908f5e053 --- /dev/null +++ b/dcc-viewer/src/components/accordionComponent.js @@ -0,0 +1,20 @@ +export function createAccordion(title, contentElement) { + const container = document.createElement('div'); + container.classList.add('accordion'); + + const header = document.createElement('button'); + header.textContent = title; + header.classList.add('accordion-header'); + + const content = document.createElement('div'); + content.classList.add('accordion-content'); + content.appendChild(contentElement); + + header.addEventListener('click', () => { + content.classList.toggle('open'); + }); + + container.appendChild(header); + container.appendChild(content); + return container; +} diff --git a/dcc-viewer/src/components/tabComponent.js b/dcc-viewer/src/components/tabComponent.js new file mode 100644 index 0000000000000000000000000000000000000000..51b08bed095680100194b30367a927ffd6428882 --- /dev/null +++ b/dcc-viewer/src/components/tabComponent.js @@ -0,0 +1,29 @@ +export function createTabs(tabsData) { + const container = document.createElement('div'); + container.classList.add('tabs-container'); + + const tabs = document.createElement('div'); + tabs.classList.add('tabs'); + + const contentContainer = document.createElement('div'); + contentContainer.classList.add('tab-content'); + + tabsData.forEach((tab, index) => { + const button = document.createElement('button'); + button.textContent = tab.title; + button.addEventListener('click', () => { + contentContainer.innerHTML = ''; + contentContainer.appendChild(tab.content); + }); + + tabs.appendChild(button); + + if (index === 0) { + contentContainer.appendChild(tab.content); + } + }); + + container.appendChild(tabs); + container.appendChild(contentContainer); + return container; +} diff --git a/dcc-viewer/src/globalData.js b/dcc-viewer/src/globalData.js index c15978e7457a0baa7e6ff9752a479606520b61ca..d3b8d9074b47744fdd668a72552014471bfd2ece 100644 --- a/dcc-viewer/src/globalData.js +++ b/dcc-viewer/src/globalData.js @@ -1 +1,3 @@ -export const globalData = {}; \ No newline at end of file +export const globalData = { + dcc: null // This will hold the parsed DCC JSON data +}; \ No newline at end of file diff --git a/dcc-viewer/src/main.js b/dcc-viewer/src/main.js index 8b19e289e29ef67c69a7bc3f77bdd6606d25e771..29b595da0c353ef09a0ca2e718c1b6afdccca509 100644 --- a/dcc-viewer/src/main.js +++ b/dcc-viewer/src/main.js @@ -1,8 +1,9 @@ import { convertXMLToJSON } from './xmlToJson.js'; -import { JSONTreeViewer } from './components/JSONTreeViewer.js'; +import { globalData } from './globalData.js'; +import { renderAdministrativeData } from './ui/adminRenderer.js'; +import { renderMeasurementResults } from './ui/measurementRenderer.js'; const fileInput = document.getElementById('file-input'); -const container = document.getElementById('json-container'); fileInput.addEventListener('change', async (event) => { const file = event.target.files?.[0]; @@ -11,10 +12,12 @@ fileInput.addEventListener('change', async (event) => { const reader = new FileReader(); reader.onload = async () => { const xmlString = reader.result; - const jsonData = await convertXMLToJSON(xmlString); - const viewer = new JSONTreeViewer(jsonData); - container.innerHTML = ''; - container.appendChild(viewer.render()); + globalData.dcc = await convertXMLToJSON(xmlString); // Store DCC globally + + console.log("DCC Data Loaded:", globalData.dcc); + + renderAdministrativeData(globalData.dcc.administrativeData); + renderMeasurementResults(globalData.dcc.measurementResults); }; reader.readAsText(file); -}); \ No newline at end of file +}); diff --git a/dcc-viewer/src/ui/adminRenderer.js b/dcc-viewer/src/ui/adminRenderer.js new file mode 100644 index 0000000000000000000000000000000000000000..857d6a424ce931662d73d7c499317d59440d4e3b --- /dev/null +++ b/dcc-viewer/src/ui/adminRenderer.js @@ -0,0 +1,72 @@ +import { createAccordion } from '../components/accordionComponent.js'; +import { JSONTreeViewer } from './jsonTreeViewer.js'; +import { globalData } from '../globalData.js'; + +export function renderAdministrativeData() { + const container = document.getElementById('admin-data-container'); + container.innerHTML = ''; // Clear previous content + + const dccRoot = globalData.dcc?.['dcc:digitalCalibrationCertificate']; + if (!dccRoot) { + container.innerHTML = "<p>No Digital Calibration Certificate Found</p>"; + return; + } + + const adminData = dccRoot?.['dcc:administrativeData']; + if (!adminData) { + container.innerHTML = "<p>No Administrative Data Found</p>"; + return; + } + + // 🔹 SOFTWARE SECTION + const softwareContainer = document.createElement('div'); + const softwareList = (adminData?.['dcc:dccSoftware']?.['dcc:software'] || []).map(software => { + return ` + <div> + <strong>${software?.['dcc:name']?.['dcc:content'] || 'Unknown Software'}</strong> + (v${software?.['dcc:release'] || 'N/A'}) - ${software?.['dcc:type'] || 'N/A'} + </div> + `; + }).join(''); + softwareContainer.innerHTML = `<h3>Software Used</h3>${softwareList}`; + + // 🔹 CORE DATA SECTION + const coreData = adminData?.['dcc:coreData'] || {}; + const coreDataContainer = document.createElement('div'); + coreDataContainer.innerHTML = ` + <h3>Core Data</h3> + <p><strong>Country:</strong> ${coreData?.['dcc:countryCodeISO3166_1']?._text || 'N/A'}</p> + <p><strong>Languages:</strong> ${Array.isArray(coreData?.['dcc:usedLangCodeISO639_1']) + ? coreData['dcc:usedLangCodeISO639_1'].map(lang => lang._text).join(', ') + : coreData?.['dcc:usedLangCodeISO639_1']?._text || 'N/A'}</p> + <p><strong>Unique Identifier:</strong> ${coreData?.['dcc:uniqueIdentifier']?._text || 'N/A'}</p> + <p><strong>Issue Date:</strong> ${coreData?.['dcc:issueDate']?._text || 'N/A'}</p> + `; + + // 🔹 CALIBRATION LAB + const labInfo = adminData?.['dcc:calibrationLaboratory']?.['dcc:contact'] || {}; + const labContainer = document.createElement('div'); + labContainer.innerHTML = ` + <h3>Calibration Laboratory</h3> + <p><strong>Name:</strong> ${labInfo?.['dcc:name']?.['dcc:content']?._text || 'N/A'}</p> + <p><strong>Email:</strong> ${labInfo?.['dcc:eMail']?._text || 'N/A'}</p> + <p><strong>Phone:</strong> ${labInfo?.['dcc:phone']?._text || 'N/A'}</p> + `; + + // 🔹 RESPONSIBLE PERSONS + const responsiblePersons = (adminData?.['dcc:respPersons']?.['dcc:respPerson'] || []).map(person => { + return `<p>${person?.['dcc:person']?.['dcc:name']?.['dcc:content']?._text || 'Unknown Person'} + ${person?.['dcc:mainSigner'] ? '(Main Signer)' : ''}</p>`; + }).join(''); + const responsibleContainer = document.createElement('div'); + responsibleContainer.innerHTML = `<h3>Responsible Persons</h3>${responsiblePersons}`; + + // 🔹 ADD SECTIONS TO ACCORDION + container.appendChild(createAccordion("Software Used", softwareContainer)); + container.appendChild(createAccordion("Core Data", coreDataContainer)); + container.appendChild(createAccordion("Calibration Laboratory", labContainer)); + container.appendChild(createAccordion("Responsible Persons", responsibleContainer)); + + // 🔹 JSON DEBUG VIEW + container.appendChild(createAccordion("Raw JSON Data (Debug)", new JSONTreeViewer(adminData).render())); +} diff --git a/dcc-viewer/src/ui/jsonTreeViewer.js b/dcc-viewer/src/ui/jsonTreeViewer.js new file mode 100644 index 0000000000000000000000000000000000000000..fdb88bbfa75159c50b37a6f0bb8aad793ff17a4c --- /dev/null +++ b/dcc-viewer/src/ui/jsonTreeViewer.js @@ -0,0 +1,11 @@ +export class JSONTreeViewer { + constructor(data) { + this.data = data; + } + + render() { + const container = document.createElement('pre'); + container.textContent = JSON.stringify(this.data, null, 2); + return container; + } +} diff --git a/dcc-viewer/src/ui/measurementRenderer.js b/dcc-viewer/src/ui/measurementRenderer.js new file mode 100644 index 0000000000000000000000000000000000000000..4b64b370bf410c938e26d1b0b08bd064aca2c8b5 --- /dev/null +++ b/dcc-viewer/src/ui/measurementRenderer.js @@ -0,0 +1,63 @@ +import { createTabs } from '../components/tabComponent.js'; +import { JSONTreeViewer } from './jsonTreeViewer.js'; +import { globalData } from '../globalData.js'; + +export function renderMeasurementResults() { + const container = document.getElementById('measurement-data-container'); + container.innerHTML = ''; // Clear previous content + + const dccRoot = globalData.dcc?.['dcc:digitalCalibrationCertificate']; + if (!dccRoot) { + container.innerHTML = "<p>No Digital Calibration Certificate Found</p>"; + return; + } + + const measurements = dccRoot?.['dcc:measurementResults']; + if (!measurements || !measurements['dcc:measurementResult']) { + container.innerHTML = "<p>No Measurement Results Found</p>"; + return; + } + + const tabs = (Array.isArray(measurements['dcc:measurementResult']) ? + measurements['dcc:measurementResult'] : [measurements['dcc:measurementResult']] + ).map((result, index) => { + const resultContainer = document.createElement('div'); + + // 🔹 Measurement Methods + const methods = result?.['dcc:usedMethods']?.['dcc:usedMethod'] || []; + const methodsList = (Array.isArray(methods) ? methods : [methods]).map(method => ` + <p><strong>${method?.['dcc:name']?.['dcc:content']?._text || 'Unknown Method'}</strong>: + ${method?.['dcc:description']?.['dcc:content']?._text || 'No description'}</p> + `).join(''); + + // 🔹 Measurement Equipment + const equipments = result?.['dcc:measuringEquipments']?.['dcc:measuringEquipment'] || []; + const equipmentList = (Array.isArray(equipments) ? equipments : [equipments]).map(eq => ` + <p><strong>${eq?.['dcc:name']?.['dcc:content']?._text || 'Unknown Equipment'}</strong> + - ${eq?.['dcc:model']?._text || 'N/A'}</p> + `).join(''); + + // 🔹 Measurement Results + const results = result?.['dcc:results']?.['dcc:result'] || []; + const resultsList = (Array.isArray(results) ? results : [results]).map(res => ` + <h4>${res?.['dcc:name']?.['dcc:content']?._text || 'Unknown Result'}</h4> + <pre>${JSON.stringify(res['dcc:data'], null, 2)}</pre> + `).join(''); + + resultContainer.innerHTML = ` + <h3>Measurement Methods</h3>${methodsList} + <h3>Equipment Used</h3>${equipmentList} + <h3>Results</h3>${resultsList} + `; + + return { + title: `Measurement ${index + 1}`, + content: resultContainer + }; + }); + + container.appendChild(createTabs(tabs)); + + // 🔹 JSON DEBUGGING VIEW + container.appendChild(createTabs([{ title: "Raw JSON", content: new JSONTreeViewer(measurements).render() }])); +} diff --git a/dcc-viewer/src/xmlToJson.js b/dcc-viewer/src/xmlToJson.js index b308fc3f8eb43538a1d5ac89224abb556dfbc878..b25a854df9ee5d9a749770e23df7328add9fa7ab 100644 --- a/dcc-viewer/src/xmlToJson.js +++ b/dcc-viewer/src/xmlToJson.js @@ -1,5 +1,6 @@ -import { parseStringPromise } from 'xml2js'; +import { xml2json } from 'xml-js'; -export async function convertXMLToJSON(xmlString) { - return parseStringPromise(xmlString, { explicitArray: false, mergeAttrs: true }); -} \ No newline at end of file +export function convertXMLToJSON(xmlString) { + const jsonData = xml2json(xmlString, { compact: true, spaces: 2 }); + return JSON.parse(jsonData); +} diff --git a/project_snapshot.json b/project_snapshot.json new file mode 100644 index 0000000000000000000000000000000000000000..30998181d2d1cc2a0dec09cb09bf941d47e4439c --- /dev/null +++ b/project_snapshot.json @@ -0,0 +1,20 @@ +{ + "src/main.js": "import { convertXMLToJSON } from './xmlToJson.js';\nimport { globalData } from './globalData.js';\nimport { renderAdministrativeData } from './ui/adminRenderer.js';\nimport { renderMeasurementResults } from './ui/measurementRenderer.js';\n\nconst fileInput = document.getElementById('file-input');\n\nfileInput.addEventListener('change', async (event) => {\n const file = event.target.files?.[0];\n if (!file) return;\n\n const reader = new FileReader();\n reader.onload = async () => {\n const xmlString = reader.result;\n globalData.dcc = await convertXMLToJSON(xmlString); // Store DCC globally\n\n console.log(\"DCC Data Loaded:\", globalData.dcc);\n\n renderAdministrativeData(globalData.dcc.administrativeData);\n renderMeasurementResults(globalData.dcc.measurementResults);\n };\n reader.readAsText(file);\n});\n", + "src/xmlToJson.js": "import { xml2json } from 'xml-js';\n\nexport function convertXMLToJSON(xmlString) {\n const jsonData = xml2json(xmlString, { compact: true, spaces: 2 });\n return JSON.parse(jsonData);\n}\n", + "src/idRegistry.js": "export const idRegistry = {};", + "src/globalData.js": "export const globalData = {\n dcc: null // This will hold the parsed DCC JSON data\n};", + "src/globalOptions.js": "export const globalOptions = { preferredLanguage: 'en' };", + "src/viewerRegistry.js": "import { JSONTreeViewer } from './components/JSONTreeViewer.js';\n\nexport function getViewerForElement() {\n return JSONTreeViewer;\n}", + "src/utils.js": "export function getLocalizedText(elements) {\n if (!Array.isArray(elements)) return elements;\n return elements[0]._ || '';\n}", + "src/components/BaseViewer.js": "export class BaseViewer {\n constructor(sectionData) {\n this.sectionData = sectionData;\n }\n render() {\n throw new Error('render() must be implemented in subclasses');\n }\n}", + "src/components/JSONTreeViewer.js": "import { BaseViewer } from './BaseViewer.js';\n\nexport class JSONTreeViewer extends BaseViewer {\n render() {\n const container = document.createElement('pre');\n container.textContent = JSON.stringify(this.sectionData, null, 2);\n return container;\n }\n}", + "src/components/accordionComponent.js": "export function createAccordion(title, contentElement) {\n const container = document.createElement('div');\n container.classList.add('accordion');\n\n const header = document.createElement('button');\n header.textContent = title;\n header.classList.add('accordion-header');\n\n const content = document.createElement('div');\n content.classList.add('accordion-content');\n content.appendChild(contentElement);\n\n header.addEventListener('click', () => {\n content.classList.toggle('open');\n });\n\n container.appendChild(header);\n container.appendChild(content);\n return container;\n}\n", + "src/components/tabComponent.js": "export function createTabs(tabsData) {\n const container = document.createElement('div');\n container.classList.add('tabs-container');\n\n const tabs = document.createElement('div');\n tabs.classList.add('tabs');\n\n const contentContainer = document.createElement('div');\n contentContainer.classList.add('tab-content');\n\n tabsData.forEach((tab, index) => {\n const button = document.createElement('button');\n button.textContent = tab.title;\n button.addEventListener('click', () => {\n contentContainer.innerHTML = '';\n contentContainer.appendChild(tab.content);\n });\n\n tabs.appendChild(button);\n\n if (index === 0) {\n contentContainer.appendChild(tab.content);\n }\n });\n\n container.appendChild(tabs);\n container.appendChild(contentContainer);\n return container;\n}\n", + "src/ui/languageSelector.js": "import { globalOptions } from '../globalOptions.js';\n\nconst languageSelect = document.getElementById('language-select');\nlanguageSelect.addEventListener('change', (event) => {\n globalOptions.preferredLanguage = event.target.value;\n});", + "src/ui/themeSwitcher.js": "const themeToggle = document.getElementById('theme-toggle');\nthemeToggle.addEventListener('click', () => {\n document.body.classList.toggle('dark-mode');\n});", + "src/ui/adminRenderer.js": "import { createAccordion } from '../components/accordionComponent.js';\nimport { JSONTreeViewer } from './jsonTreeViewer.js';\n\nexport function renderAdministrativeData(adminData) {\n const container = document.getElementById('admin-data-container');\n container.innerHTML = ''; // Clear previous content\n\n if (!adminData) {\n container.innerHTML = \"<p>No Administrative Data Found</p>\";\n return;\n }\n\n const jsonViewer = new JSONTreeViewer(adminData);\n const accordion = createAccordion(\"Administrative Data\", jsonViewer.render());\n\n container.appendChild(accordion);\n}\n", + "src/ui/measurementRenderer.js": "import { createTabs } from '../components/tabComponent.js';\nimport { JSONTreeViewer } from './jsonTreeViewer.js';\n\nexport function renderMeasurementResults(measurements) {\n const container = document.getElementById('measurement-data-container');\n container.innerHTML = ''; // Clear previous content\n\n if (!measurements || !measurements.measurementResult) {\n container.innerHTML = \"<p>No Measurement Results Found</p>\";\n return;\n }\n\n const tabs = measurements.measurementResult.map((result, index) => ({\n title: `Result ${index + 1}`,\n content: new JSONTreeViewer(result).render()\n }));\n\n const tabsComponent = createTabs(tabs);\n container.appendChild(tabsComponent);\n}\n", + "src/ui/jsonTreeViewer.js": "export class JSONTreeViewer {\n constructor(data) {\n this.data = data;\n }\n\n render() {\n const container = document.createElement('pre');\n container.textContent = JSON.stringify(this.data, null, 2);\n return container;\n }\n}\n", + "public/index.html": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <title>DCC Viewer</title>\n <script type=\"module\" src=\"/src/main.js\"></script>\n <link rel=\"stylesheet\" href=\"/public/styles.css\">\n</head>\n<body>\n<h1>DCC Viewer</h1>\n\n<input type=\"file\" id=\"file-input\" accept=\".xml\">\n\n<div id=\"admin-data-container\"></div>\n<div id=\"measurement-data-container\"></div>\n</body>\n</html>\n", + "public/styles.css": ".accordion-header {\n background-color: #f0f0f0;\n border: none;\n padding: 10px;\n cursor: pointer;\n width: 100%;\n text-align: left;\n}\n\n.accordion-content {\n display: none;\n padding: 10px;\n}\n\n.accordion-content.open {\n display: block;\n}\n\n.tabs {\n display: flex;\n gap: 10px;\n}\n\n.tabs button {\n padding: 5px 10px;\n cursor: pointer;\n}\n\n.tab-content {\n border: 1px solid #ddd;\n padding: 10px;\n}\n" +} \ No newline at end of file diff --git a/project_snapshotter.py b/project_snapshotter.py new file mode 100644 index 0000000000000000000000000000000000000000..f8d52ce72019018270c90f2873ee6ebf389242c3 --- /dev/null +++ b/project_snapshotter.py @@ -0,0 +1,40 @@ +import os +import json + +# Define the root folder of your project +PROJECT_ROOT = "dcc-viewer" + +# File extensions to include +INCLUDE_EXTENSIONS = {".js", ".html", ".css"} + +# Folders to exclude +EXCLUDE_FOLDERS = {"node_modules", "dist", ".git", ".idea", ".vite"} + +def scan_project(directory): + project_data = {} + + for root, dirs, files in os.walk(directory): + # Remove excluded folders from traversal + dirs[:] = [d for d in dirs if d not in EXCLUDE_FOLDERS] + + for file in files: + if any(file.endswith(ext) for ext in INCLUDE_EXTENSIONS): + file_path = os.path.join(root, file) + relative_path = os.path.relpath(file_path, directory) + + try: + with open(file_path, "r", encoding="utf-8") as f: + project_data[relative_path] = f.read() + except Exception as e: + print(f"Error reading {file_path}: {e}") + + return project_data + +# Run the scan and save as JSON +if __name__ == "__main__": + project_json = scan_project(PROJECT_ROOT) + + with open("project_snapshot.json", "w", encoding="utf-8") as json_file: + json.dump(project_json, json_file, indent=4, ensure_ascii=False) + + print("✅ Project snapshot saved to project_snapshot.json")