Compare commits

...

3 Commits

Author SHA1 Message Date
Disco DeDisco
b97c4a0508 woodpecker main.yaml: workspace-shared pip cache via PIP_CACHE_DIR: .pip-cache on all 3 test steps (test-UTs-n-ITs / test-two-browser-FTs / test-FTs) — each step currently re-downloads the entire requirements.txt wheel set independently; Woodpecker mounts the workspace across steps in one run, so the wheels populated by step 1 are reused by steps 2-3, saving ~1-2 min of pip-install wall-clock per run (only download time — install still happens fresh per container); pyswiss.yaml untouched (separate pipeline, separate workspace, separate requirements); cache is per-run only — cross-run persistence would need a Woodpecker volume plugin
Some checks failed
ci/woodpecker/push/pyswiss Pipeline was successful
ci/woodpecker/push/main Pipeline failed
Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 18:01:34 -04:00
Disco DeDisco
3932b17256 aperture architecture: lift the page-locking foundation (html/body/.container overflow:hidden + flex-column + min-height:0; .row flex-shrink:0) from 5 per-page SCSS files into _base.scss — was opt-in per page via body.page-billboard / page-dashboard / page-gameboard / page-sky / page-wallet etc., with 5 near-identical html:has(body.page-X) { overflow: hidden } + body.page-X { … } blocks duplicating the same rules; any page that forgot to set page_class in its view context (e.g. epic.tarot_deck — never set) rendered without the aperture, letting applet borders + titles clip past the fixed navbar/footer sidebars at narrower viewports; foundation now universal, page-specific overrides stay scoped — gameboard keeps .container { overflow: clip } (Firefox seat-tooltip scroll-anchoring quirk) + billboard/dashboard/gameboard keep .row { margin-bottom: -1rem } (h2-row tightening); page_class context vars + body class hooks preserved (FTs at test_bud_btn.py:370 / :379 still assert on them); regression gate: 60 layout-sensitive FTs (billboard, my_buds, bud_btn, applet_my_posts, dashboard, wallet, gameboard, layout_and_styling, jasmine) + 43 room FTs (gatekeeper_bud_btn, room_gatekeeper, room_sky_select, sharing) all green
Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 17:16:12 -04:00
Disco DeDisco
17c4518944 my_buds: dismiss "No buds yet" empty-state row async on first-bud add — _appendBudEntry queried .bud-entry--empty but _applet-list-shell renders it w. the family-agnostic .applet-list-entry--empty class; the selector never matched, so first-bud appends landed alongside the empty row instead of replacing it; existing test_add_bud_via_bud_btn_appends_entry extended to also assert the empty row dismisses post-add (caught the bug — TDD)
Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 16:47:13 -04:00
9 changed files with 60 additions and 91 deletions

View File

@@ -16,6 +16,12 @@ steps:
DATABASE_URL: postgresql://postgres:postgres@postgres/python_tdd_test
CELERY_BROKER_URL: redis://redis:6379/0
REDIS_URL: redis://redis:6379/1
# Workspace-shared pip cache — Woodpecker mounts the workspace across
# all steps in a run, so the wheels populated here are reused by
# test-two-browser-FTs + test-FTs (saves ~30-60s × 2 = ~1-2 min per
# run). Cache lives only inside one run; cross-run caching would
# need a volume plugin.
PIP_CACHE_DIR: .pip-cache
commands:
- pip install -r requirements.txt
- cd ./src
@@ -37,6 +43,7 @@ steps:
from_secret: stripe_secret_key
STRIPE_PUBLISHABLE_KEY:
from_secret: stripe_publishable_key
PIP_CACHE_DIR: .pip-cache
commands:
- pip install -r requirements.txt
- cd ./src
@@ -61,6 +68,7 @@ steps:
from_secret: stripe_secret_key
STRIPE_PUBLISHABLE_KEY:
from_secret: stripe_publishable_key
PIP_CACHE_DIR: .pip-cache
commands:
- pip install -r requirements.txt
- cd ./src

View File

