mirror of
https://github.com/brunopostle/ifcurl.git
synced 2026-07-12 10:18:14 +00:00
Remove /viewer and /proxy endpoints from service.py
Viewer is now a Forgejo static file; IFC bytes are fetched directly from Forgejo by the browser. The proxy is no longer needed. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
c2bbcc62c2
commit
9e0ef5b41f
2 changed files with 9 additions and 36 deletions
|
|
@ -1,16 +1,18 @@
|
||||||
|
{"id":"ifcurl-1sh","title":"viewer.html: place camera from ifc:// URL camera= param on load","description":"When viewer.html loads with a camera= param in the ifc:// URL (9 comma-separated floats: position, direction, up in IFC world coordinates), apply the IFC→Three.js coordinate transform (Y/Z swap, one negated) and set the Three.js camera position, direction and up vector accordingly. Depends on the syncCameraUrl fix (ifcurl-j2s) so the forward and inverse transforms are consistent.","status":"open","priority":2,"issue_type":"feature","owner":"bruno@postle.net","created_at":"2026-04-23T20:05:57Z","created_by":"Bruno Postle","updated_at":"2026-04-23T20:05:57Z","dependencies":[{"issue_id":"ifcurl-1sh","depends_on_id":"ifcurl-j2s","type":"blocks","created_at":"2026-04-23T21:06:08Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0}
|
||||||
|
{"id":"ifcurl-940","title":"viewer.html: URL input box and drag-and-drop target","description":"Add a text entry box and a drag-and-drop target to viewer.html so any ifc:// URL can be loaded without navigating from a Forgejo page. The input should accept a pasted ifc:// URL and immediately load it into the viewer. Drag-and-drop should accept a dropped ifc:// URL or a .ifc file URL. This makes the viewer usable as a standalone tool.","status":"open","priority":2,"issue_type":"feature","owner":"bruno@postle.net","created_at":"2026-04-23T20:05:43Z","created_by":"Bruno Postle","updated_at":"2026-04-23T20:05:43Z","dependency_count":0,"dependent_count":0,"comment_count":0}
|
||||||
{"id":"ifcurl-cmd","title":"Apply forward IFC→Three.js transform when setting camera from URL params","description":"When the viewer page loads with a camera= param in the ifc:// URL, the 9 floats are in IFC world coordinates. Apply the IFC→Three.js transform to convert them before passing them to the Three.js camera / camera-controls. This is the forward direction of the same transform used in the inverse task.","status":"open","priority":2,"issue_type":"bug","owner":"bruno@postle.net","created_at":"2026-04-23T06:12:38Z","created_by":"Bruno Postle","updated_at":"2026-04-23T06:12:38Z","dependencies":[{"issue_id":"ifcurl-cmd","depends_on_id":"ifcurl-ldk","type":"blocks","created_at":"2026-04-23T07:14:10Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0}
|
{"id":"ifcurl-cmd","title":"Apply forward IFC→Three.js transform when setting camera from URL params","description":"When the viewer page loads with a camera= param in the ifc:// URL, the 9 floats are in IFC world coordinates. Apply the IFC→Three.js transform to convert them before passing them to the Three.js camera / camera-controls. This is the forward direction of the same transform used in the inverse task.","status":"open","priority":2,"issue_type":"bug","owner":"bruno@postle.net","created_at":"2026-04-23T06:12:38Z","created_by":"Bruno Postle","updated_at":"2026-04-23T06:12:38Z","dependencies":[{"issue_id":"ifcurl-cmd","depends_on_id":"ifcurl-ldk","type":"blocks","created_at":"2026-04-23T07:14:10Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0}
|
||||||
{"id":"ifcurl-j2s","title":"Apply inverse IFC↔Three.js transform in syncCameraUrl","description":"Using the transform found in the research task, apply its inverse to camera.position, the direction vector, and camera.up before serialising them as the ifc:// camera param in syncCameraUrl. The result should be in IFC world coordinates (Z-up, matching BCF viewpoint conventions) not Three.js scene space.","status":"open","priority":2,"issue_type":"bug","owner":"bruno@postle.net","created_at":"2026-04-23T06:12:37Z","created_by":"Bruno Postle","updated_at":"2026-04-23T06:12:37Z","dependencies":[{"issue_id":"ifcurl-j2s","depends_on_id":"ifcurl-ldk","type":"blocks","created_at":"2026-04-23T07:14:09Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0}
|
{"id":"ifcurl-j2s","title":"Apply inverse IFC↔Three.js transform in syncCameraUrl","description":"Using the transform found in the research task, apply its inverse to camera.position, the direction vector, and camera.up before serialising them as the ifc:// camera param in syncCameraUrl. The result should be in IFC world coordinates (Z-up, matching BCF viewpoint conventions) not Three.js scene space.","status":"open","priority":2,"issue_type":"bug","owner":"bruno@postle.net","created_at":"2026-04-23T06:12:37Z","created_by":"Bruno Postle","updated_at":"2026-04-23T06:12:37Z","dependencies":[{"issue_id":"ifcurl-j2s","depends_on_id":"ifcurl-ldk","type":"blocks","created_at":"2026-04-23T07:14:09Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":1,"comment_count":0}
|
||||||
{"id":"ifcurl-ldk","title":"Find IFC↔Three.js coordinate transform in @thatopen/components source","description":"Grep ~/src/engine_components and ~/src/engine_fragment for the matrix or transform applied when an IFC model is loaded into Three.js scene space. IFC uses Z-up; Three.js uses Y-up. @thatopen/components almost certainly applies a 90° X-axis rotation (and possibly a scale) when constructing the Three.Group from IFC geometry. Record the exact transform so the inverse can be applied in syncCameraUrl.","status":"in_progress","priority":2,"issue_type":"task","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-04-23T06:12:36Z","created_by":"Bruno Postle","updated_at":"2026-04-23T06:19:35Z","started_at":"2026-04-23T06:19:35Z","dependency_count":0,"dependent_count":2,"comment_count":0}
|
{"id":"ifcurl-ldk","title":"Find IFC↔Three.js coordinate transform in @thatopen/components source","description":"Grep ~/src/engine_components and ~/src/engine_fragment for the matrix or transform applied when an IFC model is loaded into Three.js scene space. IFC uses Z-up; Three.js uses Y-up. @thatopen/components almost certainly applies a 90° X-axis rotation (and possibly a scale) when constructing the Three.Group from IFC geometry. Record the exact transform so the inverse can be applied in syncCameraUrl.","status":"closed","priority":2,"issue_type":"task","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-04-23T06:12:36Z","created_by":"Bruno Postle","updated_at":"2026-04-23T20:05:29Z","started_at":"2026-04-23T06:19:35Z","closed_at":"2026-04-23T20:05:29Z","close_reason":"Transform identified: IFC→Three.js is a Y/Z swap with one axis negated (Z-up to Y-up). Unblocks j2s and cmd.","dependency_count":0,"dependent_count":2,"comment_count":0}
|
||||||
{"id":"ifcurl-49o","title":"Deploy footer.tmpl to Forgejo custom templates directory","description":"Copy forgejo/templates/custom/footer.tmpl from the repo to /etc/forgejo/templates/custom/footer.tmpl on the Forgejo server. No Forgejo restart needed — custom templates are loaded dynamically. Verify the View in 3D button appears on an .ifc file page.","status":"closed","priority":2,"issue_type":"task","owner":"bruno@postle.net","created_at":"2026-04-23T06:12:22Z","created_by":"Bruno Postle","updated_at":"2026-04-23T19:47:16Z","closed_at":"2026-04-23T19:47:16Z","close_reason":"Closed","dependencies":[{"issue_id":"ifcurl-49o","depends_on_id":"ifcurl-ohq","type":"blocks","created_at":"2026-04-23T07:14:08Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":1,"comment_count":0}
|
{"id":"ifcurl-49o","title":"Deploy footer.tmpl to Forgejo custom templates directory","description":"Copy forgejo/templates/custom/footer.tmpl from the repo to /etc/forgejo/templates/custom/footer.tmpl on the Forgejo server. No Forgejo restart needed — custom templates are loaded dynamically. Verify the View in 3D button appears on an .ifc file page.","status":"closed","priority":2,"issue_type":"task","owner":"bruno@postle.net","created_at":"2026-04-23T06:12:22Z","created_by":"Bruno Postle","updated_at":"2026-04-23T19:47:16Z","closed_at":"2026-04-23T19:47:16Z","close_reason":"Closed","dependencies":[{"issue_id":"ifcurl-49o","depends_on_id":"ifcurl-ohq","type":"blocks","created_at":"2026-04-23T07:14:08Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":1,"comment_count":0}
|
||||||
{"id":"ifcurl-ohq","title":"Update footer.tmpl: point viewer button to Forgejo static file URL","description":"Change the VIEWER_BASE URL in forgejo/templates/custom/footer.tmpl from http://localhost:8000/viewer to the Forgejo static file URL determined by the research task (ifcurl-5t3). The button href should become something like /assets/viewer.html?url=ifc://... rather than the ifcurl service URL.","status":"closed","priority":2,"issue_type":"task","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-04-23T06:12:21Z","created_by":"Bruno Postle","updated_at":"2026-04-23T19:47:15Z","started_at":"2026-04-23T18:48:37Z","closed_at":"2026-04-23T19:47:15Z","close_reason":"Closed","dependencies":[{"issue_id":"ifcurl-ohq","depends_on_id":"ifcurl-5t3","type":"blocks","created_at":"2026-04-23T07:14:07Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":1,"comment_count":0}
|
{"id":"ifcurl-ohq","title":"Update footer.tmpl: point viewer button to Forgejo static file URL","description":"Change the VIEWER_BASE URL in forgejo/templates/custom/footer.tmpl from http://localhost:8000/viewer to the Forgejo static file URL determined by the research task (ifcurl-5t3). The button href should become something like /assets/viewer.html?url=ifc://... rather than the ifcurl service URL.","status":"closed","priority":2,"issue_type":"task","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-04-23T06:12:21Z","created_by":"Bruno Postle","updated_at":"2026-04-23T19:47:15Z","started_at":"2026-04-23T18:48:37Z","closed_at":"2026-04-23T19:47:15Z","close_reason":"Closed","dependencies":[{"issue_id":"ifcurl-ohq","depends_on_id":"ifcurl-5t3","type":"blocks","created_at":"2026-04-23T07:14:07Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":1,"comment_count":0}
|
||||||
{"id":"ifcurl-4yu","title":"Deploy viewer.html to Forgejo server","description":"Copy the viewer static file from the repo to the correct location on the Forgejo server so it is served at its expected URL. Document the deployment step in the repo (e.g. Makefile target or install notes).","status":"closed","priority":2,"issue_type":"task","owner":"bruno@postle.net","created_at":"2026-04-23T06:12:11Z","created_by":"Bruno Postle","updated_at":"2026-04-23T19:47:16Z","closed_at":"2026-04-23T19:47:16Z","close_reason":"Closed","dependencies":[{"issue_id":"ifcurl-4yu","depends_on_id":"ifcurl-55f","type":"blocks","created_at":"2026-04-23T07:14:05Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":1,"comment_count":0}
|
{"id":"ifcurl-4yu","title":"Deploy viewer.html to Forgejo server","description":"Copy the viewer static file from the repo to the correct location on the Forgejo server so it is served at its expected URL. Document the deployment step in the repo (e.g. Makefile target or install notes).","status":"closed","priority":2,"issue_type":"task","owner":"bruno@postle.net","created_at":"2026-04-23T06:12:11Z","created_by":"Bruno Postle","updated_at":"2026-04-23T19:47:16Z","closed_at":"2026-04-23T19:47:16Z","close_reason":"Closed","dependencies":[{"issue_id":"ifcurl-4yu","depends_on_id":"ifcurl-55f","type":"blocks","created_at":"2026-04-23T07:14:05Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":1,"comment_count":0}
|
||||||
{"id":"ifcurl-cuh","title":"Remove /viewer and /proxy endpoints from service.py","description":"Once the viewer HTML is served as a Forgejo static file and fetches IFC bytes directly from Forgejo (using the browser session for auth), the /viewer and /proxy endpoints in ifcurl/service.py are defunct. Remove them and clean up the associated VIEWER_HTML constant in viewer.py.","status":"open","priority":2,"issue_type":"task","owner":"bruno@postle.net","created_at":"2026-04-23T06:12:10Z","created_by":"Bruno Postle","updated_at":"2026-04-23T06:12:10Z","dependencies":[{"issue_id":"ifcurl-cuh","depends_on_id":"ifcurl-55f","type":"blocks","created_at":"2026-04-23T07:14:06Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0}
|
{"id":"ifcurl-cuh","title":"Remove /viewer and /proxy endpoints from service.py","description":"Once the viewer HTML is served as a Forgejo static file and fetches IFC bytes directly from Forgejo (using the browser session for auth), the /viewer and /proxy endpoints in ifcurl/service.py are defunct. Remove them and clean up the associated VIEWER_HTML constant in viewer.py.","status":"closed","priority":2,"issue_type":"task","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-04-23T06:12:10Z","created_by":"Bruno Postle","updated_at":"2026-04-23T20:05:04Z","started_at":"2026-04-23T19:54:44Z","closed_at":"2026-04-23T20:05:04Z","close_reason":"Closed","dependencies":[{"issue_id":"ifcurl-cuh","depends_on_id":"ifcurl-55f","type":"blocks","created_at":"2026-04-23T07:14:06Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0}
|
||||||
{"id":"ifcurl-55f","title":"Move viewer HTML to Forgejo custom static file","description":"Extract the VIEWER_HTML constant from ifcurl/viewer.py and write it as a static HTML file in the repo under the Forgejo custom static directory (path determined by the research task). The file should be a standalone page — no dependency on the ifcurl service for serving.","status":"closed","priority":2,"issue_type":"task","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-04-23T06:12:09Z","created_by":"Bruno Postle","updated_at":"2026-04-23T19:47:15Z","started_at":"2026-04-23T18:48:26Z","closed_at":"2026-04-23T19:47:15Z","close_reason":"Closed","dependencies":[{"issue_id":"ifcurl-55f","depends_on_id":"ifcurl-5t3","type":"blocks","created_at":"2026-04-23T07:14:03Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":2,"comment_count":0}
|
{"id":"ifcurl-55f","title":"Move viewer HTML to Forgejo custom static file","description":"Extract the VIEWER_HTML constant from ifcurl/viewer.py and write it as a static HTML file in the repo under the Forgejo custom static directory (path determined by the research task). The file should be a standalone page — no dependency on the ifcurl service for serving.","status":"closed","priority":2,"issue_type":"task","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-04-23T06:12:09Z","created_by":"Bruno Postle","updated_at":"2026-04-23T19:47:15Z","started_at":"2026-04-23T18:48:26Z","closed_at":"2026-04-23T19:47:15Z","close_reason":"Closed","dependencies":[{"issue_id":"ifcurl-55f","depends_on_id":"ifcurl-5t3","type":"blocks","created_at":"2026-04-23T07:14:03Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":2,"comment_count":0}
|
||||||
{"id":"ifcurl-5t3","title":"Research Forgejo custom static file serving","description":"Determine where Forgejo looks for custom static files and what URL they get served at. Check the Forgejo docs and source for the custom/ static directory convention. The result feeds into the viewer HTML deployment and the footer.tmpl URL update.","notes":"Forgejo serves custom static files from \u003cCustomPath\u003e/public/assets/ at URL /assets/*. CustomPath is /var/lib/forgejo/custom on this system. No auth required. Any file type. Place viewer.html at /var/lib/forgejo/custom/public/assets/viewer.html → served at /assets/viewer.html.","status":"closed","priority":2,"issue_type":"task","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-04-23T06:11:58Z","created_by":"Bruno Postle","updated_at":"2026-04-23T06:50:05Z","started_at":"2026-04-23T06:19:46Z","closed_at":"2026-04-23T06:50:05Z","close_reason":"Closed","dependency_count":0,"dependent_count":2,"comment_count":0}
|
{"id":"ifcurl-5t3","title":"Research Forgejo custom static file serving","description":"Determine where Forgejo looks for custom static files and what URL they get served at. Check the Forgejo docs and source for the custom/ static directory convention. The result feeds into the viewer HTML deployment and the footer.tmpl URL update.","notes":"Forgejo serves custom static files from \u003cCustomPath\u003e/public/assets/ at URL /assets/*. CustomPath is /var/lib/forgejo/custom on this system. No auth required. Any file type. Place viewer.html at /var/lib/forgejo/custom/public/assets/viewer.html → served at /assets/viewer.html.","status":"closed","priority":2,"issue_type":"task","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-04-23T06:11:58Z","created_by":"Bruno Postle","updated_at":"2026-04-23T06:50:05Z","started_at":"2026-04-23T06:19:46Z","closed_at":"2026-04-23T06:50:05Z","close_reason":"Closed","dependency_count":0,"dependent_count":2,"comment_count":0}
|
||||||
{"id":"ifcurl-7x1","title":"Forgejo goldmark extension: handle bare ifc:// URLs in markdown","description":"The goldmark extension in the patched Forgejo binary (modules/markup/markdown/ifc_url.go) currently only detects ifc:// URLs when written in explicit markdown link form [Title](ifc://...). It should also auto-link bare ifc:// URLs pasted inline in markdown text, the same way goldmark auto-links http:// URLs. Extend the extension (or add a separate autolink pass) to detect raw ifc:// URL tokens and wrap them in the preview embed.","status":"closed","priority":2,"issue_type":"bug","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-04-23T05:58:02Z","created_by":"Bruno Postle","updated_at":"2026-04-23T06:50:06Z","started_at":"2026-04-23T06:19:47Z","closed_at":"2026-04-23T06:50:06Z","close_reason":"Closed","dependency_count":0,"dependent_count":0,"comment_count":0}
|
{"id":"ifcurl-7x1","title":"Forgejo goldmark extension: handle bare ifc:// URLs in markdown","description":"The goldmark extension in the patched Forgejo binary (modules/markup/markdown/ifc_url.go) currently only detects ifc:// URLs when written in explicit markdown link form [Title](ifc://...). It should also auto-link bare ifc:// URLs pasted inline in markdown text, the same way goldmark auto-links http:// URLs. Extend the extension (or add a separate autolink pass) to detect raw ifc:// URL tokens and wrap them in the preview embed.","status":"closed","priority":2,"issue_type":"bug","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-04-23T05:58:02Z","created_by":"Bruno Postle","updated_at":"2026-04-23T06:50:06Z","started_at":"2026-04-23T06:19:47Z","closed_at":"2026-04-23T06:50:06Z","close_reason":"Closed","dependency_count":0,"dependent_count":0,"comment_count":0}
|
||||||
{"id":"ifcurl-ahd","title":"Serve viewer HTML as Forgejo static files instead of ifcurl /viewer endpoint","description":"Currently the viewer is served from the ifcurl preview service at GET /viewer, and IFC bytes are fetched via GET /proxy to work around CORS. This has two problems: it pipes all IFC data through the ifcurl service (bandwidth/latency), and it bypasses the browser's existing Forgejo authentication (cookies/session) so private repos won't work. Better architecture: deploy the viewer HTML as a Forgejo custom static file (e.g. /assets/viewer.html or via a custom template). The viewer JS can then fetch IFC bytes directly from Forgejo's raw file URL using the browser's existing session, so auth is inherited automatically and no proxy is needed. The /viewer and /proxy endpoints in ifcurl/service.py can be removed once this is working.","status":"closed","priority":2,"issue_type":"feature","owner":"bruno@postle.net","created_at":"2026-04-23T05:56:15Z","created_by":"Bruno Postle","updated_at":"2026-04-23T06:14:34Z","closed_at":"2026-04-23T06:14:34Z","close_reason":"Split into atomic tasks: ifcurl-5t3, ifcurl-55f, ifcurl-cuh, ifcurl-4yu","dependency_count":0,"dependent_count":2,"comment_count":0}
|
{"id":"ifcurl-ahd","title":"Serve viewer HTML as Forgejo static files instead of ifcurl /viewer endpoint","description":"Currently the viewer is served from the ifcurl preview service at GET /viewer, and IFC bytes are fetched via GET /proxy to work around CORS. This has two problems: it pipes all IFC data through the ifcurl service (bandwidth/latency), and it bypasses the browser's existing Forgejo authentication (cookies/session) so private repos won't work. Better architecture: deploy the viewer HTML as a Forgejo custom static file (e.g. /assets/viewer.html or via a custom template). The viewer JS can then fetch IFC bytes directly from Forgejo's raw file URL using the browser's existing session, so auth is inherited automatically and no proxy is needed. The /viewer and /proxy endpoints in ifcurl/service.py can be removed once this is working.","status":"closed","priority":2,"issue_type":"feature","owner":"bruno@postle.net","created_at":"2026-04-23T05:56:15Z","created_by":"Bruno Postle","updated_at":"2026-04-23T06:14:34Z","closed_at":"2026-04-23T06:14:34Z","close_reason":"Split into atomic tasks: ifcurl-5t3, ifcurl-55f, ifcurl-cuh, ifcurl-4yu","dependency_count":0,"dependent_count":2,"comment_count":0}
|
||||||
{"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-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":"open","priority":2,"issue_type":"task","owner":"bruno@postle.net","created_at":"2026-04-23T05:48:01Z","created_by":"Bruno Postle","updated_at":"2026-04-23T05:48:01Z","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-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-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-bqt","title":"Phase 4: Bonsai IFCDOCUMENTREFERENCE federation via ifc://","description":"When opening a model via ifc://, resolve IFCDOCUMENTREFERENCE locations using the repo and ref from the root file's URL as context. Resolve ifc:// locations in linked model references recursively. Requires the Phase 4 protocol handler (ifcurl-0oj).","status":"deferred","priority":3,"issue_type":"feature","owner":"bruno@postle.net","created_at":"2026-04-23T05:48:56Z","created_by":"Bruno Postle","updated_at":"2026-04-23T06:15:11Z","defer_until":"2026-12-01T00:00:00Z","dependencies":[{"issue_id":"ifcurl-bqt","depends_on_id":"ifcurl-0oj","type":"blocks","created_at":"2026-04-23T06:49:02Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":1,"comment_count":0}
|
{"id":"ifcurl-bqt","title":"Phase 4: Bonsai IFCDOCUMENTREFERENCE federation via ifc://","description":"When opening a model via ifc://, resolve IFCDOCUMENTREFERENCE locations using the repo and ref from the root file's URL as context. Resolve ifc:// locations in linked model references recursively. Requires the Phase 4 protocol handler (ifcurl-0oj).","status":"deferred","priority":3,"issue_type":"feature","owner":"bruno@postle.net","created_at":"2026-04-23T05:48:56Z","created_by":"Bruno Postle","updated_at":"2026-04-23T06:15:11Z","defer_until":"2026-12-01T00:00:00Z","dependencies":[{"issue_id":"ifcurl-bqt","depends_on_id":"ifcurl-0oj","type":"blocks","created_at":"2026-04-23T06:49:02Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":1,"comment_count":0}
|
||||||
{"id":"ifcurl-lcr","title":"Phase 4: Bonsai 'Copy view URL' button","description":"Add a button to Bonsai that generates an ifc:// URL from the current state: git remote/ref/file path, active selection as IfcOpenShell selector, current camera as camera+fov or scale params in IFC world coordinates, active clipping planes as clip params, current visibility mode. Default to commit hash ref; secondary option for @heads/ ref.","status":"deferred","priority":3,"issue_type":"feature","owner":"bruno@postle.net","created_at":"2026-04-23T05:48:55Z","created_by":"Bruno Postle","updated_at":"2026-04-23T06:15:10Z","defer_until":"2026-12-01T00:00:00Z","dependencies":[{"issue_id":"ifcurl-lcr","depends_on_id":"ifcurl-0oj","type":"blocks","created_at":"2026-04-23T06:49:01Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0}
|
{"id":"ifcurl-lcr","title":"Phase 4: Bonsai 'Copy view URL' button","description":"Add a button to Bonsai that generates an ifc:// URL from the current state: git remote/ref/file path, active selection as IfcOpenShell selector, current camera as camera+fov or scale params in IFC world coordinates, active clipping planes as clip params, current visibility mode. Default to commit hash ref; secondary option for @heads/ ref.","status":"deferred","priority":3,"issue_type":"feature","owner":"bruno@postle.net","created_at":"2026-04-23T05:48:55Z","created_by":"Bruno Postle","updated_at":"2026-04-23T06:15:10Z","defer_until":"2026-12-01T00:00:00Z","dependencies":[{"issue_id":"ifcurl-lcr","depends_on_id":"ifcurl-0oj","type":"blocks","created_at":"2026-04-23T06:49:01Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0}
|
||||||
|
|
|
||||||
|
|
@ -40,22 +40,21 @@ import os
|
||||||
import tempfile
|
import tempfile
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
import urllib.error
|
|
||||||
import urllib.request
|
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
import ifcopenshell.util.selector
|
import ifcopenshell.util.selector
|
||||||
from fastapi import FastAPI, HTTPException
|
from fastapi import FastAPI, HTTPException
|
||||||
from fastapi.responses import HTMLResponse, Response
|
from fastapi.responses import Response
|
||||||
from platformdirs import user_cache_dir
|
from platformdirs import user_cache_dir
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
|
||||||
from ifcurl import render as render_mod
|
from ifcurl import render as render_mod
|
||||||
from ifcurl.auth import get_token_for_host
|
from ifcurl.auth import get_token_for_host
|
||||||
from ifcurl.git import fetch_ifc
|
from ifcurl.git import fetch_ifc
|
||||||
from ifcurl.viewer import VIEWER_HTML
|
|
||||||
from ifcurl.url import IfcUrl
|
from ifcurl.url import IfcUrl
|
||||||
|
|
||||||
app = FastAPI(
|
app = FastAPI(
|
||||||
|
|
@ -221,34 +220,6 @@ class PreviewRequest(BaseModel):
|
||||||
# Endpoints
|
# Endpoints
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
@app.get("/viewer")
|
|
||||||
def viewer(url: str = "") -> HTMLResponse:
|
|
||||||
"""Serve the self-contained web IFC viewer page.
|
|
||||||
|
|
||||||
The ``url`` query parameter should be an ifc:// URL. The page loads
|
|
||||||
``@thatopen/components`` from CDN and fetches the IFC file through
|
|
||||||
``/proxy`` to avoid cross-origin restrictions.
|
|
||||||
"""
|
|
||||||
return HTMLResponse(content=VIEWER_HTML)
|
|
||||||
|
|
||||||
|
|
||||||
@app.get("/proxy")
|
|
||||||
def proxy(url: str) -> Response:
|
|
||||||
"""Proxy a raw IFC file URL to the browser, avoiding CORS restrictions.
|
|
||||||
|
|
||||||
Only intended for fetching IFC bytes from the co-located Forgejo instance.
|
|
||||||
No IFC processing is performed — bytes are forwarded as-is.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
with urllib.request.urlopen(url, timeout=30) as resp: # noqa: S310
|
|
||||||
data = resp.read()
|
|
||||||
content_type = resp.headers.get_content_type() or "application/octet-stream"
|
|
||||||
except urllib.error.HTTPError as exc:
|
|
||||||
raise HTTPException(status_code=exc.code, detail=str(exc.reason)) from exc
|
|
||||||
except Exception as exc:
|
|
||||||
raise HTTPException(status_code=502, detail=str(exc)) from exc
|
|
||||||
return Response(content=data, media_type=content_type)
|
|
||||||
|
|
||||||
|
|
||||||
@app.get("/preview")
|
@app.get("/preview")
|
||||||
def preview_get(url: str) -> Response:
|
def preview_get(url: str) -> Response:
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue