87 lines
2.6 KiB
JavaScript
87 lines
2.6 KiB
JavaScript
|
|
/// <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);
|
||
|
|
}
|
||
|
|
);
|