From 12ae63d3328d3e22ac73ec51103a16e556989200 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20P?= Date: Wed, 8 Apr 2026 11:39:57 +0200 Subject: [PATCH] Draft ontology menu --- js/ontology.js | 27 +++++++++++++++++++++++ js/ui.js | 52 ++++++++++++++++++++++++++++++++++---------- scenes/ssgp/index.js | 6 +---- 3 files changed, 69 insertions(+), 16 deletions(-) diff --git a/js/ontology.js b/js/ontology.js index 596c594..4ea1884 100644 --- a/js/ontology.js +++ b/js/ontology.js @@ -2,6 +2,33 @@ * @module Ontology */ +/** + * @todo Temporarily returns domains and ontology labels only + * Traverse an ontology from its JSON description + * @param {String} jsonPath The path (URI) of the ontology JSON file + * @returns {Object} + */ +export async function traverseOntology(jsonPath) { + const ontology = await loadOntology(jsonPath); + const domains = []; + + for (const k of Object.keys(ontology)) { + if (k === 'domains') { + for (const domainKey of Object.keys(ontology[k])) { + domains.push({ + label: domainKey, + child: ontology[k][domainKey][0].label, + }); + } + } + } + + return { + ontology: ontology.ontology, + domains + }; +} + /** * Load an ontology from its JSON description * @param {String} jsonPath The path (URI) of the ontology JSON file diff --git a/js/ui.js b/js/ui.js index 03295fa..67d915b 100644 --- a/js/ui.js +++ b/js/ui.js @@ -1,6 +1,7 @@ import AppState from "./state.js"; import { changeLightDirection, toggleAmbientOcclusion } from "./utils/environment.js"; import { resetClipping, addClippingPlane } from "./utils/clipping.js"; +import { traverseOntology } from "./ontology.js"; /** * @module UI @@ -17,7 +18,7 @@ const contentMenuTabs = ` @@ -26,7 +27,7 @@ const contentMenuTabs = `
-
+
`; @@ -219,11 +220,12 @@ function createLightSlider(direction, label, range, step) { /** * Right-side main menu panel * @param {String} triggerId - The menu button id + * @param {String} ontologyJsonPath */ -function toggleContentMenu(triggerId) { +function toggleContentMenu(triggerId, ontologyJsonPath) { const btn = document.querySelector(`#${triggerId}`); - btn.addEventListener('click', () => { + btn.addEventListener('click', async () => { ATON.UI.setSidePanelRight(); ATON.UI.showSidePanel({header: 'Menu'}); // Append tabs, then tab panes @@ -231,11 +233,12 @@ function toggleContentMenu(triggerId) { ATON.UI.elSidePanel.appendChild(tabs.querySelector('#content-tabs')); ATON.UI.elSidePanel.appendChild(tabs.querySelector('.tab-content')); buildLayersMenu(AppState.normalizedNodes, ATON.UI.elSidePanel.querySelector('#layer')); + buildOntologyMenu(await traverseOntology(ontologyJsonPath), ATON.UI.elSidePanel.querySelector('#content')); }); } /** * @todo Don't rebuild it every time the side panel is shown... - * @param {Array} nodes The scenes nodes (IDs and status) + * @param {Array} nodes The normalized scene nodes (IDs and status) * @param {HTMLElement} sidePanel ATON's side panel element */ function buildLayersMenu(nodes, sidePanel) { @@ -253,13 +256,13 @@ function buildLayersMenu(nodes, sidePanel) { const label = document.createElement('label'); label.className = "form-check-label"; - label.textContent = node.label; + label.textContent = node.id; menuItem.appendChild(label); sidePanel.appendChild(menuItem); // Will this ever work?? - menuItem.addEventListener('change', event => toggleNode(node.label, event.target.checked)); + menuItem.addEventListener('change', event => toggleNode(node.id, event.target.checked)); } /** @@ -269,15 +272,42 @@ function buildLayersMenu(nodes, sidePanel) { */ const toggleNode = (id, status) => { ATON.getSceneNode(id).toggle(status); - AppState.normalizedNodes.find(n => n.label === id).active = status; + AppState.normalizedNodes.find(n => n.id === id).active = status; } } /** - * Initialize required components for scene UI + * @see traverseOntology + * @param {Object} ontology The traversed ontology object (temp) + * @param {HTMLElement} sidePanel ATON's side panel element */ -export function initUI() { +function buildOntologyMenu(ontology, sidePanel) { + const list = document.createElement('ul'); + list.className = 'list-group'; + const mainNode = document.createElement('li'); + mainNode.className = 'list-group-item'; + mainNode.textContent = ontology.ontology; + + const domainList = document.createElement('ul'); + domainList.className = 'list-group'; + + for(let domain of ontology.domains) { + const domainItem = document.createElement('li'); + domainItem.textContent = domain.label; + domainItem.className = 'list-group-item'; + domainList.appendChild(domainItem); + } + + mainNode.appendChild(domainList); + list.appendChild(mainNode); + sidePanel.appendChild(list); +} +/** + * Initialize required components for scene UI + * @param {String} ontologyJsonPath + */ +export async function initUI(ontologyJsonPath) { toggleSettingsPanel('settings'); - toggleContentMenu('menu'); + toggleContentMenu('menu', ontologyJsonPath); toggleClipperBar('#clipper', '#clipper-bar'); } \ No newline at end of file diff --git a/scenes/ssgp/index.js b/scenes/ssgp/index.js index 3c453ee..3033fa1 100644 --- a/scenes/ssgp/index.js +++ b/scenes/ssgp/index.js @@ -3,14 +3,10 @@ import { config } from "../../config.js"; import AppState from "../../js/state.js"; import { normalizeNodes } from "../../js/utils/nodeUtils.js"; import { initUI } from "../../js/ui.js"; -import { loadOntology } from "../../js/ontology.js"; AppState.currentScene = 'ssgp'; const marker = config.markers.find(m => m.id === 'ssgp'); AppState.normalizedNodes = normalizeNodes(marker.nodes); openScene(marker, AppState.normalizedNodes); -initUI(); - -// DEBUG -console.debug(await loadOntology('ontology.json')); +initUI(location.pathname + '/ontology.json');