Commit Graph

47 Commits

Author SHA1 Message Date
giles
322ae481ee Move domain templates to owning apps, delete dead widgets (Phase 6)
Domain-specific templates moved from shared/browser/templates/ to
each app's templates/ dir. 38 domain-free infrastructure templates
remain (root layout, macros, oob, mobile, social, sentinel).
Removed fragment fallbacks from root header.
Deleted _widgets/ (dead code since Phase 4-5).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 16:37:08 +00:00
giles
65c4989d08 Replace account widgets with fragment composition (Phase 5)
Account nav links and page panels (tickets, bookings) now fetched
as HTML fragments from events app instead of using widget registry.
All three widget registration functions are now no-ops.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 13:56:29 +00:00
giles
d2e07e047e Replace container nav/card widgets with fragment composition (Phase 4)
Templates now consume container_nav_html and card_widgets_html from
fragment fetches instead of iterating widgets.container_nav / container_cards.
OOB nav template renders entry/calendar links directly from data.
Calendar and market widget registrations removed (account widgets remain).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 13:32:48 +00:00
giles
ab674ada31 Fix nav links: map all app slugs to correct app URLs
Previously only 'cart' was mapped — slugs like 'federation', 'market',
'events', 'account' incorrectly linked to blog_url(). Now all app
slugs resolve to their proper cross-app URLs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 11:49:04 +00:00
giles
7e650a0ee3 Add nav-tree, auth-menu, cart-mini fragment slots to shared header
The shared _header.html template now checks for pre-fetched fragment
HTML (nav_tree_html, auth_menu_html, cart_mini_html) before falling
back to local includes. This lets consumer apps render cross-app
UI via the fragment composition system.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 11:34:45 +00:00
giles
0d40dfaeca Rename product blueprint URL param slug → product_slug in templates
Avoids collision with app-level url_value_preprocessor that pops
"slug" for page-level routing. All url_for() calls for product
endpoints now use product_slug= instead of slug=.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 10:24:49 +00:00
giles
001cbffd74 Add minimal home page templates — content only, no title bar
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 17:32:25 +00:00
giles
38233279a2 Rename blog.home → blog.index in not_found template
The blog index moved from / to /index; homepage now shows a Ghost page.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 16:54:02 +00:00
giles
8323c45711 Fix logout: post to local /auth/logout/ not federation
Each app has its own session and OAuth logout endpoint now.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 11:07:03 +00:00
giles
16df62e2c4 Sign-in button → account app, clear old shared cookie
- Nav sign-in links point to account_url('/') instead of login_url()
- After-request hook clears old blog_session cookie on .rose-ash.com
  (prevents collision with new per-app first-party cookies)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 10:56:56 +00:00
