Merge main into the Utilities panel, rebuilt on the Vue panel rail

main moved the panels to Vue views and a one-open-panel rail, and removed
the two templates this branch edited. This merge carries the branch onto
that architecture; it adds no behaviour of its own beyond the port.

- The Utilities panel is a RailPanel in LayerPanelsView with its own rail
  item (handyman). LayerPanel renders the Directions rows into its list with
  LayerRows, and falls back to Data Layers without it.
- Draw leaves DisplayPanel for DrawControls, DrawMarkList and DrawSwatches,
  which render what the draw tool publishes to the display store and call
  its actions, as GeoImport does. drawMarks.js words the rows; the DOM-built
  drawMarkList.js is gone. A row's fly-to is an immediate navigation like
  Import's ('drawing' gets its Cockpit refusal), the name field keeps a
  draft through v-field-value, and the colours are one radio group with a
  single tab stop.
- UiSegmented draws an option's icon, named by its label, for the shape
  buttons.
- The catalogs take main's languages with this branch's strings, Arabic
  included, and the tests follow the views to their new homes.
This commit is contained in:
Said Turksever committed 2026-11-02 16:43:29 +00:00
commit 4ebb287d36
699 files changed
+46673 -20476

No files matched your search

+58 -2
View File
@@ -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,65 @@ 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. Components call `t()` in their templates, so their text follows the locale; `data-i18n*` attributes are only for static page markup such as the loading screen, and `npm run i18n` rejects them in a template. `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 kit's names, props, events and class names (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`