Redesign document approval flow

Replace the per-approver add/remove model with a quorum-based approval
system. Documents now have default approvers that are pre-populated when
requesting approval, and the publish dialog lets users adjust the list
before submitting.

Key changes:

- Add PENDING_APPROVAL document version status with dedicated transitions
- Introduce approval quorums with request/approve/reject/void lifecycle
- Add default approvers per document (stored in document_default_approvers)
  with MERGE-based upsert for efficient sync
- Add NoDuplicates validator for slice fields
- Split ALTER TYPE ADD VALUE migrations into separate files (required by
  PostgreSQL when run inside transactions)
- Use VOIDED consistently for both quorum status and decision state enums
- Expose void/approve/reject through GraphQL and MCP, with e2e tests
- Add approval management UI: publish dialog with approver selection,
  approval list with void support, and external approve/reject page

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
Sacha Al Himdani
2026-04-09 11:17:51 +02:00
parent 17f579b8a2
commit ab5f42ad74
38 changed files with 2125 additions and 922 deletions

View File

@@ -17,14 +17,23 @@ import { useTranslate } from "@probo/i18n";
import { Badge } from "../../Atoms/Badge/Badge";
type Props = {
state: "DRAFT" | "PUBLISHED";
state: "DRAFT" | "PENDING_APPROVAL" | "PUBLISHED";
};
export function DocumentVersionBadge(props: Props) {
const { __ } = useTranslate();
return (
<Badge variant={props.state === "DRAFT" ? "neutral" : "success"}>
{props.state === "DRAFT" ? __("Draft") : __("Published")}
</Badge>
);
const variant = {
DRAFT: "neutral",
PENDING_APPROVAL: "warning",
PUBLISHED: "success",
} as const;
const label = {
DRAFT: __("Draft"),
PENDING_APPROVAL: __("Pending approval"),
PUBLISHED: __("Published"),
} as const;
return <Badge variant={variant[props.state]}>{label[props.state]}</Badge>;
}