kanban-dev-webapp/pocketbase/pb_migrations/1789601200_added_card_proposals.js

87 lines
2.6 KiB
JavaScript
Raw Permalink Normal View History

2026-09-19 16:35:33 +00:00
/// <reference path="../pb_data/types.d.ts" />
/**
* Proposal fields on `cards`.
*
* Plan Puzzle v1: clients drag a card into a month slot and we record their
* intent on three nullable fields rather than overwriting `target_date`
* (which the owner controls). The owner sees the chip, accepts (which copies
* the proposal into `target_date`), or dismisses (which clears it).
*
* The three fields are written and cleared together. A row with one set and
* the others null is logically incoherent; nothing in the application writes
* one without the others. See src/app/actions/plan/client-proposal.ts and
* src/app/actions/plan/owner-plan.ts for the only writers.
*
* The partial index supports the owner-side "show me cards with pending
* proposals" query without indexing the millions of empty proposals on the
* rest of the table.
*
* REFERENCE ONLY — see pb_migrations/README.md. scripts/setup-remote.ts is
* what runs.
*/
migrate(
(app) => {
const cards = app.findCollectionByNameOrId("cards");
const users = app.findCollectionByNameOrId("users");
cards.fields.add([
{
name: "proposed_target_date",
type: "date",
required: false,
presentable: false,
hidden: false,
system: false,
},
{
name: "proposed_by",
type: "relation",
required: false,
collectionId: users.id,
cascadeDelete: false,
minSelect: 0,
maxSelect: 1,
presentable: false,
hidden: false,
system: false,
},
{
name: "proposed_at",
type: "date",
required: false,
presentable: false,
hidden: false,
system: false,
},
]);
const existing = new Set((cards.indexes as string[]) ?? []);
const proposalIndex =
"CREATE INDEX idx_cards_proposal ON cards (proposed_target_date) WHERE proposed_target_date IS NOT NULL";
if (!existing.has(proposalIndex)) {
cards.indexes.push(proposalIndex);
}
return app.save(cards);
},
(app) => {
const cards = app.findCollectionByNameOrId("cards");
for (const name of [
"proposed_target_date",
"proposed_by",
"proposed_at",
]) {
const field = cards.fields.find((f) => f.name === name);
if (field) cards.fields.removeById(field.id);
}
const indexes = (cards.indexes as string[]) ?? [];
const proposalIndex =
"CREATE INDEX idx_cards_proposal ON cards (proposed_target_date) WHERE proposed_target_date IS NOT NULL";
cards.indexes = indexes.filter((i) => i !== proposalIndex);
return app.save(cards);
}
);