shopping: multi-list, DnD ordering, phone layout; fix flaky tests
Shopping lists:
- Multiple lists per tenant: picker uses checkboxes instead of
radios. Relay schema migrated to composite PK (tenant_id,
card_uid) with a position column for display ordering.
- Picker rows are drag-and-drop reorderable (grip handle +
accent drop indicator). Order persists in localStorage and is
pushed to the relay as position integers — phone renders lists
in that order (ORDER BY position, title).
- Each picker row has a goto-arrow that closes the popup,
switches to the card's bucket if needed, and opens the card.
- Relay DELETE /api/shopping removes deactivated lists. Client
proxy forwards DELETE. Deactivating a list in the picker
immediately removes it from the relay.
- Phone UI renders multiple lists as stacked boxes with headers.
Section headings (# h1–h6) get 14px top padding for breathing
room. CSS selectors fixed to match div-based headings inside
the new .shopping-list-box containers.
- Help text updated for multi-list wording.
- pullOne preserves the synced position so a pull doesn't cause
a spurious re-push of the same order.
Test fixes:
- Line-numbers gutter height tolerance bumped 50%→60% — OS text
shaping can push the divergence past 50%.
- Find/replace flaky: replaced sleep(200) with waitFor on the
confirm dialog so slow renders don't miss the OK click.
- Shopping picker test updated: checkboxes instead of radios.
Bumps to 1.9.25.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
4c3954d989
commit
be7eb1523e
12 files changed
+370
-192
No files matched your search
+30
-5
@@ -233,19 +233,44 @@ $db->exec('CREATE TABLE IF NOT EXISTS chat_room_members (
|
||||
)');
|
||||
$db->exec('CREATE INDEX IF NOT EXISTS idx_chat_room_member_tenant ON chat_room_members(tenant_id, room_uid)');
|
||||
|
||||
// Shopping list: one active card per tenant, body mirrored from the
|
||||
// client. Phone toggles checkboxes in-place via the session UI — no
|
||||
// multi-list fan-out, no history, no attachments. hyprcrd remains the
|
||||
// only surface that edits item text.
|
||||
// Shopping lists: multiple active cards per tenant, each mirrored from
|
||||
// the client. Phone toggles checkboxes in-place via the session UI.
|
||||
// hyprcrd remains the only surface that edits item text.
|
||||
$db->exec('CREATE TABLE IF NOT EXISTS shopping_state (
|
||||
tenant_id INTEGER PRIMARY KEY,
|
||||
tenant_id INTEGER NOT NULL,
|
||||
card_uid TEXT NOT NULL,
|
||||
title TEXT NOT NULL DEFAULT "",
|
||||
body TEXT NOT NULL DEFAULT "",
|
||||
position INTEGER NOT NULL DEFAULT 0,
|
||||
updated_at_client TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at_server TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (tenant_id, card_uid),
|
||||
FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE
|
||||
)');
|
||||
// Migrate from old single-PK schema (tenant_id only) to composite PK
|
||||
// + ensure position column exists (may be missing on tables created
|
||||
// before the multi-list update).
|
||||
$shoppingInfo = $db->query("PRAGMA table_info(shopping_state)")->fetchAll();
|
||||
$shoppingPk = array_filter($shoppingInfo, fn($c) => $c['pk'] > 0);
|
||||
$shoppingColNames = array_column($shoppingInfo, 'name');
|
||||
if (count($shoppingPk) === 1) {
|
||||
$db->exec('ALTER TABLE shopping_state RENAME TO _shopping_old');
|
||||
$db->exec('CREATE TABLE shopping_state (
|
||||
tenant_id INTEGER NOT NULL,
|
||||
card_uid TEXT NOT NULL,
|
||||
title TEXT NOT NULL DEFAULT "",
|
||||
body TEXT NOT NULL DEFAULT "",
|
||||
position INTEGER NOT NULL DEFAULT 0,
|
||||
updated_at_client TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at_server TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (tenant_id, card_uid),
|
||||
FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE
|
||||
)');
|
||||
$db->exec('INSERT OR IGNORE INTO shopping_state (tenant_id, card_uid, title, body, updated_at_client, updated_at_server) SELECT tenant_id, card_uid, title, body, updated_at_client, updated_at_server FROM _shopping_old');
|
||||
$db->exec('DROP TABLE _shopping_old');
|
||||
} elseif (!in_array('position', $shoppingColNames)) {
|
||||
$db->exec('ALTER TABLE shopping_state ADD COLUMN position INTEGER NOT NULL DEFAULT 0');
|
||||
}
|
||||
|
||||
// Sync-event notifications: replaces the old bot-chat mechanism. When a
|
||||
// client syncs a card they received, they POST here; the sender polls
|
||||
|
||||
Reference in new issue
Block a user