Query panel: highlight the clicked row as active

Clicking a query results row highlighted the element in the 3D canvas
but gave no feedback in the list itself. Track the active row and
toggle an .active class, matching the existing storey-row pattern.

Closes ifcurl-cmm

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Bruno Postle 2026-06-08 07:36:48 +01:00
parent a3d4994c4f
commit 125423fcca
3 changed files with 9 additions and 1 deletions

View file

@ -69,7 +69,7 @@
{"id":"ifcurl-ei8","title":"Fix syncCameraUrl: convert WebGL coords to IFC world space","description":"syncCameraUrl in viewer.py currently records camera.position/direction/up directly from Three.js, which are in WebGL/Three.js coordinate space (Y-up, different scale/orientation than IFC). The ifc:// URL spec expects IFC world coordinates (Z-up, matching BCF viewpoint conventions). Need to find the IFC→Three.js transform that @thatopen/components applies when loading a model, then apply its inverse in syncCameraUrl before serialising the camera params. Repos cloned for reference: ~/src/engine_components and ~/src/engine_fragment.","status":"closed","priority":2,"issue_type":"bug","owner":"bruno@postle.net","created_at":"2026-04-23T05:53:06Z","created_by":"Bruno Postle","updated_at":"2026-04-23T06:14:36Z","closed_at":"2026-04-23T06:14:36Z","close_reason":"Split into atomic tasks: ifcurl-ldk, ifcurl-j2s, ifcurl-cmd","dependency_count":0,"dependent_count":0,"comment_count":0}
{"id":"ifcurl-i1s","title":"Test Phase 3b web viewer end-to-end","description":"After deploying the footer template (ifcurl-ach), test the full flow: open an .ifc file in Forgejo at localhost:3000, click 'View in 3D', verify the viewer loads the model. CDN versions (@thatopen/components 2.4.0, three 0.160.0, web-ifc 0.0.66) may need adjustment if the API has changed.","status":"closed","priority":2,"issue_type":"task","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-04-23T05:48:01Z","created_by":"Bruno Postle","updated_at":"2026-04-23T20:05:04Z","started_at":"2026-04-23T19:54:56Z","closed_at":"2026-04-23T20:05:04Z","close_reason":"Closed","dependencies":[{"issue_id":"ifcurl-i1s","depends_on_id":"ifcurl-49o","type":"blocks","created_at":"2026-04-23T07:14:12Z","created_by":"Bruno Postle","metadata":"{}"},{"issue_id":"ifcurl-i1s","depends_on_id":"ifcurl-4yu","type":"blocks","created_at":"2026-04-23T07:14:11Z","created_by":"Bruno Postle","metadata":"{}"},{"issue_id":"ifcurl-i1s","depends_on_id":"ifcurl-ach","type":"blocks","created_at":"2026-04-23T06:48:10Z","created_by":"Bruno Postle","metadata":"{}"},{"issue_id":"ifcurl-i1s","depends_on_id":"ifcurl-ahd","type":"blocks","created_at":"2026-04-23T07:02:54Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":4,"dependent_count":1,"comment_count":0}
{"id":"ifcurl-ach","title":"Deploy Phase 3b footer template to Forgejo","description":"The footer.tmpl file that injects a 'View in 3D' button on .ifc file pages has been written but not yet deployed. Deploy it to /etc/forgejo/templates/custom/footer.tmpl and verify the button appears when viewing an .ifc file on localhost:3000.","status":"closed","priority":2,"issue_type":"task","owner":"bruno@postle.net","created_at":"2026-04-23T05:47:53Z","created_by":"Bruno Postle","updated_at":"2026-04-23T06:14:35Z","closed_at":"2026-04-23T06:14:35Z","close_reason":"Split into atomic tasks: ifcurl-ohq, ifcurl-49o","dependencies":[{"issue_id":"ifcurl-ach","depends_on_id":"ifcurl-ahd","type":"blocks","created_at":"2026-04-23T07:02:40Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":1,"comment_count":0}
{"id":"ifcurl-cmm","title":"Query panel: clicking a row should highlight it in the list","description":"When a row in the query results panel is clicked, the corresponding element highlights in the 3D canvas correctly. However the clicked row itself gets no visual selection state in the panel list — there is no highlighted/active row indicator. Minor UI consistency issue: the panel gives no feedback about which row was last clicked.","status":"open","priority":3,"issue_type":"bug","owner":"bruno@postle.net","created_at":"2026-06-07T22:11:30Z","created_by":"Bruno Postle","updated_at":"2026-06-07T22:11:30Z","dependency_count":0,"dependent_count":0,"comment_count":0}
{"id":"ifcurl-cmm","title":"Query panel: clicking a row should highlight it in the list","description":"When a row in the query results panel is clicked, the corresponding element highlights in the 3D canvas correctly. However the clicked row itself gets no visual selection state in the panel list — there is no highlighted/active row indicator. Minor UI consistency issue: the panel gives no feedback about which row was last clicked.","status":"in_progress","priority":3,"issue_type":"bug","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-06-07T22:11:30Z","created_by":"Bruno Postle","updated_at":"2026-06-08T06:35:03Z","started_at":"2026-06-08T06:35:03Z","dependency_count":0,"dependent_count":0,"comment_count":0}
{"id":"ifcurl-pq6","title":"Document OpenCDE Foundation API and document picker in SPECIFICATION.md","description":"The OpenCDE Foundation API 1.1 OAuth2 proxy routes (foundation_api.py) and document picker select-documents flow (documents_api.py) are implemented but not described in SPECIFICATION.md or the CLAUDE.md browser test checklist. Update SPECIFICATION.md §9 or add a new section covering: the OAuth2 setup (registering Forgejo app, env vars IFCURL_OAUTH2_CLIENT_ID/SECRET), the three /foundation/1.1/oauth2/ routes and their request/response shapes, the POST /documents/1.0/select-documents flow and the picker UI. Add a browser test checklist item to CLAUDE.md covering the end-to-end select-documents flow.","status":"closed","priority":3,"issue_type":"task","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-06-07T11:21:26Z","created_by":"Bruno Postle","updated_at":"2026-06-07T14:52:56Z","started_at":"2026-06-07T14:19:39Z","closed_at":"2026-06-07T14:52:56Z","close_reason":"Closed","dependency_count":0,"dependent_count":0,"comment_count":0}
{"id":"ifcurl-4zf","title":"Document recently-closed features in README or SPECIFICATION","description":"Several features have been implemented and closed in recent beads but are not reflected in user-facing documentation. These include: OpenCDE Foundation API 1.1 OAuth2 proxy routes (ifcurl-bil), OpenCDE document picker select-documents flow (ifcurl-xfi, in progress), BCF export rewrite as pure client-side (7c25e06), ifc:// OS protocol handler ifcurl-open/ifcurl-register (d975658), PR/commit diff view, BCF round-trip import, query panel, click-to-inspect, metadata panel, and storey isolation. README and/or SPECIFICATION should be updated to reflect what is now implemented vs planned.","status":"closed","priority":3,"issue_type":"task","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-06-07T09:11:03Z","created_by":"Bruno Postle","updated_at":"2026-06-07T14:52:57Z","started_at":"2026-06-07T14:19:42Z","closed_at":"2026-06-07T14:52:57Z","close_reason":"Closed","dependency_count":0,"dependent_count":0,"comment_count":0}
{"id":"ifcurl-bsw","title":"Socket IPC: dispatch ifc:// URLs to already-running viewer instance","description":"When a viewer (bonsai or ifcviewer) is running, ifcurl-open should send the URL to the existing instance rather than launching a new process. Protocol: on startup the viewer opens a Unix socket at ~/.cache/ifcurl/\u003cviewer-name\u003e.sock. ifcurl-open tries the socket first; if it connects it sends the URL as a newline-terminated string and exits. If no socket exists or connection fails, falls back to launching fresh. Bonsai and ifcviewer each need to implement the socket listener.","status":"closed","priority":3,"issue_type":"feature","owner":"bruno@postle.net","created_at":"2026-06-05T14:43:06Z","created_by":"Bruno Postle","updated_at":"2026-06-07T07:34:25Z","closed_at":"2026-06-07T07:34:25Z","close_reason":"Descoped: ifcurl-open will always launch a new viewer instance. Socket IPC is complex, not idiomatic for Blender, and can be added later if there is demand. Instance reuse policy is left to the viewer application.","dependencies":[{"issue_id":"ifcurl-bsw","depends_on_id":"ifcurl-7db","type":"blocks","created_at":"2026-06-05T15:43:26Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0}

View file

@ -138,6 +138,8 @@
border-bottom: 1px solid rgba(255,255,255,0.05);
max-width: 280px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#query-table tbody tr:hover { background: rgba(255,255,255,0.07); }
#query-table tbody tr.active td { background: rgba(80,120,255,0.2); color: #a8c8ff; }
/* Element properties panel */
#props-panel {
position: fixed; bottom: 44px; right: 12px; z-index: 10;

View file

@ -758,6 +758,7 @@ async function applyQuery(srcUrl, queryPath) {
queryPanelTitle.textContent = queryPath;
queryValHeader.textContent = queryPath;
queryTbody.innerHTML = "";
let activeQueryRow = null;
for (const [guid, value] of entries) {
const tr = document.createElement("tr");
tr.style.cursor = "pointer";
@ -768,6 +769,11 @@ async function applyQuery(srcUrl, queryPath) {
tr.appendChild(tdGuid);
tr.appendChild(tdVal);
tr.addEventListener("click", async () => {
if (activeQueryRow !== tr) {
activeQueryRow?.classList.remove("active");
tr.classList.add("active");
activeQueryRow = tr;
}
if (!components || !loadedModel) return;
const localIds = (await loadedModel.getLocalIdsByGuids([guid])).filter(id => id !== null);
if (!localIds.length) return;