logaritmisk 27205c65ef fix(web): disable delete confirms while pending + Signing in… feedback (#70)
The delete dialogs (DeleteObjectDialog and the shared
DeleteConfirmDialog) left their confirm button enabled during the
in-flight request, so a double-click fired a second DELETE that 404'd
and surfaced a spurious error. Disable cancel + confirm while pending
and swap the confirm label to a new actions.deleting ("Deleting…" /
"Tar bort…").

The login button disabled itself during login.isPending but kept the
"Sign in" label; it now shows auth.signingIn ("Signing in…" /
"Loggar in…") so slow networks get visible feedback.

Each fix is covered by a gated-MSW (or gated-promise) test asserting
the pending label + disabled state before releasing the request.

Closes #70

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 13:35:27 +02:00

Biggus Dickus

Biggus Dickus

A museum collection-management system: a Rust (axum + sqlx + Postgres) API with a React + TypeScript admin SPA and optional Meilisearch-backed full-text search.

Running locally

The whole backing stack runs from one docker compose file (PostgreSQL + Meilisearch).

Prerequisites

  • Docker (PostgreSQL + Meilisearch)
  • Rust (stable; plus a nightly toolchain for cargo +nightly fmt)
  • Node.js and pnpm (web frontend)
  • just — optional, for the shortcuts below

1. Start the backing services

docker compose up -d

PostgreSQL listens on localhost:5432 (database cms_dev) and Meilisearch on localhost:7700. Give them a few seconds to become healthy on first start.

2. Configure the environment

cp .env.example .env

The defaults already match the compose services. Note SESSION_COOKIE_SECURE=false: local development is plain HTTP, and browsers drop Secure cookies on http://localhost, so leaving it true would make login silently fail. Set it back to true for any HTTPS deployment.

3. Run the API server

just run        # or: cargo run -p server

On startup the server connects to PostgreSQL, runs database migrations automatically, ensures the Meilisearch index exists, and listens on http://localhost:8080. (If the MEILI_* variables are unset, search is disabled and everything else still works.)

4. Create a login user

There is no seeded account — create one (you'll be prompted for a password, minimum 8 characters):

cargo run -p server -- create-user --email you@example.com --role admin
# non-interactive:
BOOTSTRAP_PASSWORD=changeme123 cargo run -p server -- create-user --email you@example.com --role editor

Roles are admin or editor.

5. Seed the baseline cataloguing fields (idempotent)

just seed            # or: cargo run -p server -- seed

Populates the baseline Spectrum cataloguing vocabularies and field definitions. Safe to re-run — the seed is idempotent.

6. Run the web frontend

The API server serves JSON only; in development the SPA is served by Vite, which proxies /api to :8080:

cd web
pnpm install
pnpm dev        # http://localhost:5173

Open http://localhost:5173 and sign in with the user from step 4.

Single-binary alternative

To serve the built SPA and the API from one process (no Vite), build the web assets and enable the embed-web feature:

cd web && pnpm build                          # outputs web/dist
cargo run -p server --features embed-web      # SPA + API on http://localhost:8080

Assets are embedded at compile time, so rebuild web/dist and recompile after frontend changes.

Running tests

Backend tests reuse the same compose services — PostgreSQL provisions a throwaway database per test (sqlx::test) and Meilisearch tests use isolated, unique index names, so they don't touch your dev data. With docker compose up -d running and .env in place:

just test                 # cargo test --workspace (reads .env via dotenv)
cd web && pnpm test       # frontend tests (Vitest + MSW; no services needed)

just check runs format + lint + the Rust test suite. Run cargo test directly only if DATABASE_URL/MEILI_URL/MEILI_MASTER_KEY are exported in your shell — the Meilisearch tests require them; just loads them from .env for you.

S
Description
No description provided
Readme 2.9 MiB
Languages
Rust 49.4%
TypeScript 48%
JavaScript 1.7%
CSS 0.5%
PLpgSQL 0.2%
Other 0.2%