@thatopen/services 0.3.2 → 0.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/built-in/index.d.ts +9 -0
- package/dist/cli.js +2 -2
- package/docs/ai-quickstart.md +55 -16
- package/docs/builtin/paths.json +74 -74
- package/docs/cli/login.md +2 -2
- package/docs/cli/paths.json +1 -1
- package/docs/cli/serve.md +3 -3
- package/package.json +1 -1
- package/src/built-in/index.ts +9 -0
- package/src/cli/templates/app/src/main.ts +10 -34
package/dist/built-in/index.d.ts
CHANGED
|
@@ -484,6 +484,15 @@ declare class _CDEManager extends OBC.Component implements OBC.Transitionable<CD
|
|
|
484
484
|
private _saveConversionIndex;
|
|
485
485
|
private _loadConversionIndex;
|
|
486
486
|
private _resumePendingConversions;
|
|
487
|
+
/** Cached id of the IfcFragmenter component, resolved by name for this session. */
|
|
488
|
+
private _ifcFragmenterId?;
|
|
489
|
+
/**
|
|
490
|
+
* Resolves the platform IFC→FRAG cloud component's id by its stable name
|
|
491
|
+
* (`IfcFragmenter`) within the current project, so it works across dev/prod
|
|
492
|
+
* without a hardcoded id. Cached for the session. Returns `undefined` if no
|
|
493
|
+
* such component is available in the project.
|
|
494
|
+
*/
|
|
495
|
+
private _resolveIfcFragmenterId;
|
|
487
496
|
private _triggerIfcConversions;
|
|
488
497
|
uploadFiles(files: File[], folderId?: string | null, options?: {
|
|
489
498
|
forceNew?: boolean;
|
package/dist/cli.js
CHANGED
|
@@ -8028,8 +8028,8 @@ async function configureBetaNpmrc(dir) {
|
|
|
8028
8028
|
}
|
|
8029
8029
|
const loginCommand = new Command2("login").description("Authenticate with the ThatOpen platform").option("--token <token>", "Access token from the dashboard").option(
|
|
8030
8030
|
"--api-url <url>",
|
|
8031
|
-
"API URL",
|
|
8032
|
-
"https://
|
|
8031
|
+
"API URL (defaults to production; pass https://dev.platform.thatopen.com for the dev environment)",
|
|
8032
|
+
"https://platform.thatopen.com"
|
|
8033
8033
|
).option(
|
|
8034
8034
|
"--local",
|
|
8035
8035
|
"Save credentials to local .thatopen file instead of global config"
|
package/docs/ai-quickstart.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
# That Open Platform — AI Quick Start (zero to a running app)
|
|
1
|
+
# That Open Platform — AI Quick Start (zero to a running app or cloud component)
|
|
2
2
|
|
|
3
|
-
You are an AI assistant. A user pointed you at this URL so you can scaffold and run
|
|
4
|
-
|
|
3
|
+
You are an AI assistant. A user pointed you at this URL so you can scaffold and run something
|
|
4
|
+
on the [That Open Platform](https://platform.thatopen.com) from scratch, using
|
|
5
5
|
`@thatopen/services` (the `thatopen` CLI + client library). Follow the steps below in order.
|
|
6
6
|
|
|
7
7
|
> The only secret you need is a **platform API token** — **not** an npm token. The CLI
|
|
@@ -9,6 +9,22 @@ You are an AI assistant. A user pointed you at this URL so you can scaffold and
|
|
|
9
9
|
|
|
10
10
|
---
|
|
11
11
|
|
|
12
|
+
## First — what are you building? (ask if the user hasn't said)
|
|
13
|
+
|
|
14
|
+
There are two kinds of project. **If the user hasn't told you which they want, ASK them
|
|
15
|
+
before scaffolding** — explain it in plain terms and let them pick:
|
|
16
|
+
|
|
17
|
+
- **App** — something people *open and click around in*, running in the platform's browser
|
|
18
|
+
UI: a 3D BIM viewer, a dashboard, a form, a custom tool. Choose this when the goal is a
|
|
19
|
+
visual interface. Template: `app`.
|
|
20
|
+
- **Cloud component** — *server-side logic* with no UI of its own, running in the platform's
|
|
21
|
+
cloud and triggered by an app or an automation to do work on the project's data — e.g.
|
|
22
|
+
convert a file (IFC→fragments, point cloud→tiles), generate a report, run a calculation.
|
|
23
|
+
Choose this when the goal is processing/automation, not a screen. Template: `cloud-component`.
|
|
24
|
+
|
|
25
|
+
Steps 0–2 are identical for both; they diverge only at `create` (step 3) and how you run them
|
|
26
|
+
(step 4). This guide marks **[app]** / **[component]** where they differ.
|
|
27
|
+
|
|
12
28
|
## 0. Prerequisites (check, don't assume)
|
|
13
29
|
|
|
14
30
|
- **Node.js ≥ 18** and **npm** — verify with `node -v`.
|
|
@@ -24,6 +40,9 @@ npm install -g @thatopen/services@latest
|
|
|
24
40
|
|
|
25
41
|
## 2. Log in (do this BEFORE creating the project)
|
|
26
42
|
|
|
43
|
+
Get the token from the platform dashboard — **https://platform.thatopen.com/dashboard/data**
|
|
44
|
+
→ **API Tokens** → create → copy. Ask the user to paste it, then run:
|
|
45
|
+
|
|
27
46
|
```bash
|
|
28
47
|
thatopen login --token <platform-token>
|
|
29
48
|
```
|
|
@@ -33,39 +52,57 @@ first: the next step's install pulls the private `@thatopen-platform/*-beta` pac
|
|
|
33
52
|
`create` uses your logged-in token to write an authenticated `.npmrc` so that install can
|
|
34
53
|
resolve them. No npm account or manual npm token is involved.
|
|
35
54
|
|
|
36
|
-
## 3. Scaffold a beta
|
|
55
|
+
## 3. Scaffold a beta project
|
|
37
56
|
|
|
57
|
+
**[app]**
|
|
38
58
|
```bash
|
|
39
59
|
thatopen create my-app --beta
|
|
40
60
|
cd my-app
|
|
41
61
|
```
|
|
42
62
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
63
|
+
**[component]**
|
|
64
|
+
```bash
|
|
65
|
+
thatopen create my-component -t cloud-component --beta
|
|
66
|
+
cd my-component
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
`--beta` is required for now (the templates use engine APIs that currently live only in the
|
|
70
|
+
beta libraries; public support lands with the October release). `create` configures private
|
|
71
|
+
beta access from your platform token and runs `npm install` for you. The **app** scaffold is
|
|
72
|
+
a complete working viewer; the **cloud-component** scaffold is a `main()` entry point plus a
|
|
73
|
+
`declarations.json` (the parameters the component accepts) — read its `README.md`, which
|
|
74
|
+
explains the exactly-four globals the cloud engine injects (do NOT import them) and how to
|
|
75
|
+
read/write the project's data.
|
|
46
76
|
|
|
47
77
|
## 4. Run it
|
|
48
78
|
|
|
79
|
+
**[app]**
|
|
49
80
|
```bash
|
|
50
81
|
npm run dev
|
|
51
82
|
```
|
|
83
|
+
Serves the app and opens it inside the platform. **You now have a complete, working viewer** —
|
|
84
|
+
model loading, spatial tree, properties, measurement, sectioning, and more.
|
|
52
85
|
|
|
53
|
-
|
|
54
|
-
|
|
86
|
+
**[component]**
|
|
87
|
+
```bash
|
|
88
|
+
npm run run # executes the component locally against the platform (no browser)
|
|
89
|
+
```
|
|
90
|
+
Runs `main()` in a local emulation of the cloud engine so you can iterate before publishing.
|
|
55
91
|
|
|
56
92
|
## 5. Then build — read the in-project agent guide
|
|
57
93
|
|
|
58
|
-
The scaffold is
|
|
94
|
+
The scaffold is real, working code — a complete viewer **[app]** or a runnable `main()`
|
|
95
|
+
**[component]** — not a blank page. **Before changing anything**, open and follow:
|
|
59
96
|
|
|
60
97
|
```
|
|
61
98
|
node_modules/@thatopen/services/resources/AGENTS.md
|
|
62
99
|
```
|
|
63
100
|
|
|
64
|
-
(The scaffolded project's own `AGENTS.md` points here too.) It is the canonical guide
|
|
65
|
-
indexes every platform built-in, the client API, the CLI, and the
|
|
66
|
-
Load those indexes before writing code.
|
|
67
|
-
(`BUI`)** — consult the design system
|
|
68
|
-
it; don't rebuild
|
|
101
|
+
(The scaffolded project's own `AGENTS.md` points here too.) It is the canonical guide for
|
|
102
|
+
**both** project types: it indexes every platform built-in, the client API, the CLI, and the
|
|
103
|
+
engine / UI example sets. Load those indexes before writing code. For an **app**, **all UI
|
|
104
|
+
must be built with Lit + `@thatopen/ui` (`BUI`)** — consult the design system first. Run the
|
|
105
|
+
scaffold first, then extend it; don't rebuild from scratch.
|
|
69
106
|
|
|
70
107
|
## 6. Publish (when ready)
|
|
71
108
|
|
|
@@ -73,7 +110,9 @@ it; don't rebuild a viewer from scratch.
|
|
|
73
110
|
npm run publish
|
|
74
111
|
```
|
|
75
112
|
|
|
76
|
-
Builds
|
|
113
|
+
Builds, zips (`dist/bundle.zip`), and uploads a new version to the platform — for an **app**
|
|
114
|
+
or a **component** (a component also ships its `declarations.json`). Re-run it any time to
|
|
115
|
+
push a new version.
|
|
77
116
|
|
|
78
117
|
---
|
|
79
118
|
|
package/docs/builtin/paths.json
CHANGED
|
@@ -1,74 +1,74 @@
|
|
|
1
|
-
[
|
|
2
|
-
{
|
|
3
|
-
"path": "src/built-in/CDEManager/example.ts",
|
|
4
|
-
"description": "CDEManager — CDEManager is the central state machine for a Common Data Environment. It holds files, folders, metadata schemas, viewer groups, and user permissions, and exposes a typed state machine that all file operations — selecting, editing, uploading, viewing — route through. It has no DOM or Three.js dependencies and can run in Node, a browser, or a server-side worker wherever `@thatopen/components` is available."
|
|
5
|
-
},
|
|
6
|
-
{
|
|
7
|
-
"path": "src/built-in/CDEManager/examples/FileEditing/example.ts",
|
|
8
|
-
"description": "Bulk file editing — stage, preview, revert, and commit — A project manager preparing a deliverable handoff needs to update discipline tags across fifteen IFC files after a scope change, rename each to match the new naming convention, and archive three superseded models — all before anything is sent to the backend. Doing the changes one file at a time risks leaving the file list in a half-updated state if the session is interrupted, and there is no way to review exactly what will change before committing."
|
|
9
|
-
},
|
|
10
|
-
{
|
|
11
|
-
"path": "src/built-in/CDEManager/examples/FileMoves/example.ts",
|
|
12
|
-
"description": "Drag-and-drop file and folder moves — A coordinator restructures the project after a scope change: structural files move from the root into a dedicated discipline folder, a MEP sub-folder needs to be promoted to the top level, and a few documents need to come back to root to appear in the general view. Drag-and-drop is the natural gesture for all of this, but each drag session has intermediate stages — the file is \"in the air\", hovering over a candidate target — and every panel watching the file table should see the right state without coordinating directly with the drag component."
|
|
13
|
-
},
|
|
14
|
-
{
|
|
15
|
-
"path": "src/built-in/CDEManager/examples/FileOperations/example.ts",
|
|
16
|
-
"description": "File operations — inline edit, rename, view, download, archive — BIM coordinators reviewing a model drop repeat the same small actions throughout their session: correcting a discipline tag that changed after a scope revision, renaming a file to match the agreed convention, opening it alongside the structural model to check for clashes, handing it off to a sub-consultant, or removing a superseded version from the live set. If every panel in the platform handles these separately, two panels looking at the same file at the same time can show contradictory states — one says \"uploading\", another still shows the old name."
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
"path": "src/built-in/CDEManager/examples/FileTransfers/example.ts",
|
|
20
|
-
"description": "File uploads, versioning, and the download cache — A site coordinator drops a batch of files onto the CDE every Monday after the weekend review: some are entirely new models, some are revised versions of files already in the project, and sometimes the metadata group they upload into should be stamped automatically onto the new files. If the platform makes the coordinator sort this out manually, it slows the handoff and introduces naming errors. And if an upload fails halfway through a batch, the file table should land in a safe state rather than freeze at a loading spinner."
|
|
21
|
-
},
|
|
22
|
-
{
|
|
23
|
-
"path": "src/built-in/CDEManager/examples/FolderManagement/example.ts",
|
|
24
|
-
"description": "Folder management — create, rename, archive, and commit — A project reaches the construction phase and the coordination team needs to restructure the folder hierarchy: add a \"Facades\" discipline folder, rename \"Structural\" to its official abbreviation, and archive two superseded folders that have been merged. Doing these one at a time through separate API calls means the folder tree flickers between invalid states as each change lands — a freshly created folder appears before its sibling is renamed, and the archived folders briefly disappear before the new one is visible."
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
"path": "src/built-in/CDEManager/examples/MetadataSchema/example.ts",
|
|
28
|
-
"description": "Metadata schema — define, stage, and publish field definitions — Every project has its own vocabulary for describing files: discipline codes, revision phases, area zones, review statuses. A metadata schema defines which fields exist, what values they accept, and whether they are mandatory. Without a structured schema, each user invents their own labels and the file list becomes impossible to filter or report on consistently."
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
"path": "src/built-in/CDEManager/examples/MetadataViews/example.ts",
|
|
32
|
-
"description": "Metadata views — organize fields into named table layouts — A structural engineer and an MEP coordinator look at the same file list but care about completely different metadata. Showing every field to everyone produces a wide table that is hard to navigate. Metadata views let each role define which fields appear in which order — saving the layout so the table opens correctly next time without requiring a manual setup every session."
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
"path": "src/built-in/CDEManager/examples/ProjectConfig/example.ts",
|
|
36
|
-
"description": "Project configuration — read, write, and reload persistent data — A CDE application needs to store two kinds of configuration: project-wide settings that all team members share (the metadata schema, custom naming rules) and personal settings that belong to one user (which columns are visible, which metadata views are pinned). Both live inside the project's file storage under a reserved system folder, so they travel with the project and don't rely on a separate configuration service."
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
"path": "src/built-in/UIManager/src/app/example.ts",
|
|
40
|
-
"description": "top-app — Front-end developers building BIM web apps need to coordinate several async initialization steps before the UI can be shown — loading the engine, preparing fragment workers, registering loaders — and users need visible feedback on what is happening during that wait, rather than a blank screen."
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
"path": "src/built-in/UIManager/src/app/examples/AppState/example.ts",
|
|
44
|
-
"description": "Shared reactive state with AppState — Developers building interactive BIM panels often need sibling components — a filter selector and a results table, for example — to stay in sync without a shared parent. Lifting state to a common ancestor and threading it down as props works for shallow trees but becomes unwieldy as the component tree grows."
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
"path": "src/built-in/UIManager/src/app/examples/Banner/example.ts",
|
|
48
|
-
"description": "Persistent banners with top:banner — Some application states need a persistent, visible indicator that stays on screen until the state is explicitly cleared — an archived-files mode, a read-only permission warning, a degraded-connectivity notice. A toast auto-dismisses after a few seconds, which is wrong for these cases. A modal blocks interaction entirely, which is too heavy."
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
"path": "src/built-in/UIManager/src/app/examples/Contexts/example.ts",
|
|
52
|
-
"description": "Consuming platform contexts in child components — Developers building custom BIM panels need access to the 3D engine, the platform API, and the current project's metadata — but threading these objects down through props across multiple component layers forces every intermediate element to know about data it doesn't use, making trees brittle and hard to refactor."
|
|
53
|
-
},
|
|
54
|
-
{
|
|
55
|
-
"path": "src/built-in/UIManager/src/app/examples/FileDrop/example.ts",
|
|
56
|
-
"description": "File drag-and-drop with top:files-dropped — Desktop BIM workflows often rely on dragging files straight from the OS file manager onto the browser window — but wiring a document-level dragenter, dragover, dragleave, and drop handler that correctly tracks nested enter/leave counts, shows a visual overlay, and forwards the files to the right component is tedious boilerplate to repeat for every app."
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
"path": "src/built-in/UIManager/src/app/examples/FloatingLayout/example.ts",
|
|
60
|
-
"description": "Floating layout — Developers building BIM coordination tools often want the 3D model to fill the entire window while control panels float above it — but standard grid layouts give every area equal standing, shrinking the viewer into one cell and leaving visible seams between it and the panels."
|
|
61
|
-
},
|
|
62
|
-
{
|
|
63
|
-
"path": "src/built-in/UIManager/src/app/examples/Modal/example.ts",
|
|
64
|
-
"description": "Confirmation modals with top:modal — Destructive or irreversible actions — deleting records, overwriting files, leaving unsaved changes — should ask the user to confirm before proceeding. Opening a custom dialog element from a deeply nested component means threading a reference to a controller up through every layer of the tree."
|
|
65
|
-
},
|
|
66
|
-
{
|
|
67
|
-
"path": "src/built-in/UIManager/src/app/examples/Notifications/example.ts",
|
|
68
|
-
"description": "Toasts and cross-component notifications — Developers building BIM processing UIs need to surface status updates, errors, and async feedback to users from different points in the component tree — but reaching back to the app root to trigger a notification from a deeply nested component requires threading a reference through every layer in between."
|
|
69
|
-
},
|
|
70
|
-
{
|
|
71
|
-
"path": "src/built-in/UIManager/src/app/examples/Sidebar/example.ts",
|
|
72
|
-
"description": "Sidebar navigation — Product teams building BIM apps often need multiple distinct views — a 3D model viewer, a data browser, a settings screen — but wiring a custom nav bar and managing view transitions from scratch adds complexity before any real feature work begins."
|
|
73
|
-
}
|
|
74
|
-
]
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"path": "src/built-in/CDEManager/example.ts",
|
|
4
|
+
"description": "CDEManager — CDEManager is the central state machine for a Common Data Environment. It holds files, folders, metadata schemas, viewer groups, and user permissions, and exposes a typed state machine that all file operations — selecting, editing, uploading, viewing — route through. It has no DOM or Three.js dependencies and can run in Node, a browser, or a server-side worker wherever `@thatopen/components` is available."
|
|
5
|
+
},
|
|
6
|
+
{
|
|
7
|
+
"path": "src/built-in/CDEManager/examples/FileEditing/example.ts",
|
|
8
|
+
"description": "Bulk file editing — stage, preview, revert, and commit — A project manager preparing a deliverable handoff needs to update discipline tags across fifteen IFC files after a scope change, rename each to match the new naming convention, and archive three superseded models — all before anything is sent to the backend. Doing the changes one file at a time risks leaving the file list in a half-updated state if the session is interrupted, and there is no way to review exactly what will change before committing."
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"path": "src/built-in/CDEManager/examples/FileMoves/example.ts",
|
|
12
|
+
"description": "Drag-and-drop file and folder moves — A coordinator restructures the project after a scope change: structural files move from the root into a dedicated discipline folder, a MEP sub-folder needs to be promoted to the top level, and a few documents need to come back to root to appear in the general view. Drag-and-drop is the natural gesture for all of this, but each drag session has intermediate stages — the file is \"in the air\", hovering over a candidate target — and every panel watching the file table should see the right state without coordinating directly with the drag component."
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"path": "src/built-in/CDEManager/examples/FileOperations/example.ts",
|
|
16
|
+
"description": "File operations — inline edit, rename, view, download, archive — BIM coordinators reviewing a model drop repeat the same small actions throughout their session: correcting a discipline tag that changed after a scope revision, renaming a file to match the agreed convention, opening it alongside the structural model to check for clashes, handing it off to a sub-consultant, or removing a superseded version from the live set. If every panel in the platform handles these separately, two panels looking at the same file at the same time can show contradictory states — one says \"uploading\", another still shows the old name."
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"path": "src/built-in/CDEManager/examples/FileTransfers/example.ts",
|
|
20
|
+
"description": "File uploads, versioning, and the download cache — A site coordinator drops a batch of files onto the CDE every Monday after the weekend review: some are entirely new models, some are revised versions of files already in the project, and sometimes the metadata group they upload into should be stamped automatically onto the new files. If the platform makes the coordinator sort this out manually, it slows the handoff and introduces naming errors. And if an upload fails halfway through a batch, the file table should land in a safe state rather than freeze at a loading spinner."
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"path": "src/built-in/CDEManager/examples/FolderManagement/example.ts",
|
|
24
|
+
"description": "Folder management — create, rename, archive, and commit — A project reaches the construction phase and the coordination team needs to restructure the folder hierarchy: add a \"Facades\" discipline folder, rename \"Structural\" to its official abbreviation, and archive two superseded folders that have been merged. Doing these one at a time through separate API calls means the folder tree flickers between invalid states as each change lands — a freshly created folder appears before its sibling is renamed, and the archived folders briefly disappear before the new one is visible."
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"path": "src/built-in/CDEManager/examples/MetadataSchema/example.ts",
|
|
28
|
+
"description": "Metadata schema — define, stage, and publish field definitions — Every project has its own vocabulary for describing files: discipline codes, revision phases, area zones, review statuses. A metadata schema defines which fields exist, what values they accept, and whether they are mandatory. Without a structured schema, each user invents their own labels and the file list becomes impossible to filter or report on consistently."
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"path": "src/built-in/CDEManager/examples/MetadataViews/example.ts",
|
|
32
|
+
"description": "Metadata views — organize fields into named table layouts — A structural engineer and an MEP coordinator look at the same file list but care about completely different metadata. Showing every field to everyone produces a wide table that is hard to navigate. Metadata views let each role define which fields appear in which order — saving the layout so the table opens correctly next time without requiring a manual setup every session."
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"path": "src/built-in/CDEManager/examples/ProjectConfig/example.ts",
|
|
36
|
+
"description": "Project configuration — read, write, and reload persistent data — A CDE application needs to store two kinds of configuration: project-wide settings that all team members share (the metadata schema, custom naming rules) and personal settings that belong to one user (which columns are visible, which metadata views are pinned). Both live inside the project's file storage under a reserved system folder, so they travel with the project and don't rely on a separate configuration service."
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"path": "src/built-in/UIManager/src/app/example.ts",
|
|
40
|
+
"description": "top-app — Front-end developers building BIM web apps need to coordinate several async initialization steps before the UI can be shown — loading the engine, preparing fragment workers, registering loaders — and users need visible feedback on what is happening during that wait, rather than a blank screen."
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"path": "src/built-in/UIManager/src/app/examples/AppState/example.ts",
|
|
44
|
+
"description": "Shared reactive state with AppState — Developers building interactive BIM panels often need sibling components — a filter selector and a results table, for example — to stay in sync without a shared parent. Lifting state to a common ancestor and threading it down as props works for shallow trees but becomes unwieldy as the component tree grows."
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"path": "src/built-in/UIManager/src/app/examples/Banner/example.ts",
|
|
48
|
+
"description": "Persistent banners with top:banner — Some application states need a persistent, visible indicator that stays on screen until the state is explicitly cleared — an archived-files mode, a read-only permission warning, a degraded-connectivity notice. A toast auto-dismisses after a few seconds, which is wrong for these cases. A modal blocks interaction entirely, which is too heavy."
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"path": "src/built-in/UIManager/src/app/examples/Contexts/example.ts",
|
|
52
|
+
"description": "Consuming platform contexts in child components — Developers building custom BIM panels need access to the 3D engine, the platform API, and the current project's metadata — but threading these objects down through props across multiple component layers forces every intermediate element to know about data it doesn't use, making trees brittle and hard to refactor."
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"path": "src/built-in/UIManager/src/app/examples/FileDrop/example.ts",
|
|
56
|
+
"description": "File drag-and-drop with top:files-dropped — Desktop BIM workflows often rely on dragging files straight from the OS file manager onto the browser window — but wiring a document-level dragenter, dragover, dragleave, and drop handler that correctly tracks nested enter/leave counts, shows a visual overlay, and forwards the files to the right component is tedious boilerplate to repeat for every app."
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"path": "src/built-in/UIManager/src/app/examples/FloatingLayout/example.ts",
|
|
60
|
+
"description": "Floating layout — Developers building BIM coordination tools often want the 3D model to fill the entire window while control panels float above it — but standard grid layouts give every area equal standing, shrinking the viewer into one cell and leaving visible seams between it and the panels."
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"path": "src/built-in/UIManager/src/app/examples/Modal/example.ts",
|
|
64
|
+
"description": "Confirmation modals with top:modal — Destructive or irreversible actions — deleting records, overwriting files, leaving unsaved changes — should ask the user to confirm before proceeding. Opening a custom dialog element from a deeply nested component means threading a reference to a controller up through every layer of the tree."
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"path": "src/built-in/UIManager/src/app/examples/Notifications/example.ts",
|
|
68
|
+
"description": "Toasts and cross-component notifications — Developers building BIM processing UIs need to surface status updates, errors, and async feedback to users from different points in the component tree — but reaching back to the app root to trigger a notification from a deeply nested component requires threading a reference through every layer in between."
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"path": "src/built-in/UIManager/src/app/examples/Sidebar/example.ts",
|
|
72
|
+
"description": "Sidebar navigation — Product teams building BIM apps often need multiple distinct views — a 3D model viewer, a data browser, a settings screen — but wiring a custom nav bar and managing view transitions from scratch adds complexity before any real feature work begins."
|
|
73
|
+
}
|
|
74
|
+
]
|
package/docs/cli/login.md
CHANGED
|
@@ -7,7 +7,7 @@ description: "Authenticate with the ThatOpen platform by validating an access to
|
|
|
7
7
|
Validates an access token against the platform API and saves the credentials. Run this once globally before using any other command, or per-project with `--local`.
|
|
8
8
|
|
|
9
9
|
To get a token:
|
|
10
|
-
1. Go to [https://
|
|
10
|
+
1. Go to [https://platform.thatopen.com](https://platform.thatopen.com)
|
|
11
11
|
2. In the header, click **Data**
|
|
12
12
|
3. Find the **Tokens** card and create a new token
|
|
13
13
|
4. Enable the permissions: **Apps**, **Components**, and **Storage**
|
|
@@ -21,7 +21,7 @@ thatopen login --token <token> [flags]
|
|
|
21
21
|
**Flags:**
|
|
22
22
|
|
|
23
23
|
- `--token <token>` — Access token from the dashboard. Required.
|
|
24
|
-
- `--api-url <url>` — Platform API URL. Default: `https://dev.platform.thatopen.com
|
|
24
|
+
- `--api-url <url>` — Platform API URL. Default: `https://platform.thatopen.com` (production). Pass `https://dev.platform.thatopen.com` to target the dev environment.
|
|
25
25
|
- `--local` — Save credentials to `.thatopen` in the current directory instead of the global config. Use this inside a project to override the global token for that project only.
|
|
26
26
|
|
|
27
27
|
**Examples:**
|
package/docs/cli/paths.json
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
},
|
|
22
22
|
{
|
|
23
23
|
"path": "docs/cli/serve.md",
|
|
24
|
-
"description": "Start a local dev server for a browser app. Uses esbuild in watch mode and serves the IIFE bundle on port 4000 with SSE live reload. To connect: open the project on
|
|
24
|
+
"description": "Start a local dev server for a browser app. Uses esbuild in watch mode and serves the IIFE bundle on port 4000 with SSE live reload. To connect: open the project on platform.thatopen.com, click the Local App icon, then Get Started."
|
|
25
25
|
},
|
|
26
26
|
{
|
|
27
27
|
"path": "docs/cli/swap.md",
|
package/docs/cli/serve.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: "Start a local dev server for a browser app. Uses esbuild in watch mode and serves the IIFE bundle on port 4000 with SSE live reload. To connect: open the project on
|
|
2
|
+
description: "Start a local dev server for a browser app. Uses esbuild in watch mode and serves the IIFE bundle on port 4000 with SSE live reload. To connect: open the project on platform.thatopen.com, click the Local App icon, then Get Started."
|
|
3
3
|
---
|
|
4
4
|
|
|
5
5
|
## thatopen serve
|
|
@@ -31,7 +31,7 @@ thatopen serve --port 4321
|
|
|
31
31
|
|
|
32
32
|
**Connecting the platform to your local server:**
|
|
33
33
|
|
|
34
|
-
1. Go to [https://
|
|
34
|
+
1. Go to [https://platform.thatopen.com](https://platform.thatopen.com) and open a project (create one first if needed).
|
|
35
35
|
2. In the top right corner, click the **Local App** icon.
|
|
36
36
|
3. Click **Get Started**.
|
|
37
37
|
|
|
@@ -39,5 +39,5 @@ The platform loads the bundle from port 4000 and renders the app inside the proj
|
|
|
39
39
|
|
|
40
40
|
The resulting URL follows this pattern:
|
|
41
41
|
```
|
|
42
|
-
https://
|
|
42
|
+
https://platform.thatopen.com/dashboard/projects/{projectId}/apps/local-app
|
|
43
43
|
```
|
package/package.json
CHANGED
package/src/built-in/index.ts
CHANGED
|
@@ -488,6 +488,15 @@ declare class _CDEManager extends OBC.Component implements OBC.Transitionable<CD
|
|
|
488
488
|
private _saveConversionIndex;
|
|
489
489
|
private _loadConversionIndex;
|
|
490
490
|
private _resumePendingConversions;
|
|
491
|
+
/** Cached id of the IfcFragmenter component, resolved by name for this session. */
|
|
492
|
+
private _ifcFragmenterId?;
|
|
493
|
+
/**
|
|
494
|
+
* Resolves the platform IFC→FRAG cloud component's id by its stable name
|
|
495
|
+
* (`IfcFragmenter`) within the current project, so it works across dev/prod
|
|
496
|
+
* without a hardcoded id. Cached for the session. Returns `undefined` if no
|
|
497
|
+
* such component is available in the project.
|
|
498
|
+
*/
|
|
499
|
+
private _resolveIfcFragmenterId;
|
|
491
500
|
private _triggerIfcConversions;
|
|
492
501
|
uploadFiles(files: File[], folderId?: string | null, options?: {
|
|
493
502
|
forceNew?: boolean;
|
|
@@ -45,6 +45,14 @@ async function main() {
|
|
|
45
45
|
// visibility/inspect toolbar (see below), so the platform default would just
|
|
46
46
|
// duplicate it.
|
|
47
47
|
const viewerEl = document.createElement("top-viewer");
|
|
48
|
+
// Frame the viewport to match the side panels (BUI bim-panel host = 1px border
|
|
49
|
+
// + 0.75rem radius). top-viewer's host is already overflow:hidden, so the
|
|
50
|
+
// radius clips the canvas corners; border-box keeps the 1px inside the grid
|
|
51
|
+
// area. Done here (not in top-viewer) so the CDE's top-file-viewer, which draws
|
|
52
|
+
// its own frame, never double-borders.
|
|
53
|
+
viewerEl.style.border = "1px solid var(--bim-ui_bg-contrast-20)";
|
|
54
|
+
viewerEl.style.borderRadius = "0.75rem";
|
|
55
|
+
viewerEl.style.boxSizing = "border-box";
|
|
48
56
|
|
|
49
57
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
50
58
|
const app = document.createElement("top-app") as any;
|
|
@@ -169,8 +177,8 @@ async function main() {
|
|
|
169
177
|
// Navigation gizmo is now baked into <top-viewer> (setupViewerTools), so the
|
|
170
178
|
// app no longer mounts it. (Cascade: the rest of the overlay tools follow.)
|
|
171
179
|
|
|
172
|
-
//
|
|
173
|
-
|
|
180
|
+
// No auto-load: the viewer opens empty. Users add models from the Assets
|
|
181
|
+
// (files) panel — top-models-list loads the .frag they pick into the world.
|
|
174
182
|
}
|
|
175
183
|
|
|
176
184
|
/** Resolves with the first world once it exists (top-viewer creates it async). */
|
|
@@ -188,36 +196,4 @@ function firstWorld(worlds: any): Promise<any> {
|
|
|
188
196
|
});
|
|
189
197
|
}
|
|
190
198
|
|
|
191
|
-
|
|
192
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
193
|
-
async function autoLoadFirstModel(components: OBC.Components, client: any) {
|
|
194
|
-
const fragments = components.get(OBC.FragmentsManager);
|
|
195
|
-
const projectId: string | undefined = client?.context?.projectId;
|
|
196
|
-
if (!projectId) {
|
|
197
|
-
console.warn("[a2] no projectId — skipping auto-load");
|
|
198
|
-
return;
|
|
199
|
-
}
|
|
200
|
-
try {
|
|
201
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
202
|
-
const items = (await client.listFiles({ projectId })) as any[];
|
|
203
|
-
const frags = items.filter((it) =>
|
|
204
|
-
(it.name ?? "").toLowerCase().endsWith(".frag"),
|
|
205
|
-
);
|
|
206
|
-
const frag =
|
|
207
|
-
frags.find((it) => (it.name ?? "").toLowerCase().includes("bloxhub")) ??
|
|
208
|
-
frags[0];
|
|
209
|
-
if (!frag) {
|
|
210
|
-
console.warn("[a2] no .frag in project to auto-load");
|
|
211
|
-
return;
|
|
212
|
-
}
|
|
213
|
-
const resp = await client.downloadFile(String(frag._id));
|
|
214
|
-
const buffer = await resp.arrayBuffer();
|
|
215
|
-
await fragments.core.load(buffer, { modelId: String(frag._id) });
|
|
216
|
-
await fragments.core.update(true);
|
|
217
|
-
console.log("[a2] auto-loaded model:", frag.name);
|
|
218
|
-
} catch (error) {
|
|
219
|
-
console.warn("[a2] auto-load failed", error);
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
199
|
main().catch(console.error);
|