giles
46f44f6171 OAuth SSO infrastructure + account app support
- OAuthCode model + migration for authorization code flow
- OAuth client blueprint (auto-registered for non-federation apps)
- Per-app first-party session cookies (fixes Safari ITP)
- /oauth/authorize endpoint support in URL helpers
- account_url() helper + Jinja global
- Templates: federation_url('/auth/...') → account_url('/...')
- Widget registry: account page links use account_url

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 09:55:27 +00:00
giles
326b380135 Fix root top-bar account link to point to federation
The logged-in user links in _full_user.html (desktop + mobile)
still used blog_url — now they use federation_url to match
the account page migration.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 09:07:38 +00:00
giles
ea8e7da9d4 Move account page URLs from blog to federation
Auth templates and widget nav links now point to
federation_url instead of blog_url, co-locating the
account UI with the auth system in the federation app.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 09:00:44 +00:00
giles
bd18d0befc Route auth to federation: login_url default, logout URL, federation_url global
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 08:41:18 +00:00
giles
798087de9a Rename coop to blog throughout codebase
- coop_url() → blog_url(), AUTH_APP default → "blog"
- Session cookie: coop_session → blog_session
- Config keys: coop_root/coop_title → market_root/market_title
- All Jinja templates: coop_url → blog_url, coop_title → market_title
- Template blocks: coop-child-header → blog-child-header

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 08:32:46 +00:00
giles
9cdd2195df Restore all 33 deleted shared templates
Templates were incorrectly identified as dead code because individual
apps override them, but other apps still depend on the shared versions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 19:26:48 +00:00
giles
46f6ca4a0f Remove dead code: domain_event.py + 39 overridden templates
- Delete shared/models/domain_event.py (table dropped, model orphaned)
- Delete 39 shared templates that are overridden by app-local copies:
  - 8 blog overrides (blog/_action_buttons, post/_meta, etc.)
  - 27 events overrides (calendar/*, day/*, entry/*, post_entries/*)
  - 4 market overrides (market/index, browse/_oob_elements, etc.)

These shared copies were never served — Quart loads app-level
templates first, so the app-local versions always win.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 18:09:02 +00:00
giles
7de4a2e40e Remove dead shared _cart.html template
The cart app has its own override with ticket support. The shared
copy was never used and would only cause confusion.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 18:05:17 +00:00
giles
07aa2e2be9 Fix cart sign-in button: use plain link instead of HTMX
The login URL is cross-origin (blog app), so hx-get can't load it
into the current page. Use a regular <a href> for cross-app navigation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 17:37:16 +00:00
giles
04f7c5e85c Add fediverse social features: followers/following lists, actor timelines
Adds get_followers_paginated and get_actor_timeline to FederationService
protocol + SQL implementation + stubs. Includes accumulated federation
changes: models, DTOs, delivery handler, webfinger, inline publishing,
widget nav templates, and migration.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 13:41:58 +00:00
giles
24432cd52a Page-aware labels in blog_new template
- "Post title"→"Page title", "Create Post"→"Create Page" when is_page

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 22:31:58 +00:00
giles
9a1a4996bc Use "Page" labels instead of "Post" when editing pages
- Edit: placeholder "Page title..." vs "Post title..."
- Settings: slug placeholder, featured checkbox, custom template
  all say "page" when is_page is true

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 22:13:50 +00:00
giles
1832c53980 Skip blog chrome (like, tags, authors, excerpt) for pages
Pages are container/landing pages, not blog posts. Hide the like
button, tags/authors bar, and excerpt when post.is_page is true.
Feature image and content still render for both.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 22:10:39 +00:00
giles
7abef48cf2 Add count param to cart mini macro for explicit override
When the macro is imported without context ({% from ... import mini %}),
template variables like cart_count aren't visible. The new count param
allows callers to pass it explicitly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 09:42:58 +00:00
giles
e83df2f742 Decoupling audit cleanup: fix protocol gaps, remove dead APIs
- Add search_posts, entry_ids_for_content, visible_entries_for_period
  to protocols and stubs
- Delete internal_api.py and factory cleanup hook (zero callers)
- Convert utils.py to utils/ package with calendar_helpers module
- Remove deleted_at check from calendar_view template (service filters)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 10:58:07 +00:00
giles
7ee8638d6e Add ticket-to-cart integration
Reserved tickets now flow through the cart and checkout pipeline:
- TicketDTO gains price, entry_id, order_id, calendar_container_id
- CartSummaryDTO gains ticket_count, ticket_total
- 6 new CalendarService methods for ticket lifecycle
- cart_summary includes tickets; login adoption migrates tickets
- New _ticket_items.html template for checkout return page

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 21:32:30 +00:00
giles
71729ffb28 Remove debug comment from post nav template
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 19:57:07 +00:00
giles
8b6be6da96 Add template debug comment for widget nav
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 19:32:43 +00:00
giles
7882644731 Add widget registry for universal UI decoupling
Introduces a widget system where domains register UI fragments into
named slots (container_nav, container_card, account_page, account_link).
Host apps iterate widgets generically without naming any domain.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 18:04:13 +00:00
giles
dfc324b1be Add tickets & bookings to account page
Add TicketDTO, user_tickets/user_bookings to CalendarService protocol
and SqlCalendarService implementation, plus nav links and panel
templates for the auth account sub-pages.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 16:06:21 +00:00
giles
98c3df860b Fix category selector highlighting to use slug comparison
Use top_slug/sub_slug directly instead of current_local_href for
active state detection. The previous approach compared full request
paths against short category-relative paths, which never matched.
This also avoids conflicting with current_local_href used by brand
filter URL construction.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 15:28:51 +00:00
giles
3febef074b Fix menu item highlighting with aria-selected attribute
Added app_name Jinja global and aria-selected to nav menu links.
Matches by first path segment (e.g. /market/... → "market") or by
app_name for cross-domain cases (e.g. cart app → "cart" menu item).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 13:56:07 +00:00
giles
6db91cb3c1 Add delete button with confirm modal to cart_item, clamp minus at 0
Minus button now floors at 0 instead of going negative. A trash button
with SweetAlert2 confirmation appears when cart_delete_url is defined
(cart app only). Items at quantity 0 remain visible for re-increment.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 09:43:12 +00:00
giles
7b55d78214 Fix cross-origin cart +/- buttons by supporting cart_quantity_url in template
The cart_item macro now checks for cart_quantity_url (defined only in the cart app)
and uses it for same-origin quantity updates, falling back to market_product_url.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 09:31:06 +00:00
giles
9cba422aa9 Fix DTO compatibility: replace ORM relationship traversals with DTO fields
Templates were accessing entry.calendar.name/slug/post via ORM relationships,
but these entries are now CalendarEntryDTOs. Use flat fields instead
(calendar_name, calendar_slug, etc.).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 05:04:53 +00:00
giles
e3f8ff6e3c Fix cart-mini home link: use coop_url instead of broken qs|host filter
The |qs filter returns "" when makeqs_factory is not set (events app),
causing |host to generate the events app root URL which has no route.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 21:49:28 +00:00
giles
0c0f3c8416 Decouple cross-app models: move canonical definitions to shared/models/
- Move 6 model files to shared/models/ (ghost_content, order, page_config,
  market, market_place, calendars) so apps import from shared, not each other
- Fix auth templates: replace url_for('auth.*') with coop_url() for
  cross-app compatibility
- Fix TYPE_CHECKING import in sumup.py to use shared.models.order
- Delete dead infrastructure/cart_loader.py (inverted dependency)
- Update models/__init__.py to export all new models

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 20:46:36 +00:00
giles
da10fc4cf9 Add data-hx-disable to orders link to prevent htmx interception
The orders link navigates cross-domain (cart subdomain from coop) and
htmx 2.0 selfRequestsOnly blocks cross-origin requests. Explicitly
disable htmx on this link so the browser does a normal navigation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 19:30:45 +00:00
giles
526d4f6e1b Use coop_url for auth links in shared templates
url_for('auth.account') and url_for('auth.newsletters') only work in
the blog app. Other apps (cart) that render these shared templates
don't have an auth blueprint. Use coop_url() so links always resolve
to the blog subdomain regardless of which app renders the template.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 19:18:28 +00:00
giles
97bd6162c5 Fix market nav link: point to coop.rose-ash.com/market/ not market subdomain
The market menu item in the top bar should link to the blog page at
coop_url('/market/'), not to market_url('/') which goes to the market
subdomain. Reverts the incorrect 'market' addition to _app_slugs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 18:48:24 +00:00
giles
d805af0764 Add page_config support to get_checkout for per-page SumUp credentials
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 18:37:55 +00:00
giles
3aa1aadd0b Add market_product_url helper for correct product URLs
market_url('/product/...') was missing the /<page_slug>/<market_slug>/
prefix required by the market app's route structure. New helper
market_product_url() resolves the prefix from request context
(g.post_slug/g.market_slug in market app, g.page_slug + market_place
in cart app).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 18:19:36 +00:00
giles
a858e33ca3 Add page_config support to SumUp create_checkout
Accept optional page_config parameter to use per-page
SumUp merchant code and API key instead of global config.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 17:51:35 +00:00
giles
4d00ba3dbe Fix doubled URLs when |host filter receives absolute URLs
_join_url_parts() only checked the first segment for a scheme, so
passing an already-absolute URL (e.g. from cart_url()) through the
|host filter would join route_prefix() + absolute URL, producing
"https://host/https://host/path/".

Now detects schemes in later segments and resets the base.

Also add missing 'market' entry to _nav.html _app_slugs to match
_nav_oob.html — without it the market menu item fell through to
coop_url('/market/') instead of market_url('/').

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 11:45:35 +00:00
giles
d1621b8e70 Use cart_url/page_cart_url for checkout action instead of url_for
The checkout form action used url_for('cart_global.checkout') which
only resolves inside the cart app. Replace with cart_url() and
page_cart_url() Jinja globals that work across all apps.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 10:22:22 +00:00
giles
2c4ab9e3c8 Add glue layer support: MenuNode templates, factory registration, migration
- Templates: item.post.X → item.X (MenuNode has label/slug/feature_image directly)
- factory.py: add glue.models to import loop + register_glue_handlers() at startup
- alembic env.py: add glue.models to import loop
- New migration: container_relations + menu_nodes tables with backfill from existing data

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 23:37:35 +00:00
giles
ef806f8fbb feat: extract shared infrastructure from shared_lib
Phase 1-3 of decoupling plan:
- Shared DB, models, infrastructure, browser, config, utils
- Event infrastructure (domain_events outbox, bus, processor)
- Structured logging
- Generic container concept (container_type/container_id)
- Alembic migrations for all schema changes

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 12:45:56 +00:00