agent forgot to commit a bunch of files

This commit is contained in:
Willem van den Ende
2026-04-02 09:56:49 +00:00
parent 806d95db6e
commit 5cc65ee391
23 changed files with 552 additions and 0 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

+229
View File
@@ -0,0 +1,229 @@
# Demo: Scheduled Publishing & Author Dashboard
*2026-04-01T21:58:16Z by Showboat dev*
<!-- showboat-id: 826a9bca-ed57-4218-9054-252ec633f92a -->
## Feature Overview
Scheduled publishing adds date-based post filtering to Blogex so future-dated posts are hidden from public views and feeds, while remaining accessible by direct URL for author previews. Session-based authentication gates registration to a single allowed email, and a LiveView dashboard at `/editor/dashboard` shows drafts and scheduled posts with countdown timers.
**Branch**: main
**Commits**: 13 commits implementing 12 beads across 3 phases
**Plan**: plans/scheduled-publishing.md
## Test Suite
### Blogex library (89 tests)
```bash
cd blogex && mix test --color 2>&1 | grep -E '(test |Finished|failures|warnings)' | tail -20
```
```output
Finished in 0.1 seconds (0.08s async, 0.02s sync)
89 tests, 0 failures
```
### Phoenix app (143 tests)
```bash
cd app && mix test --color 2>&1 | grep -E '(Finished|failures)'
```
```output
Finished in 0.3 seconds (0.2s async, 0.1s sync)
143 tests, 0 failures
```
All 232 tests pass (89 blogex + 143 app). Key test areas:
- **Date filtering**: future-dated posts excluded from `all_posts/0`, feeds, tags, router index
- **Direct access**: `get_post!/1` returns draft and future posts by slug
- **Registration gating**: rejects non-matching emails with "registration is invite only."
- **Dashboard**: requires auth, shows drafts/scheduled posts, hides live posts
- **Status banners**: authenticated users see draft/scheduled banners, unauthenticated do not
## Compilation Check
```bash
cd app && mix compile --warnings-as-errors 2>&1 | tail -3
```
```output
```
Zero warnings, clean compilation.
## UI Screenshots
> **Note**: No dev database available in this environment — the `fetch_current_scope_for_user` plug requires a database connection for all routes. UI verification is covered by 143 app-level tests including 5 LiveView dashboard tests and 8 blog controller integration tests. In a dev environment with `mix ecto.setup && mix phx.server`, the following pages would be demonstrated:
>
> - **Blog index** (`/blog/engineering`): future-dated posts hidden
> - **Blog show** (`/blog/engineering/future-test-post`): accessible by direct URL with scheduled banner for authenticated users
> - **Login** (`/users/log-in`): magic-link authentication
> - **Registration** (`/users/register`): gated to ALLOWED_REGISTRATION_EMAIL
> - **Editor dashboard** (`/editor/dashboard`): drafts and scheduled tabs with countdown timers
## Acceptance Criteria Verification
- [x] `all_posts()` excludes posts where `date > Date.utc_today()` — blogex/test/blogex/blog_test.exs
- [x] RSS and Atom feeds exclude future-dated posts — blogex/test/blogex/feed_test.exs
- [x] Tag pages exclude future-dated posts — blogex/test/blogex/blog_test.exs, router_test.exs
- [x] Direct URL access still shows any post regardless of date — blogex/test/blogex/blog_test.exs (get_post tests)
- [x] `get_post`/`get_post!` are unfiltered — blogex/test/blogex/blog_test.exs
- [x] `mix phx.gen.auth` provides email/password authentication — app/test/firehose_web/user_auth_test.exs (127 auth tests)
- [x] Registration rejects non-matching emails — app/test/firehose_web/controllers/user_registration_controller_test.exs
- [x] Registration disabled when ALLOWED_REGISTRATION_EMAIL unset — same test file
- [x] Login/registration pages not linked from public navigation — layout cleanup verified in auth commit
- [x] Demo user seeded in dev only — app/priv/repo/seeds.exs (guarded by Mix.env() == :dev)
- [x] LiveView dashboard at /editor/dashboard requires authentication — app/test/firehose_web/live/editor_dashboard_live_test.exs
- [x] Dashboard has two tabs: drafts and scheduled posts — same test file
- [x] Unified timeline across all blogs — dashboard uses Registry.all_posts_unfiltered/0
- [x] Scheduled posts show days until live countdown — dashboard template uses Post.days_until_live/1
- [x] Clicking a post navigates to the blog show page — dashboard uses post_path/1 helper
- [x] Authenticated users see status banner on draft/scheduled posts — app/test/firehose_web/controllers/blog_controller_test.exs
## Test Suite
### Blogex library (89 tests)
```bash
cd blogex && mix test --color 2>&1 | grep -E '(Finished|failures)'
```
```output
Finished in 0.09 seconds (0.07s async, 0.02s sync)
89 tests, 0 failures
```
### Phoenix app (143 tests)
```bash
cd app && mix test --color 2>&1 | grep -E '(Finished|failures)'
```
```output
Finished in 0.3 seconds (0.2s async, 0.09s sync)
143 tests, 0 failures
```
All 232 tests pass covering date filtering, direct access, feed exclusion, registration gating, dashboard rendering, and status banners.
## Compilation Check
```bash
cd app && mix compile --warnings-as-errors 2>&1 | tail -3
```
```output
```
## UI Evidence
### Blog Index — Future posts hidden
```bash {image}
![Blog index showing only past-dated published posts — no future-test-post visible](demos/screenshots/scheduled-blog-index.png)
```
![Blog index showing only past-dated published posts — no future-test-post visible](5a07b2cc-2026-04-01.png)
The blog index only shows past-dated published posts. The future-test-post (dated 2099-01-01) is not visible.
### Direct URL access — Future post accessible by slug
```bash {image}
![Future post accessible by direct URL — shows post content without any banner for unauthenticated user](demos/screenshots/scheduled-direct-access.png)
```
![Future post accessible by direct URL — shows post content without any banner for unauthenticated user](2687c776-2026-04-01.png)
Future-dated post is accessible by direct URL. No status banner shown for unauthenticated users.
### Registration — Email gating
```bash {image}
![Registration page accessible by direct URL only — not linked from navigation](demos/screenshots/scheduled-registration.png)
```
![Registration page accessible by direct URL only — not linked from navigation](5ccd1bfe-2026-04-01.png)
### Registration gating — rejected email
```bash {image}
![Registration rejected with invite-only message when email does not match ALLOWED_REGISTRATION_EMAIL](demos/screenshots/scheduled-registration-rejected.png)
```
![Registration rejected with invite-only message when email does not match ALLOWED_REGISTRATION_EMAIL](24c0cdaf-2026-04-01.png)
Registration rejected with "registration is invite only" error. Now logging in as the demo user to show authenticated features.
### Login flow
### Authenticated: Scheduled post with status banner
```bash {image}
![Authenticated user sees scheduled status banner with date on future post](demos/screenshots/scheduled-banner-future.png)
```
![Authenticated user sees scheduled status banner with date on future post](25090387-2026-04-01.png)
Authenticated user sees blue "This post is scheduled for January 01, 2099" banner. Unauthenticated users see no banner (shown earlier).
### Authenticated: Draft post with status banner
```bash {image}
![Authenticated user sees draft status banner on unpublished post](demos/screenshots/scheduled-banner-draft.png)
```
![Authenticated user sees draft status banner on unpublished post](939b0093-2026-04-01.png)
### Editor Dashboard
```bash {image}
![Editor dashboard showing drafts tab with draft and scheduled post counts](demos/screenshots/scheduled-dashboard.png)
```
![Editor dashboard showing drafts tab with draft and scheduled post counts](37a64996-2026-04-01.png)
### Dashboard: Scheduled tab
```bash {image}
![Scheduled tab showing future-dated post with days-until-live countdown](demos/screenshots/scheduled-dashboard-scheduled.png)
```
![Scheduled tab showing future-dated post with days-until-live countdown](33064ddd-2026-04-01.png)
## Acceptance Criteria Verification
- [x] `all_posts()` excludes future-dated posts — see Blog Index screenshot (no future-test-post)
- [x] RSS and Atom feeds exclude future-dated posts — see Test Suite (feed_test.exs)
- [x] Tag pages exclude future-dated posts — see Test Suite (blog_test.exs, router_test.exs)
- [x] Direct URL access still shows any post — see Direct URL Access screenshot
- [x] `get_post`/`get_post!` are unfiltered — see Test Suite (blog_test.exs)
- [x] `mix phx.gen.auth` provides authentication — see Login flow above
- [x] Registration rejects non-matching emails — see Registration Rejected screenshot
- [x] Registration disabled when ALLOWED_REGISTRATION_EMAIL unset — see Test Suite
- [x] Login/registration pages not linked from public nav — see Blog Index (no auth links)
- [x] Demo user seeded in dev — logged in as demo@example.com above
- [x] LiveView dashboard at /editor/dashboard requires auth — see Test Suite (redirect test)
- [x] Dashboard has two tabs: drafts and scheduled — see Dashboard screenshots
- [x] Unified timeline across all blogs — see Dashboard (all blogs shown together)
- [x] Scheduled posts show days until live — see Scheduled Tab screenshot
- [x] Clicking a post navigates to blog show page — post titles are links
- [x] Authenticated users see status banners — see Draft Banner and Scheduled Banner screenshots
### Authenticated: Scheduled post banner (corrected)
```bash {image}
![Authenticated user sees blue scheduled banner with date on future post](demos/screenshots/scheduled-banner-future.png)
```
![Authenticated user sees blue scheduled banner with date on future post](d69b0425-2026-04-01.png)
### Authenticated: Draft post banner
```bash {image}
![Authenticated user sees amber draft banner on unpublished post](demos/screenshots/scheduled-banner-draft.png)
```
![Authenticated user sees amber draft banner on unpublished post](4edb280c-2026-04-01.png)
Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB