108 lines
2.8 KiB
TypeScript
108 lines
2.8 KiB
TypeScript
import {
|
|
apiFetch,
|
|
apiPath,
|
|
type ApiSettings
|
|
} from "@govoplan/core-webui";
|
|
|
|
|
|
export type ProjectObjectKind = "portfolio" | "project" | "milestone";
|
|
|
|
export type ProjectSubjectRef = {
|
|
kind: string;
|
|
id: string;
|
|
label?: string | null;
|
|
};
|
|
|
|
export type ProjectRecord = {
|
|
tenant_id: string;
|
|
object_kind: ProjectObjectKind;
|
|
object_id: string;
|
|
object_key: string;
|
|
revision: number;
|
|
title: string;
|
|
state: string;
|
|
description?: string | null;
|
|
visibility: "tenant" | "restricted";
|
|
parent_kind?: ProjectObjectKind | null;
|
|
parent_id?: string | null;
|
|
starts_at?: string | null;
|
|
due_at?: string | null;
|
|
recorded_at: string;
|
|
change_reason: string;
|
|
owner?: ProjectSubjectRef | null;
|
|
memberships: Array<Record<string, unknown>>;
|
|
outcomes: Array<{ key: string; title: string; description?: string | null }>;
|
|
benefits: Array<{ key: string; title: string; target?: string | null }>;
|
|
dependencies: Array<Record<string, unknown>>;
|
|
capacity_assumptions: Array<Record<string, unknown>>;
|
|
change_impacts: Array<Record<string, unknown>>;
|
|
benefit_reviews: Array<Record<string, unknown>>;
|
|
resource_links: Array<Record<string, unknown>>;
|
|
external_references: Array<Record<string, unknown>>;
|
|
metadata: Record<string, unknown>;
|
|
};
|
|
|
|
export type ProjectListResponse = {
|
|
objects: ProjectRecord[];
|
|
total: number;
|
|
offset: number;
|
|
limit: number;
|
|
};
|
|
|
|
export function listProjectObjects(
|
|
settings: ApiSettings,
|
|
options: {
|
|
objectKinds?: ProjectObjectKind[];
|
|
states?: string[];
|
|
parentKind?: ProjectObjectKind;
|
|
parentId?: string;
|
|
query?: string;
|
|
offset?: number;
|
|
limit?: number;
|
|
},
|
|
signal?: AbortSignal
|
|
): Promise<ProjectListResponse> {
|
|
return apiFetch(settings, apiPath("/api/v1/projects/objects", {
|
|
object_kind: options.objectKinds,
|
|
state: options.states,
|
|
parent_kind: options.parentKind,
|
|
parent_id: options.parentId,
|
|
query: options.query,
|
|
offset: options.offset,
|
|
limit: options.limit
|
|
}), { signal });
|
|
}
|
|
|
|
export function createProjectObject(
|
|
settings: ApiSettings,
|
|
record: ProjectRecord,
|
|
idempotencyKey: string
|
|
): Promise<ProjectRecord> {
|
|
return apiFetch(settings, "/api/v1/projects/objects", {
|
|
method: "POST",
|
|
body: JSON.stringify({ record, idempotency_key: idempotencyKey })
|
|
});
|
|
}
|
|
|
|
export function updateProjectObject(
|
|
settings: ApiSettings,
|
|
record: ProjectRecord,
|
|
changes: Record<string, unknown>,
|
|
changeReason: string
|
|
): Promise<ProjectRecord> {
|
|
return apiFetch(
|
|
settings,
|
|
`/api/v1/projects/objects/${encodeURIComponent(record.object_kind)}/${encodeURIComponent(record.object_id)}`,
|
|
{
|
|
method: "PATCH",
|
|
body: JSON.stringify({
|
|
expected_revision: record.revision,
|
|
recorded_at: new Date().toISOString(),
|
|
change_reason: changeReason,
|
|
idempotency_key: crypto.randomUUID(),
|
|
changes
|
|
})
|
|
}
|
|
);
|
|
}
|