@@ -55,6 +55,12 @@ class MyBudsPageTest(FunctionalTest):
self.wait_for(lambda: self.assertIn(
self.alice, list(self.gamer.buds.all())
))
# "No buds yet" empty-state row dismisses async as the first bud lands
# (shell partial renders w. .applet-list-entry--empty, not .bud-entry--empty)
self.wait_for(lambda: self.assertEqual(
self.browser.find_elements(By.CSS_SELECTOR, ".applet-list-entry--empty"),
[],
))
def test_no_autocomplete_suggestions_on_my_buds_page(self):
"""The bud-autocomplete pool is request.user.buds — surfacing buds

View File

@@ -7,6 +7,13 @@
// 2.4vmin hits 16px (browser default) at vmin=667 (iPhone SE landscape).
html {
font-size: clamp(14px, 2.4vmin, 22px);
// Aperture foundation — locks the document viewport so content lives
// between/behind the fixed navbar + footer sidebars instead of leaking
// into a page-level scroll. Was opt-in per-page via body.page-X classes
// (duplicated 5× across SCSS files); now universal. Pages that need a
// narrower override (e.g. body.page-gameboard .container { overflow:
// clip; }) live in their per-page SCSS.
overflow: hidden;
}
// Layout custom properties — single source of truth for the landscape
@@ -25,6 +32,7 @@ body {
color: rgba(var(--secUser), 1);
font-family: Georgia, serif;
height: 100vh;
overflow: hidden;
a {
text-decoration: none;
@@ -43,6 +51,14 @@ body {
margin: 0 auto;
// padding: 0 1rem;
flex: 1;
// Aperture container — flex-column so navbar + h2 row + page content
// stack vertically, min-height: 0 + overflow: hidden contain the
// content within the aperture so applet borders / titles can't
// leak past the navbar / footer sidebars at narrow viewports.
display: flex;
flex-direction: column;
min-height: 0;
overflow: hidden;
.navbar {
padding: 0.75rem 0;
@@ -183,6 +199,10 @@ body {
.row {
padding: 2rem 0;
// Aperture: the h2-row mustn't shrink when the page-content
// child fills the remaining vertical space. Universal — was
// duplicated in every body.page-X { .row { flex-shrink: 0 } }.
flex-shrink: 0;
.col-md-12 {
width: 100%;

View File

@@ -24,6 +24,12 @@
}
// ── Shared aperture fill for both billboard pages ──────────────────────────
//
// Aperture foundation (html/body/.container overflow + flex-column +
// .row flex-shrink: 0) now lives universally in _base.scss. Only the
// page-specific `.row { margin-bottom: -1rem }` pull (tightening the
// h2 row against subsequent applet content) stays here, since wallet
// + sky pages deliberately don't carry that pull.
%billboard-page-base {
flex: 1;
@@ -33,31 +39,12 @@
position: relative;
}
html:has(body.page-billboard),
html:has(body.page-billscroll),
html:has(body.page-billpost),
html:has(body.page-billbuds),
html:has(body.page-billposts) {
overflow: hidden;
}
body.page-billboard,
body.page-billscroll,
body.page-billpost,
body.page-billbuds,
body.page-billposts {
overflow: hidden;
.container {
overflow: hidden;
display: flex;
flex-direction: column;
flex: 1;
min-height: 0;
}
.row {
flex-shrink: 0;
margin-bottom: -1rem;
}
}

View File

@@ -1,23 +1,8 @@
html:has(body.page-dashboard) {
overflow: hidden;
}
// Aperture foundation now lives in _base.scss; only the dashboard-specific
// `.row { margin-bottom: -1rem }` pull stays here.
body.page-dashboard {
overflow: hidden;
.container {
overflow: hidden;
display: flex;
flex-direction: column;
flex: 1;
min-height: 0;
}
.row {
flex-shrink: 0;
margin-bottom: -1rem;
}
body.page-dashboard .row {
margin-bottom: -1rem;
}
#id_dash_content {

View File

@@ -1,21 +1,16 @@
html:has(body.page-gameboard) {
overflow: hidden;
}
// Aperture foundation (html/body/.container overflow + flex-column) lives
// universally in _base.scss. Gameboard's only divergence: `overflow: clip`
// on .container instead of `hidden` — `clip` prevents the seat tooltip
// scroll-anchoring quirk Firefox triggers under overflow:hidden. The
// `.row { margin-bottom: -1rem }` pull mirrors the billboard/dashboard
// h2-row tightening.
body.page-gameboard {
overflow: hidden;
.container {
overflow: clip;
display: flex;
flex-direction: column;
flex: 1;
min-height: 0;
}
.row {
flex-shrink: 0;
margin-bottom: -1rem;
}
}

View File

@@ -935,27 +935,10 @@ body[class*="-light"] #id_sky_tooltip_2 {
}
}
// ── Sky full page (aperture + column layout) ──────────────────────────────────
html:has(body.page-sky) {
overflow: hidden;
}
body.page-sky {
overflow: hidden;
.container {
overflow: hidden;
display: flex;
flex-direction: column;
flex: 1;
min-height: 0;
}
.row {
flex-shrink: 0;
}
}
// ── Sky full page (column layout) ─────────────────────────────────────────
//
// Aperture foundation lives universally in _base.scss; nothing sky-specific
// here besides the .sky-page block below.
// Sky page fills the aperture; its content can scroll past the bottom edge.
// overflow-x: hidden clips any horizontal overflow that would otherwise create

View File

@@ -22,25 +22,8 @@
> i { opacity: 0.4; }
}
html:has(body.page-wallet) {
overflow: hidden;
}
body.page-wallet {
overflow: hidden;
.container {
overflow: hidden;
display: flex;
flex-direction: column;
flex: 1;
min-height: 0;
}
.row {
flex-shrink: 0;
}
}
// Aperture foundation lives universally in _base.scss; nothing
// wallet-specific to override.
.wallet-page {
position: relative;

View File

@@ -35,8 +35,10 @@
// Skip if already in DOM (server-side dedup ensures M2M idempotence;
// this guards a fast double-click that races the post-add refresh).
if (list.querySelector('[data-bud-id="' + bud.id + '"]')) return;
// Drop the empty-state row if present
var empty = list.querySelector('.bud-entry--empty');
// Drop the empty-state row if present — _applet-list-shell renders
// it w. `.applet-list-entry--empty` (NOT `.bud-entry--empty`); the
// shell sets the family-agnostic class.
var empty = list.querySelector('.applet-list-entry--empty');
if (empty) empty.remove();
var li = document.createElement('li');