mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 02:14:01 +00:00
docs: require Vue views, Pinia stores and the kit for new UI
CONTRIBUTING gains a Building UI section: new UX elements are Vue components rendering a Pinia store their owner publishes to, portable owners stay framework-free behind a publish option, controls come from src/ui/kit first, controllers don't bind the DOM by hand (Teleport where a view renders elsewhere; body classes, focus, same-task measured positions and painted surfaces stay imperative), text goes through t()/tn() with msg() for stored English, and tests mount components. The README and the architecture summary drop the stale vanilla-JS claim, the UI ownership doc points to the guide, and the migration doc's UiPanel note names v-panel-state as what draws a panel's collapse.
This commit is contained in:
1 parent
fd4b69ff52
commit
19ca67a6e5
4 files changed
+69
-7
No files matched your search
+59
-2
@@ -115,7 +115,7 @@ The highest-leverage places to jump in:
|
||||
|
||||
## Architecture in one minute
|
||||
|
||||
- **No framework.** Vanilla JS + [CesiumJS](https://cesium.com/platform/cesiumjs/) + [Vite](https://vitejs.dev/).
|
||||
- **Vue 3 + Pinia for the interface,** [CesiumJS](https://cesium.com/platform/cesiumjs/) for the globe and [Vite](https://vitejs.dev/) to build. See [Building UI](#building-ui).
|
||||
- **Assembly lives in `src/app/`; standalone defaults live in `src/standalone/`.** UI controllers live in `src/ui/`, layer factories in `src/layers/`, portable sources in `src/sources/`, and application operations in `src/services/`. Existing `src/data/<layer>.js` entries retain compatibility; new code belongs with its focused owner.
|
||||
- Sources acquire records; renderers own Cesium resources. Import `gods-eye-view/layers/<family>/source` when only a source factory is needed. Common voice controls consume the session interface; protocol adapters own connection details.
|
||||
- **Secrets stay server-side.** Anything needing a private key goes through a local proxy under `server/providers/`. The browser only ever sees the Google Maps key (which you restrict) and ephemeral tokens.
|
||||
@@ -126,9 +126,66 @@ The highest-leverage places to jump in:
|
||||
- ES modules, **2-space indent, single quotes, semicolons.**
|
||||
- JSDoc on exported/public functions.
|
||||
- Match the surrounding code — comment density, naming, and idiom.
|
||||
- User-visible text goes through `t()`, `tn()` or `msg()`, or a `data-i18n*` attribute in markup, and `npm run i18n` must pass. See [docs/I18N.md](docs/I18N.md).
|
||||
- User-visible text goes through `t()` or `tn()`, with `msg()` marking English that is stored and translated later. Static page markup that predates the views keeps its `data-i18n*` attributes; components use `t()`. `npm run i18n` must pass. See [docs/I18N.md](docs/I18N.md).
|
||||
- Prefer small, reviewable commits. Conventional-commit-style prefixes (`feat:`, `fix:`, `perf:`, `docs:`) are appreciated but not required.
|
||||
|
||||
## Building UI
|
||||
|
||||
New UX elements are Vue components whose state lives in a Pinia store, and so
|
||||
are existing ones when a change converts them:
|
||||
|
||||
- **Views are Vue components.** Application views live in `src/ui/views/` and
|
||||
the components they place in `src/ui/views/panels/`; a component that
|
||||
belongs to one feature sits beside its owner (`src/ui/rail/`,
|
||||
`src/ui/weather/`). A view renders what its store holds and forwards
|
||||
clicks and input to the store; it holds no application logic.
|
||||
- **State lives in a Pinia store** in `src/ui/stores/`. The owner presents a
|
||||
plain view object and publishes it to the store; the view renders it. User
|
||||
actions return to the owner through handlers it connects to the store,
|
||||
which replace an earlier owner's. Where several owners answer different
|
||||
actions of one store, use `createOwners()` from `src/ui/stores/owners.js`:
|
||||
`act(name, ...args)` calls the newest connected owner that handles `name`,
|
||||
and the owner calls `detach(token)` when it stops.
|
||||
- **Portable owners stay framework-free.** An owner in a portable export
|
||||
imports neither Vue nor Pinia: it takes a `publish` option or offers a
|
||||
`subscribe…()`, and the application shell connects it to the store.
|
||||
`npm run check:boundaries` enforces this.
|
||||
- **Reuse the kit first.** `src/ui/kit/` has one component per control:
|
||||
`UiButton` (including pressed toggles and pressable chips), `UiSelect`,
|
||||
`UiSlider`, `UiSegmented`, `UiChip` (a label, not a control), `UiBadge`,
|
||||
`UiEmpty`, `UiIcon`, `UiTooltip`, `UiPanel` and `UiRail`. Use these before
|
||||
writing a control. When the kit lacks something, extend a kit component or
|
||||
add one that follows the names, props, events and class names of
|
||||
Halfpixel's `ui-vue` kit, as the existing ones do (see
|
||||
[Component kit](docs/VUE-MIGRATION.md#component-kit)), rather than
|
||||
building a one-off.
|
||||
- **No hand-written DOM binding.** Don't build elements or write text,
|
||||
classes or attributes from a controller to show UI state; render it from
|
||||
the store. New controls take input through the store rather than through
|
||||
listeners the owner adds. To render outside the view's host (the body, the
|
||||
globe container, or a slot another surface opens), use `<Teleport>` to
|
||||
`body`, a fixed id or a container the owner publishes; don't move nodes by
|
||||
hand. What stays imperative: classes on `<body>` and `<head>`, which sit
|
||||
outside Vue (`cockpit-mode`, `ui-clean-view`); focus moves; positions a
|
||||
layout pass measures in the same task that writes them; and surfaces an
|
||||
owner paints or plays, such as the Cesium canvas, overlay canvases and live
|
||||
video. A few existing surfaces keep listeners or bindings that
|
||||
[docs/VUE-MIGRATION.md](docs/VUE-MIGRATION.md) records; keep those
|
||||
contracts when you change them, and don't copy them into new UI.
|
||||
- **Text** goes through `t()` or `tn()` where the template renders it.
|
||||
English kept in a constant or a store is marked with `msg()` and passed to
|
||||
`t()` when it renders, since a `t()` at module load would fix the English.
|
||||
- **Test components, not markup strings.** Mount the component over
|
||||
happy-dom with `@vue/test-utils` or `createApp` and assert what it renders
|
||||
from its store (see `src/testSupport/vueDom.mjs`, `src/ui/kit/*.test.mjs`
|
||||
and `src/ui/views/intelHudView.test.mjs`). Run one such file with
|
||||
`node --import=./build/registerVue.js --test <file>`. Don't pass happy-dom
|
||||
nodes to `assert.equal`/`deepEqual`; compare them with `assertSameNode()`
|
||||
from `src/testSupport/domAssert.mjs`.
|
||||
|
||||
[docs/VUE-MIGRATION.md](docs/VUE-MIGRATION.md) records how each surface moved
|
||||
and what stays imperative, and why.
|
||||
|
||||
## Formatting and reusable components
|
||||
|
||||
Run `npm run format` before submitting changes, then `npm run format:check`
|
||||
|
||||
@@ -491,12 +491,12 @@ How the globe handles live data:
|
||||
- **Sits on the real ground.** Entity heights are aligned to work with Google 3D tiles, so aircraft park on aprons and cameras stand on street corners instead of floating.
|
||||
- **Caching and request budgets.** An OpenSky credit governor, a TomTom daily tile budget, and disk-cached TLEs reduce repeated requests. These controls do not replace provider quotas or billing controls.
|
||||
- **Server-side credentials.** Every API that touches a private key (OpenAI, AISStream, OpenSky OAuth, camera frames) is brokered through a hardened server-side proxy with SSRF protection, response caps, and sanitized errors. The only keys the browser sees are Google Maps and Cesium ion (restrict both at the provider).
|
||||
- **No framework.** Vanilla JavaScript, **CesiumJS**, and **Vite** — plus **Google Photorealistic 3D Tiles** for the planet and the **OpenAI Realtime API** for voice. Fast to read, fast to hack on.
|
||||
- **A small stack.** **Vue 3** and **Pinia** for the interface, **CesiumJS** for the globe and **Vite** to build it — plus **Google Photorealistic 3D Tiles** for the planet and the **OpenAI Realtime API** for voice. Fast to read, fast to hack on.
|
||||
|
||||
```
|
||||
src/
|
||||
├── main.js # Bootstrap: Google 3D tiles, layer registration
|
||||
├── ui/ # Runtime UI — panels, HUD, styles, controls
|
||||
├── ui/ # Runtime UI — Vue views, Pinia stores, kit, controllers, styles
|
||||
├── hud.js # Intelligence HUD + AI scene summary
|
||||
├── keySetup.js # POWER UP panel — in-app provider keys (dev server only)
|
||||
├── mapStackController.js # Basemap switching — Google 3D / Esri / OSM / ion stacks
|
||||
|
||||
@@ -18,6 +18,11 @@ scene playback and voice. It delegates; new behavior belongs with its owner.
|
||||
| `shareRestoration.js` | Initial share/layer restoration and cancellation |
|
||||
| `shellFeedback.js` | Loading feedback, notices and toast lifetime |
|
||||
|
||||
Owners that present UI do so through Vue: they publish plain view objects to a
|
||||
Pinia store in `src/ui/stores/`, views in `src/ui/views/` render them, and user
|
||||
actions return through the handlers the owner connects to that store. See
|
||||
[Building UI](../CONTRIBUTING.md#building-ui).
|
||||
|
||||
Owners receive named services, elements, operations and readers. They do not
|
||||
receive the application shell itself. Readers resolve a replaceable collaborator
|
||||
at use time; operations cross an ownership boundary without copying its state.
|
||||
|
||||
@@ -48,9 +48,9 @@ existing stylesheet and custom properties; a kit class such as
|
||||
`ui-button--icon` carries no Core style yet, and a converted control keeps
|
||||
its own classes beside it. They contain no application state.
|
||||
`UiPanel` takes ui-vue's `title`, slots and `v-model:collapsed`, but its
|
||||
`collapsed` drives only the button and `ui-panel--collapsed`: the panel's
|
||||
owner hides the body by writing the root's `collapsed` class at once, and
|
||||
there is no `closable`, since Core's panels collapse rather than close.
|
||||
`collapsed` drives only the button and `ui-panel--collapsed`: the root's
|
||||
`collapsed` class, which hides the body, is drawn at once by `v-panel-state`
|
||||
from the panel chrome store, and there is no `closable`, since Core's panels collapse rather than close.
|
||||
`UiSegmented` adds `keyboard` (`none`, `arrows` as in ui-vue, or `radio` with
|
||||
Home and End), since each of Core's groups keeps its own keyboard policy, and
|
||||
`itemClass`/`activeClass` for Core's segment classes. A key moves focus at
|
||||
|
||||
Reference in new issue
Block a user