feat: implement governed cases workspace
This commit is contained in:
@@ -0,0 +1,180 @@
|
||||
import {
|
||||
apiFetch,
|
||||
apiPath,
|
||||
apiReferenceOptionProvider,
|
||||
type ApiSettings,
|
||||
type ReferenceOptionProvider
|
||||
} from "@govoplan/core-webui";
|
||||
|
||||
|
||||
export type InstitutionalReference = {
|
||||
kind: string;
|
||||
owner_module: string;
|
||||
object_id: string;
|
||||
tenant_id: string;
|
||||
version?: string | null;
|
||||
};
|
||||
|
||||
export type EvidenceReference = {
|
||||
kind: string;
|
||||
owner_module: string;
|
||||
evidence_id: string;
|
||||
tenant_id: string;
|
||||
version?: string | null;
|
||||
};
|
||||
|
||||
export type CaseRecord = {
|
||||
reference: InstitutionalReference;
|
||||
revision: number;
|
||||
case_number: string;
|
||||
case_type_key: string;
|
||||
status_key: string;
|
||||
title: string;
|
||||
access_mode: "tenant" | "restricted";
|
||||
access_grants: CaseGrant[];
|
||||
context: Record<string, unknown>;
|
||||
service_ref?: InstitutionalReference | null;
|
||||
party_refs: InstitutionalReference[];
|
||||
assignment_refs: InstitutionalReference[];
|
||||
evidence_refs: EvidenceReference[];
|
||||
decision_refs: InstitutionalReference[];
|
||||
record_refs: InstitutionalReference[];
|
||||
opened_at: string;
|
||||
recorded_at: string;
|
||||
deadline_at?: string | null;
|
||||
closed_at?: string | null;
|
||||
change_reason: string;
|
||||
metadata: Record<string, unknown>;
|
||||
};
|
||||
|
||||
export type CaseGrant = {
|
||||
subject_kind: "account" | "identity" | "group" | "role" | "function" | "function_assignment" | "organization_unit" | "service_account";
|
||||
subject_id: string;
|
||||
permissions: Array<"read" | "update" | "share" | "admin">;
|
||||
};
|
||||
|
||||
export type CaseStatusDefinition = {
|
||||
status_key: string;
|
||||
label: string;
|
||||
category: string;
|
||||
terminal: boolean;
|
||||
sort_order: number;
|
||||
active: boolean;
|
||||
revision: number;
|
||||
};
|
||||
|
||||
export type CaseTypeDefinition = {
|
||||
type_key: string;
|
||||
label: string;
|
||||
description?: string | null;
|
||||
initial_status_key: string;
|
||||
allowed_status_keys: string[];
|
||||
active: boolean;
|
||||
revision: number;
|
||||
};
|
||||
|
||||
export type CaseCatalog = {
|
||||
statuses: CaseStatusDefinition[];
|
||||
types: CaseTypeDefinition[];
|
||||
};
|
||||
|
||||
export type CaseListResponse = {
|
||||
cases: CaseRecord[];
|
||||
total: number;
|
||||
offset: number;
|
||||
limit: number;
|
||||
};
|
||||
|
||||
export type CaseTimelineEntry = {
|
||||
event_id: string;
|
||||
event_type: string;
|
||||
case_revision: number;
|
||||
summary: string;
|
||||
actor_id?: string | null;
|
||||
occurred_at: string;
|
||||
audit_event_id?: string | null;
|
||||
payload: Record<string, unknown>;
|
||||
};
|
||||
|
||||
export function listCases(
|
||||
settings: ApiSettings,
|
||||
options: {
|
||||
query?: string;
|
||||
statuses?: string[];
|
||||
caseTypes?: string[];
|
||||
offset?: number;
|
||||
limit?: number;
|
||||
},
|
||||
signal?: AbortSignal
|
||||
): Promise<CaseListResponse> {
|
||||
return apiFetch<CaseListResponse>(settings, apiPath("/api/v1/cases", {
|
||||
query: options.query,
|
||||
status_key: options.statuses,
|
||||
case_type_key: options.caseTypes,
|
||||
offset: options.offset,
|
||||
limit: options.limit
|
||||
}), { signal });
|
||||
}
|
||||
|
||||
export function getCase(
|
||||
settings: ApiSettings,
|
||||
caseId: string,
|
||||
signal?: AbortSignal
|
||||
): Promise<CaseRecord> {
|
||||
return apiFetch<CaseRecord>(settings, `/api/v1/cases/${encodeURIComponent(caseId)}`, { signal });
|
||||
}
|
||||
|
||||
export function listCaseCatalog(
|
||||
settings: ApiSettings,
|
||||
signal?: AbortSignal
|
||||
): Promise<CaseCatalog> {
|
||||
return apiFetch<CaseCatalog>(settings, "/api/v1/cases/catalog", { signal });
|
||||
}
|
||||
|
||||
export function caseHistory(
|
||||
settings: ApiSettings,
|
||||
caseId: string,
|
||||
signal?: AbortSignal
|
||||
): Promise<{ revisions: CaseRecord[] }> {
|
||||
return apiFetch(settings, `/api/v1/cases/${encodeURIComponent(caseId)}/history`, { signal });
|
||||
}
|
||||
|
||||
export function caseTimeline(
|
||||
settings: ApiSettings,
|
||||
caseId: string,
|
||||
signal?: AbortSignal
|
||||
): Promise<{ entries: CaseTimelineEntry[] }> {
|
||||
return apiFetch(settings, `/api/v1/cases/${encodeURIComponent(caseId)}/timeline`, { signal });
|
||||
}
|
||||
|
||||
export function updateCase(
|
||||
settings: ApiSettings,
|
||||
caseId: string,
|
||||
payload: {
|
||||
expected_revision: number;
|
||||
recorded_at: string;
|
||||
change_reason: string;
|
||||
idempotency_key: string;
|
||||
title?: string;
|
||||
status_key?: string;
|
||||
access_mode?: "tenant" | "restricted";
|
||||
access_grants?: CaseGrant[];
|
||||
}
|
||||
): Promise<CaseRecord> {
|
||||
return apiFetch<CaseRecord>(settings, `/api/v1/cases/${encodeURIComponent(caseId)}`, {
|
||||
method: "PATCH",
|
||||
body: JSON.stringify(payload)
|
||||
});
|
||||
}
|
||||
|
||||
export function caseShareTargetProvider(
|
||||
settings: ApiSettings,
|
||||
caseId: string,
|
||||
targetType: "user" | "group"
|
||||
): ReferenceOptionProvider {
|
||||
return apiReferenceOptionProvider(
|
||||
settings,
|
||||
`/api/v1/cases/${encodeURIComponent(caseId)}/share-target-options`,
|
||||
{ target_type: targetType }
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user