Rename policy to document

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
Sacha Al Himdani
2025-05-29 19:58:23 -07:00
parent c9f2df3cdd
commit e1b4079e1f
76 changed files with 5572 additions and 4690 deletions

View File

@@ -13,7 +13,7 @@
@import "@radix-ui/colors/orange.css"; @import "@radix-ui/colors/orange.css";
@import "@radix-ui/colors/orange-dark.css"; @import "@radix-ui/colors/orange-dark.css";
@import "./styles/policy-content.css"; @import "./styles/document-content.css";
@plugin 'tailwindcss-animate'; @plugin 'tailwindcss-animate';
@plugin "@tailwindcss/typography"; @plugin "@tailwindcss/typography";

View File

@@ -7,7 +7,7 @@ import { HelmetProvider } from "react-helmet-async";
import { RelayEnvironmentProvider } from "react-relay"; import { RelayEnvironmentProvider } from "react-relay";
import { BrowserRouter, Route, Routes, useLocation } from "react-router"; import { BrowserRouter, Route, Routes, useLocation } from "react-router";
import "./App.css"; import "./App.css";
import "./styles/policy-content.css"; import "./styles/document-content.css";
import ErrorBoundary from "./components/ErrorBoundary"; import ErrorBoundary from "./components/ErrorBoundary";
import AuthLayout from "./layouts/AuthLayout"; import AuthLayout from "./layouts/AuthLayout";
import { RelayEnvironment } from "./RelayEnvironment"; import { RelayEnvironment } from "./RelayEnvironment";
@@ -55,7 +55,7 @@ function App() {
/> />
<Route <Route
path="policies/signing-requests" path="documents/signing-requests"
element={<SigningRequestsPage />} element={<SigningRequestsPage />}
/> />

View File

@@ -1,4 +1,4 @@
.policy-editor-container { .document-editor-container {
border-radius: 0.5rem; border-radius: 0.5rem;
position: relative; position: relative;
line-height: 1.5; line-height: 1.5;
@@ -9,7 +9,7 @@
width: 100%; width: 100%;
} }
.policy-editor { .document-editor {
background: var(--bg-invert-bg); background: var(--bg-invert-bg);
position: relative; position: relative;
border-radius: 0.5rem; border-radius: 0.5rem;
@@ -18,7 +18,7 @@
width: 100%; width: 100%;
} }
.policy-editor-inner { .document-editor-inner {
background: #fff; background: #fff;
position: relative; position: relative;
border-radius: 0 0 0.5rem 0.5rem; border-radius: 0 0 0.5rem 0.5rem;
@@ -26,7 +26,7 @@
min-height: 250px; min-height: 250px;
} }
.policy-editor-input { .document-editor-input {
min-height: 250px; min-height: 250px;
max-height: 500px; max-height: 500px;
resize: none; resize: none;
@@ -41,7 +41,7 @@
color: #000; color: #000;
} }
.policy-editor-placeholder { .document-editor-placeholder {
color: #999; color: #999;
overflow: hidden; overflow: hidden;
position: absolute; position: absolute;
@@ -54,12 +54,12 @@
pointer-events: none; pointer-events: none;
} }
.policy-editor-paragraph { .document-editor-paragraph {
margin: 0 0 15px 0; margin: 0 0 15px 0;
position: relative; position: relative;
} }
.policy-editor .toolbar { .document-editor .toolbar {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
padding: 8px; padding: 8px;
@@ -68,7 +68,7 @@
border-radius: 0.5rem 0.5rem 0 0; border-radius: 0.5rem 0.5rem 0 0;
} }
.policy-editor .toolbar button { .document-editor .toolbar button {
border: 0; border: 0;
display: flex; display: flex;
background: none; background: none;
@@ -80,15 +80,15 @@
justify-content: center; justify-content: center;
} }
.policy-editor .toolbar button:hover { .document-editor .toolbar button:hover {
background-color: rgba(0, 0, 0, 0.05); background-color: rgba(0, 0, 0, 0.05);
} }
.policy-editor .toolbar button.active { .document-editor .toolbar button.active {
background-color: rgba(0, 0, 0, 0.1); background-color: rgba(0, 0, 0, 0.1);
} }
.policy-editor .toolbar .divider { .document-editor .toolbar .divider {
width: 1px; width: 1px;
background-color: hsl(var(--solid-b)); background-color: hsl(var(--solid-b));
margin: 0 8px; margin: 0 8px;

View File

@@ -174,9 +174,9 @@ function getNavItems(organizationId?: string): NavItem[] {
icon: Store, icon: Store,
}, },
{ {
title: "Policies", title: "Documents",
url: organizationId url: organizationId
? `/organizations/${organizationId}/policies` ? `/organizations/${organizationId}/documents`
: undefined, : undefined,
icon: FileText, icon: FileText,
}, },

View File

@@ -17,7 +17,7 @@ import remarkGfm from "remark-gfm";
import rehypeRaw from 'rehype-raw'; import rehypeRaw from 'rehype-raw';
type Document = { type Document = {
policy_version_id: string; document_version_id: string;
title: string; title: string;
content: string; content: string;
signed?: boolean; signed?: boolean;
@@ -49,7 +49,7 @@ export default function SigningRequestsPage() {
async function fetchDocuments() { async function fetchDocuments() {
try { try {
const response = await fetch( const response = await fetch(
buildEndpoint("/api/console/v1/policies/signing-requests"), buildEndpoint("/api/console/v1/documents/signing-requests"),
{ {
method: "GET", method: "GET",
headers: { headers: {
@@ -96,7 +96,7 @@ export default function SigningRequestsPage() {
try { try {
const response = await fetch( const response = await fetch(
buildEndpoint( buildEndpoint(
`/api/console/v1/policies/signing-requests/${docToSign.policy_version_id}/sign`, `/api/console/v1/documents/signing-requests/${docToSign.document_version_id}/sign`,
), ),
{ {
method: "POST", method: "POST",

View File

@@ -13,7 +13,7 @@ import { NavLink, Outlet, Route, Routes, To, useParams } from "react-router";
import { OrganizationBreadcrumbBreadcrumbFrameworkOverviewQuery } from "./__generated__/OrganizationBreadcrumbBreadcrumbFrameworkOverviewQuery.graphql"; import { OrganizationBreadcrumbBreadcrumbFrameworkOverviewQuery } from "./__generated__/OrganizationBreadcrumbBreadcrumbFrameworkOverviewQuery.graphql";
import { OrganizationBreadcrumbBreadcrumbPeopleOverviewQuery } from "./__generated__/OrganizationBreadcrumbBreadcrumbPeopleOverviewQuery.graphql"; import { OrganizationBreadcrumbBreadcrumbPeopleOverviewQuery } from "./__generated__/OrganizationBreadcrumbBreadcrumbPeopleOverviewQuery.graphql";
import { OrganizationBreadcrumbBreadcrumbPolicyOverviewQuery } from "./__generated__/OrganizationBreadcrumbBreadcrumbPolicyOverviewQuery.graphql"; import { OrganizationBreadcrumbBreadcrumbDocumentOverviewQuery } from "./__generated__/OrganizationBreadcrumbBreadcrumbDocumentOverviewQuery.graphql";
import { OrganizationBreadcrumbBreadcrumbVendorOverviewQuery } from "./__generated__/OrganizationBreadcrumbBreadcrumbVendorOverviewQuery.graphql"; import { OrganizationBreadcrumbBreadcrumbVendorOverviewQuery } from "./__generated__/OrganizationBreadcrumbBreadcrumbVendorOverviewQuery.graphql";
import { OrganizationBreadcrumbOrganizationQuery } from "./__generated__/OrganizationBreadcrumbOrganizationQuery.graphql"; import { OrganizationBreadcrumbOrganizationQuery } from "./__generated__/OrganizationBreadcrumbOrganizationQuery.graphql";
import { OrganizationBreadcrumbBreadcrumbMeasureViewQuery } from "./__generated__/OrganizationBreadcrumbBreadcrumbMeasureViewQuery.graphql"; import { OrganizationBreadcrumbBreadcrumbMeasureViewQuery } from "./__generated__/OrganizationBreadcrumbBreadcrumbMeasureViewQuery.graphql";
@@ -264,14 +264,14 @@ function BreadcrumbPeopleOverview() {
); );
} }
function BreadcrumbPolicyList() { function BreadcrumbDocumentList() {
const { organizationId } = useParams(); const { organizationId } = useParams();
return ( return (
<> <>
<BreadcrumbSeparator /> <BreadcrumbSeparator />
<BreadcrumbItem> <BreadcrumbItem>
<BreadcrumbNavLink to={`/organizations/${organizationId}/policies`}> <BreadcrumbNavLink to={`/organizations/${organizationId}/documents`}>
Policies Documents
</BreadcrumbNavLink> </BreadcrumbNavLink>
</BreadcrumbItem> </BreadcrumbItem>
<Outlet /> <Outlet />
@@ -279,23 +279,23 @@ function BreadcrumbPolicyList() {
); );
} }
function BreadcrumbPolicyOverview() { function BreadcrumbDocumentOverview() {
const { organizationId, policyId } = useParams(); const { organizationId, documentId } = useParams();
const data = const data =
useLazyLoadQuery<OrganizationBreadcrumbBreadcrumbPolicyOverviewQuery>( useLazyLoadQuery<OrganizationBreadcrumbBreadcrumbDocumentOverviewQuery>(
graphql` graphql`
query OrganizationBreadcrumbBreadcrumbPolicyOverviewQuery( query OrganizationBreadcrumbBreadcrumbDocumentOverviewQuery(
$policyId: ID! $documentId: ID!
) { ) {
policy: node(id: $policyId) { document: node(id: $documentId) {
id id
... on Policy { ... on Document {
title title
} }
} }
} }
`, `,
{ policyId: policyId! }, { documentId: documentId! },
{ fetchPolicy: "store-or-network" }, { fetchPolicy: "store-or-network" },
); );
@@ -304,9 +304,9 @@ function BreadcrumbPolicyOverview() {
<BreadcrumbSeparator /> <BreadcrumbSeparator />
<BreadcrumbItem> <BreadcrumbItem>
<BreadcrumbNavLink <BreadcrumbNavLink
to={`/organizations/${organizationId}/policies/${policyId}`} to={`/organizations/${organizationId}/documents/${documentId}`}
> >
{data.policy?.title} {data.document?.title}
</BreadcrumbNavLink> </BreadcrumbNavLink>
</BreadcrumbItem> </BreadcrumbItem>
<Outlet /> <Outlet />
@@ -531,12 +531,12 @@ export function BreadCrumb() {
} }
/> />
</Route> </Route>
<Route path="policies" element={<BreadcrumbPolicyList />}> <Route path="documents" element={<BreadcrumbDocumentList />}>
<Route <Route
path=":policyId" path=":documentId"
element={ element={
<Suspense> <Suspense>
<BreadcrumbPolicyOverview /> <BreadcrumbDocumentOverview />
</Suspense> </Suspense>
} }
> >

View File

@@ -18,9 +18,9 @@ import { NewMeasurePage } from "./measures/NewMeasurePage";
import { NewPeoplePage } from "./people/NewPeoplePage"; import { NewPeoplePage } from "./people/NewPeoplePage";
import { PeopleListPage } from "./people/PeopleListPage"; import { PeopleListPage } from "./people/PeopleListPage";
import { PeoplePage } from "./people/PeoplePage"; import { PeoplePage } from "./people/PeoplePage";
import { EditPolicyPage } from "./policies/EditPolicyPage"; import { EditDocumentPage } from "./documents/EditDocumentPage";
import { PolicyListPage } from "./policies/PolicyListPage"; import { DocumentListPage } from "./documents/DocumentListPage";
import { ShowPolicyPage } from "./policies/ShowPolicyPage"; import { ShowDocumentPage } from "./documents/ShowDocumentPage";
import { EditRiskPage } from "./risks/EditRiskPage"; import { EditRiskPage } from "./risks/EditRiskPage";
import { NewRiskPage } from "./risks/NewRiskPage"; import { NewRiskPage } from "./risks/NewRiskPage";
import { ListRiskPage } from "./risks/ListRiskPage"; import { ListRiskPage } from "./risks/ListRiskPage";
@@ -54,11 +54,11 @@ export function OrganizationsRoutes() {
<Route path="measures/:measureId" element={<MeasurePage />} /> <Route path="measures/:measureId" element={<MeasurePage />} />
<Route path="measures/:measureId/edit" element={<EditMeasurePage />} /> <Route path="measures/:measureId/edit" element={<EditMeasurePage />} />
<Route path="vendors/:vendorId" element={<VendorPage />} /> <Route path="vendors/:vendorId" element={<VendorPage />} />
<Route path="policies" element={<PolicyListPage />} /> <Route path="documents" element={<DocumentListPage />} />
<Route path="policies/:policyId" element={<ShowPolicyPage />} /> <Route path="documents/:documentId" element={<ShowDocumentPage />} />
<Route <Route
path="policies/:policyId/versions/:versionId/edit" path="documents/:documentId/versions/:versionId/edit"
element={<EditPolicyPage />} element={<EditDocumentPage />}
/> />
<Route path="risks" element={<ListRiskPage />} /> <Route path="risks" element={<ListRiskPage />} />
<Route path="risks/new" element={<NewRiskPage />} /> <Route path="risks/new" element={<NewRiskPage />} />

View File

@@ -1,5 +1,5 @@
/** /**
* @generated SignedSource<<ca410ce7df7231383e55d134d37916bd>> * @generated SignedSource<<2cac1fe037796fc1b9542c9388ed930d>>
* @lightSyntaxTransform * @lightSyntaxTransform
* @nogrep * @nogrep
*/ */
@@ -9,18 +9,18 @@
// @ts-nocheck // @ts-nocheck
import { ConcreteRequest } from 'relay-runtime'; import { ConcreteRequest } from 'relay-runtime';
export type OrganizationBreadcrumbBreadcrumbPolicyOverviewQuery$variables = { export type OrganizationBreadcrumbBreadcrumbDocumentOverviewQuery$variables = {
policyId: string; documentId: string;
}; };
export type OrganizationBreadcrumbBreadcrumbPolicyOverviewQuery$data = { export type OrganizationBreadcrumbBreadcrumbDocumentOverviewQuery$data = {
readonly policy: { readonly document: {
readonly id: string; readonly id: string;
readonly title?: string; readonly title?: string;
}; };
}; };
export type OrganizationBreadcrumbBreadcrumbPolicyOverviewQuery = { export type OrganizationBreadcrumbBreadcrumbDocumentOverviewQuery = {
response: OrganizationBreadcrumbBreadcrumbPolicyOverviewQuery$data; response: OrganizationBreadcrumbBreadcrumbDocumentOverviewQuery$data;
variables: OrganizationBreadcrumbBreadcrumbPolicyOverviewQuery$variables; variables: OrganizationBreadcrumbBreadcrumbDocumentOverviewQuery$variables;
}; };
const node: ConcreteRequest = (function(){ const node: ConcreteRequest = (function(){
@@ -28,14 +28,14 @@ var v0 = [
{ {
"defaultValue": null, "defaultValue": null,
"kind": "LocalArgument", "kind": "LocalArgument",
"name": "policyId" "name": "documentId"
} }
], ],
v1 = [ v1 = [
{ {
"kind": "Variable", "kind": "Variable",
"name": "id", "name": "id",
"variableName": "policyId" "variableName": "documentId"
} }
], ],
v2 = { v2 = {
@@ -56,7 +56,7 @@ v3 = {
"storageKey": null "storageKey": null
} }
], ],
"type": "Policy", "type": "Document",
"abstractKey": null "abstractKey": null
}; };
return { return {
@@ -64,10 +64,10 @@ return {
"argumentDefinitions": (v0/*: any*/), "argumentDefinitions": (v0/*: any*/),
"kind": "Fragment", "kind": "Fragment",
"metadata": null, "metadata": null,
"name": "OrganizationBreadcrumbBreadcrumbPolicyOverviewQuery", "name": "OrganizationBreadcrumbBreadcrumbDocumentOverviewQuery",
"selections": [ "selections": [
{ {
"alias": "policy", "alias": "document",
"args": (v1/*: any*/), "args": (v1/*: any*/),
"concreteType": null, "concreteType": null,
"kind": "LinkedField", "kind": "LinkedField",
@@ -87,10 +87,10 @@ return {
"operation": { "operation": {
"argumentDefinitions": (v0/*: any*/), "argumentDefinitions": (v0/*: any*/),
"kind": "Operation", "kind": "Operation",
"name": "OrganizationBreadcrumbBreadcrumbPolicyOverviewQuery", "name": "OrganizationBreadcrumbBreadcrumbDocumentOverviewQuery",
"selections": [ "selections": [
{ {
"alias": "policy", "alias": "document",
"args": (v1/*: any*/), "args": (v1/*: any*/),
"concreteType": null, "concreteType": null,
"kind": "LinkedField", "kind": "LinkedField",
@@ -112,16 +112,16 @@ return {
] ]
}, },
"params": { "params": {
"cacheID": "bc0b04bbe75c94660de230461532773a", "cacheID": "bf577e8122cd59894e36f951f7a3551a",
"id": null, "id": null,
"metadata": {}, "metadata": {},
"name": "OrganizationBreadcrumbBreadcrumbPolicyOverviewQuery", "name": "OrganizationBreadcrumbBreadcrumbDocumentOverviewQuery",
"operationKind": "query", "operationKind": "query",
"text": "query OrganizationBreadcrumbBreadcrumbPolicyOverviewQuery(\n $policyId: ID!\n) {\n policy: node(id: $policyId) {\n __typename\n id\n ... on Policy {\n title\n }\n }\n}\n" "text": "query OrganizationBreadcrumbBreadcrumbDocumentOverviewQuery(\n $documentId: ID!\n) {\n document: node(id: $documentId) {\n __typename\n id\n ... on Document {\n title\n }\n }\n}\n"
} }
}; };
})(); })();
(node as any).hash = "ced380d1e6eb1c31ecc5f2dc9096133b"; (node as any).hash = "7ef8052c69e997cf2252d7c00b3f1c1f";
export default node; export default node;

View File

@@ -5,13 +5,13 @@ import { useLocation } from "react-router";
import { ErrorBoundaryWithLocation } from "../ErrorBoundary"; import { ErrorBoundaryWithLocation } from "../ErrorBoundary";
import { lazy } from "@probo/react-lazy"; import { lazy } from "@probo/react-lazy";
const PolicyListView = lazy(() => import("./PolicyListView")); const DocumentListView = lazy(() => import("./DocumentListView"));
export function PolicyListViewSkeleton() { export function DocumentListViewSkeleton() {
return ( return (
<PageTemplateSkeleton <PageTemplateSkeleton
title="Policies" title="Documents"
description="Manage your organization's policies" description="Manage your organization's documents"
actions={ actions={
<div className="bg-subtle-bg animate-pulse h-9 w-1/6 rounded-lg" /> <div className="bg-subtle-bg animate-pulse h-9 w-1/6 rounded-lg" />
} }
@@ -28,7 +28,7 @@ export function PolicyListViewSkeleton() {
{/* Results summary skeleton */} {/* Results summary skeleton */}
<div className="mb-4 h-4 w-48 bg-subtle-bg animate-pulse rounded" /> <div className="mb-4 h-4 w-48 bg-subtle-bg animate-pulse rounded" />
{/* Policy grid skeleton */} {/* Document grid skeleton */}
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3"> <div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
{[1, 2, 3, 4, 5, 6].map((i) => ( {[1, 2, 3, 4, 5, 6].map((i) => (
<Card key={i} className="bg-level-1/50 h-full flex flex-col"> <Card key={i} className="bg-level-1/50 h-full flex flex-col">
@@ -60,13 +60,13 @@ export function PolicyListViewSkeleton() {
); );
} }
export function PolicyListPage() { export function DocumentListPage() {
const location = useLocation(); const location = useLocation();
return ( return (
<Suspense key={location.pathname} fallback={<PolicyListViewSkeleton />}> <Suspense key={location.pathname} fallback={<DocumentListViewSkeleton />}>
<ErrorBoundaryWithLocation> <ErrorBoundaryWithLocation>
<PolicyListView /> <DocumentListView />
</ErrorBoundaryWithLocation> </ErrorBoundaryWithLocation>
</Suspense> </Suspense>
); );

View File

@@ -27,14 +27,14 @@ import {
import { useToast } from "@/hooks/use-toast"; import { useToast } from "@/hooks/use-toast";
import { format } from "date-fns"; import { format } from "date-fns";
import type { import type {
PolicyListViewQuery, DocumentListViewQuery,
PolicyListViewQuery$data, DocumentListViewQuery$data,
} from "./__generated__/PolicyListViewQuery.graphql"; } from "./__generated__/DocumentListViewQuery.graphql";
import type { PolicyListViewDeleteMutation } from "./__generated__/PolicyListViewDeleteMutation.graphql"; import type { DocumentListViewDeleteMutation } from "./__generated__/DocumentListViewDeleteMutation.graphql";
import type { PolicyListViewCreateMutation } from "./__generated__/PolicyListViewCreateMutation.graphql"; import type { DocumentListViewCreateMutation } from "./__generated__/DocumentListViewCreateMutation.graphql";
import type { PolicyListViewSendSigningNotificationsMutation } from "./__generated__/PolicyListViewSendSigningNotificationsMutation.graphql"; import type { DocumentListViewSendSigningNotificationsMutation } from "./__generated__/DocumentListViewSendSigningNotificationsMutation.graphql";
import { PageTemplate } from "@/components/PageTemplate"; import { PageTemplate } from "@/components/PageTemplate";
import { PolicyListViewSkeleton } from "./PolicyListPage"; import { DocumentListViewSkeleton } from "./DocumentListPage";
import { import {
Dialog, Dialog,
DialogContent, DialogContent,
@@ -46,8 +46,8 @@ import PeopleSelector from "@/components/PeopleSelector";
import type { PeopleSelector_organization$key } from "@/components/__generated__/PeopleSelector_organization.graphql"; import type { PeopleSelector_organization$key } from "@/components/__generated__/PeopleSelector_organization.graphql";
import { Textarea } from "@/components/ui/textarea"; import { Textarea } from "@/components/ui/textarea";
const policyListViewQuery = graphql` const documentListViewQuery = graphql`
query PolicyListViewQuery($organizationId: ID!) { query DocumentListViewQuery($organizationId: ID!) {
viewer { viewer {
user { user {
id id
@@ -57,8 +57,8 @@ const policyListViewQuery = graphql`
organization: node(id: $organizationId) { organization: node(id: $organizationId) {
... on Organization { ... on Organization {
...PeopleSelector_organization ...PeopleSelector_organization
policies(first: 50, orderBy: { field: TITLE, direction: ASC }) documents(first: 50, orderBy: { field: TITLE, direction: ASC })
@connection(key: "PolicyListView_policies") { @connection(key: "DocumentListView_documents") {
edges { edges {
node { node {
id id
@@ -96,24 +96,24 @@ const policyListViewQuery = graphql`
} }
`; `;
const DeletePolicyMutation = graphql` const DeleteDocumentMutation = graphql`
mutation PolicyListViewDeleteMutation( mutation DocumentListViewDeleteMutation(
$input: DeletePolicyInput! $input: DeleteDocumentInput!
$connections: [ID!]! $connections: [ID!]!
) { ) {
deletePolicy(input: $input) { deleteDocument(input: $input) {
deletedPolicyId @deleteEdge(connections: $connections) deletedDocumentId @deleteEdge(connections: $connections)
} }
} }
`; `;
const createPolicyMutation = graphql` const createDocumentMutation = graphql`
mutation PolicyListViewCreateMutation( mutation DocumentListViewCreateMutation(
$input: CreatePolicyInput! $input: CreateDocumentInput!
$connections: [ID!]! $connections: [ID!]!
) { ) {
createPolicy(input: $input) { createDocument(input: $input) {
policyEdge @prependEdge(connections: $connections) { documentEdge @prependEdge(connections: $connections) {
node { node {
id id
title title
@@ -131,7 +131,7 @@ const createPolicyMutation = graphql`
`; `;
const sendSigningNotificationsMutation = graphql` const sendSigningNotificationsMutation = graphql`
mutation PolicyListViewSendSigningNotificationsMutation( mutation DocumentListViewSendSigningNotificationsMutation(
$input: SendSigningNotificationsInput! $input: SendSigningNotificationsInput!
) { ) {
sendSigningNotifications(input: $input) { sendSigningNotifications(input: $input) {
@@ -139,21 +139,21 @@ const sendSigningNotificationsMutation = graphql`
} }
} }
`; `;
function PolicyTableRow({ function DocumentTableRow({
policy, document,
organizationId, organizationId,
}: { }: {
policy: NonNullable< document: NonNullable<
PolicyListViewQuery$data["organization"]["policies"] DocumentListViewQuery$data["organization"]["documents"]
>["edges"][0]["node"]; >["edges"][0]["node"];
organizationId: string; organizationId: string;
}) { }) {
const navigate = useNavigate(); const navigate = useNavigate();
const { toast } = useToast(); const { toast } = useToast();
const [deletePolicy, isDeleting] = const [deleteDocument, isDeleting] =
useMutation<PolicyListViewDeleteMutation>(DeletePolicyMutation); useMutation<DocumentListViewDeleteMutation>(DeleteDocumentMutation);
const latestVersion = policy.versions?.edges[0]?.node; const latestVersion = document.versions?.edges[0]?.node;
const status = latestVersion?.status || "DRAFT"; const status = latestVersion?.status || "DRAFT";
// Get signature counts // Get signature counts
@@ -163,45 +163,45 @@ function PolicyTableRow({
(edge) => edge?.node?.state === "SIGNED", (edge) => edge?.node?.state === "SIGNED",
).length; ).length;
const handleDeletePolicy = (e: React.MouseEvent) => { const handleDeleteDocument = (e: React.MouseEvent) => {
e.stopPropagation(); e.stopPropagation();
if ( if (
window.confirm( window.confirm(
"Are you sure you want to delete this policy? This action cannot be undone.", "Are you sure you want to delete this document? This action cannot be undone.",
) )
) { ) {
deletePolicy({ deleteDocument({
variables: { variables: {
input: { input: {
policyId: policy.id, documentId: document.id,
}, },
connections: [ connections: [
ConnectionHandler.getConnectionID( ConnectionHandler.getConnectionID(
organizationId, organizationId,
"PolicyListView_policies", "DocumentListView_documents",
), ),
], ],
}, },
onCompleted: (_, errors) => { onCompleted: (_, errors) => {
if (errors) { if (errors) {
console.error("Error deleting policy:", errors); console.error("Error deleting document:", errors);
toast({ toast({
title: "Error", title: "Error",
description: "Failed to delete policy. Please try again.", description: "Failed to delete document. Please try again.",
variant: "destructive", variant: "destructive",
}); });
return; return;
} }
toast({ toast({
title: "Success", title: "Success",
description: "Policy deleted successfully.", description: "Document deleted successfully.",
}); });
}, },
onError: (error) => { onError: (error) => {
console.error("Error deleting policy:", error); console.error("Error deleting document:", error);
toast({ toast({
title: "Error", title: "Error",
description: "Failed to delete policy. Please try again.", description: "Failed to delete document. Please try again.",
variant: "destructive", variant: "destructive",
}); });
}, },
@@ -211,32 +211,32 @@ function PolicyTableRow({
const handleView = (e: React.MouseEvent) => { const handleView = (e: React.MouseEvent) => {
e.stopPropagation(); e.stopPropagation();
navigate(`/organizations/${organizationId}/policies/${policy.id}`); navigate(`/organizations/${organizationId}/documents/${document.id}`);
}; };
return ( return (
<tr <tr
className="border-t border-solid-b hover:bg-subtle-bg cursor-pointer" className="border-t border-solid-b hover:bg-subtle-bg cursor-pointer"
onClick={() => { onClick={() => {
navigate(`/organizations/${organizationId}/policies/${policy.id}`); navigate(`/organizations/${organizationId}/documents/${document.id}`);
}} }}
> >
<td className="py-4 px-6"> <td className="py-4 px-6">
<div className="flex flex-col"> <div className="flex flex-col">
<span className="font-medium text-primary">{policy.title}</span> <span className="font-medium text-primary">{document.title}</span>
<span className="text-sm text-tertiary"> <span className="text-sm text-tertiary">
{policy.description || "No description provided"} {document.description || "No description provided"}
</span> </span>
</div> </div>
</td> </td>
<td className="py-4 px-6"> <td className="py-4 px-6">
<span className="text-sm text-primary"> <span className="text-sm text-primary">
{policy.owner?.fullName || "Unassigned"} {document.owner?.fullName || "Unassigned"}
</span> </span>
</td> </td>
<td className="py-4 px-6"> <td className="py-4 px-6">
<span className="text-sm text-primary"> <span className="text-sm text-primary">
{format(new Date(policy.updatedAt), "MMM d, yyyy")} {format(new Date(document.updatedAt), "MMM d, yyyy")}
</span> </span>
</td> </td>
<td className="py-4 px-6"> <td className="py-4 px-6">
@@ -277,7 +277,7 @@ function PolicyTableRow({
View View
</DropdownMenuItem> </DropdownMenuItem>
<DropdownMenuItem <DropdownMenuItem
onClick={handleDeletePolicy} onClick={handleDeleteDocument}
className="text-danger focus:text-danger focus:bg-danger-bg" className="text-danger focus:text-danger focus:bg-danger-bg"
disabled={isDeleting} disabled={isDeleting}
> >
@@ -291,7 +291,7 @@ function PolicyTableRow({
); );
} }
function CreatePolicyModal({ function CreateDocumentModal({
open, open,
onOpenChange, onOpenChange,
organizationId, organizationId,
@@ -307,8 +307,8 @@ function CreatePolicyModal({
const [content, setContent] = useState(""); const [content, setContent] = useState("");
const [ownerId, setOwnerId] = useState<string | null>(null); const [ownerId, setOwnerId] = useState<string | null>(null);
const [createPolicy, isCreating] = const [createDocument, isCreating] =
useMutation<PolicyListViewCreateMutation>(createPolicyMutation); useMutation<DocumentListViewCreateMutation>(createDocumentMutation);
// Reset form fields // Reset form fields
const resetForm = () => { const resetForm = () => {
@@ -317,11 +317,11 @@ function CreatePolicyModal({
setOwnerId(null); setOwnerId(null);
}; };
const handleCreatePolicy = () => { const handleCreateDocument = () => {
if (!title.trim()) { if (!title.trim()) {
toast({ toast({
title: "Error", title: "Error",
description: "Please enter a policy title.", description: "Please enter a document title.",
variant: "destructive", variant: "destructive",
}); });
return; return;
@@ -330,7 +330,7 @@ function CreatePolicyModal({
if (!ownerId) { if (!ownerId) {
toast({ toast({
title: "Error", title: "Error",
description: "Please select an owner for the policy.", description: "Please select an owner for the document.",
variant: "destructive", variant: "destructive",
}); });
return; return;
@@ -343,23 +343,23 @@ function CreatePolicyModal({
ownerId, ownerId,
}; };
createPolicy({ createDocument({
variables: { variables: {
input, input,
connections: [ connections: [
ConnectionHandler.getConnectionID( ConnectionHandler.getConnectionID(
organizationId, organizationId,
"PolicyListView_policies", "DocumentListView_documents",
{ orderBy: { field: "TITLE", direction: "ASC" } }, { orderBy: { field: "TITLE", direction: "ASC" } },
), ),
], ],
}, },
onCompleted: (response, errors) => { onCompleted: (response, errors) => {
if (errors) { if (errors) {
console.error("Error creating policy:", errors); console.error("Error creating document:", errors);
toast({ toast({
title: "Error", title: "Error",
description: "Failed to create policy. Please try again.", description: "Failed to create document. Please try again.",
variant: "destructive", variant: "destructive",
}); });
return; return;
@@ -367,17 +367,17 @@ function CreatePolicyModal({
toast({ toast({
title: "Success", title: "Success",
description: "Policy created successfully!", description: "Document created successfully!",
}); });
resetForm(); resetForm();
onOpenChange(false); onOpenChange(false);
}, },
onError: (error) => { onError: (error) => {
console.error("Error creating policy:", error); console.error("Error creating document:", error);
toast({ toast({
title: "Error", title: "Error",
description: "Failed to create policy. Please try again.", description: "Failed to create document. Please try again.",
variant: "destructive", variant: "destructive",
}); });
}, },
@@ -394,16 +394,16 @@ function CreatePolicyModal({
return ( return (
<Dialog open={open} onOpenChange={onOpenChange}> <Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="sm:max-w-[1080px] h-[700px] max-h-[700px] p-0 gap-0 flex flex-col"> <DialogContent className="sm:max-w-[1080px] h-[700px] max-h-[700px] p-0 gap-0 flex flex-col">
<DialogTitle className="sr-only">Create new policy</DialogTitle> <DialogTitle className="sr-only">Create new document</DialogTitle>
<DialogDescription className="sr-only"> <DialogDescription className="sr-only">
Form to create a new policy with title, content, and owner Form to create a new document with title, content, and owner
information. information.
</DialogDescription> </DialogDescription>
<div className="flex justify-between items-center py-2 px-4 border-b border-solid-b h-[40px]"> <div className="flex justify-between items-center py-2 px-4 border-b border-solid-b h-[40px]">
<div className="flex items-center gap-1 text-sm"> <div className="flex items-center gap-1 text-sm">
<span className="text-tertiary">Policies</span> <span className="text-tertiary">Documents</span>
<ChevronDown className="h-3 w-3 text-quaternary rotate-[270deg]" /> <ChevronDown className="h-3 w-3 text-quaternary rotate-[270deg]" />
<span className="font-medium">New policy</span> <span className="font-medium">New document</span>
</div> </div>
</div> </div>
@@ -425,25 +425,25 @@ function CreatePolicyModal({
} }
}} }}
onFocus={(e) => { onFocus={(e) => {
if (e.currentTarget.textContent === "Enter policy title...") { if (e.currentTarget.textContent === "Enter document title...") {
e.currentTarget.textContent = ""; e.currentTarget.textContent = "";
} }
}} }}
onBlur={(e) => { onBlur={(e) => {
if (!e.currentTarget.textContent?.trim()) { if (!e.currentTarget.textContent?.trim()) {
e.currentTarget.textContent = "Enter policy title..."; e.currentTarget.textContent = "Enter document title...";
setTitle(""); setTitle("");
} }
}} }}
ref={(el) => { ref={(el) => {
if (el && !el.textContent) { if (el && !el.textContent) {
el.textContent = title || "Enter policy title..."; el.textContent = title || "Enter document title...";
} }
}} }}
></h1> ></h1>
</div> </div>
<Textarea <Textarea
placeholder="This Privacy Policy outlines how NovaSoft collects, uses, and protects personal information provided by users of its services. By accessing or using our platform, you agree to the collection and use of information in accordance with this policy..." placeholder="This Privacy Document outlines how NovaSoft collects, uses, and protects personal information provided by users of its services. By accessing or using our platform, you agree to the collection and use of information in accordance with this document..."
className="min-h-[300px] border-none resize-none p-0 focus-visible:ring-0 focus-visible:ring-offset-0" className="min-h-[300px] border-none resize-none p-0 focus-visible:ring-0 focus-visible:ring-offset-0"
value={content} value={content}
onChange={(e) => setContent(e.target.value)} onChange={(e) => setContent(e.target.value)}
@@ -499,11 +499,11 @@ function CreatePolicyModal({
Cancel Cancel
</Button> </Button>
<Button <Button
onClick={handleCreatePolicy} onClick={handleCreateDocument}
disabled={isCreating} disabled={isCreating}
className="h-9" className="h-9"
> >
{isCreating ? "Creating..." : "Create policy"} {isCreating ? "Creating..." : "Create document"}
</Button> </Button>
</DialogFooter> </DialogFooter>
</DialogContent> </DialogContent>
@@ -511,24 +511,24 @@ function CreatePolicyModal({
); );
} }
function PolicyListViewContent({ function DocumentListViewContent({
queryRef, queryRef,
}: { }: {
queryRef: PreloadedQuery<PolicyListViewQuery>; queryRef: PreloadedQuery<DocumentListViewQuery>;
}) { }) {
const data = usePreloadedQuery<PolicyListViewQuery>( const data = usePreloadedQuery<DocumentListViewQuery>(
policyListViewQuery, documentListViewQuery,
queryRef, queryRef,
); );
const { organizationId } = useParams(); const { organizationId } = useParams();
const policies = const documents =
data.organization?.policies?.edges.map((edge) => edge?.node) ?? []; data.organization?.documents?.edges.map((edge) => edge?.node) ?? [];
const [createModalOpen, setCreateModalOpen] = useState(false); const [createModalOpen, setCreateModalOpen] = useState(false);
const [confirmSigningModalOpen, setConfirmSigningModalOpen] = useState(false); const [confirmSigningModalOpen, setConfirmSigningModalOpen] = useState(false);
const [sendSigningNotifications, isSendingNotifications] = const [sendSigningNotifications, isSendingNotifications] =
useMutation<PolicyListViewSendSigningNotificationsMutation>( useMutation<DocumentListViewSendSigningNotificationsMutation>(
sendSigningNotificationsMutation, sendSigningNotificationsMutation,
); );
const { toast } = useToast(); const { toast } = useToast();
@@ -580,12 +580,12 @@ function PolicyListViewContent({
return ( return (
<PageTemplate <PageTemplate
title="Policies" title="Documents"
actions={ actions={
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<Button onClick={handleOpenModal}> <Button onClick={handleOpenModal}>
<Plus className="mr-2 h-4 w-4" /> <Plus className="mr-2 h-4 w-4" />
New policy New document
</Button> </Button>
<Button onClick={() => setConfirmSigningModalOpen(true)}> <Button onClick={() => setConfirmSigningModalOpen(true)}>
Send signing notifications Send signing notifications
@@ -593,14 +593,14 @@ function PolicyListViewContent({
</div> </div>
} }
> >
{/* Policy table */} {/* Document table */}
<div className="rounded-lg border border-solid-b overflow-hidden bg-level-1"> <div className="rounded-lg border border-solid-b overflow-hidden bg-level-1">
<table className="w-full"> <table className="w-full">
<thead> <thead>
<tr className="bg-level-1 text-left"> <tr className="bg-level-1 text-left">
<th className="py-3 px-6 text-xs font-medium text-tertiary border-b border-low-b"> <th className="py-3 px-6 text-xs font-medium text-tertiary border-b border-low-b">
<div className="flex items-center gap-1"> <div className="flex items-center gap-1">
Policy Document
<ChevronDown className="h-3 w-3 text-quaternary" /> <ChevronDown className="h-3 w-3 text-quaternary" />
</div> </div>
</th> </th>
@@ -632,11 +632,11 @@ function PolicyListViewContent({
</tr> </tr>
</thead> </thead>
<tbody className="bg-level-1"> <tbody className="bg-level-1">
{policies.length > 0 ? ( {documents.length > 0 ? (
policies.map((policy: any) => ( documents.map((document: any) => (
<PolicyTableRow <DocumentTableRow
key={policy.id} key={document.id}
policy={policy} document={document}
organizationId={organizationId!} organizationId={organizationId!}
/> />
)) ))
@@ -644,13 +644,13 @@ function PolicyListViewContent({
<tr> <tr>
<td colSpan={6} className="py-12 text-center"> <td colSpan={6} className="py-12 text-center">
<div className="flex flex-col items-center gap-2"> <div className="flex flex-col items-center gap-2">
<h3 className="text-lg font-medium">No policies found</h3> <h3 className="text-lg font-medium">No documents found</h3>
<p className="text-tertiary"> <p className="text-tertiary">
Create your first policy to get started Create your first document to get started
</p> </p>
<Button onClick={handleOpenModal}> <Button onClick={handleOpenModal}>
<Plus className="mr-2 h-4 w-4" /> <Plus className="mr-2 h-4 w-4" />
Create policy Create document
</Button> </Button>
</div> </div>
</td> </td>
@@ -660,7 +660,7 @@ function PolicyListViewContent({
</table> </table>
</div> </div>
<CreatePolicyModal <CreateDocumentModal
open={createModalOpen} open={createModalOpen}
onOpenChange={handleCloseModal} onOpenChange={handleCloseModal}
organizationId={organizationId!} organizationId={organizationId!}
@@ -676,7 +676,7 @@ function PolicyListViewContent({
<DialogTitle>Send Signing Notifications</DialogTitle> <DialogTitle>Send Signing Notifications</DialogTitle>
<DialogDescription> <DialogDescription>
This will send signing notifications to all users who have pending This will send signing notifications to all users who have pending
policies to sign. Are you sure you want to continue? documents to sign. Are you sure you want to continue?
</DialogDescription> </DialogDescription>
<DialogFooter className="gap-2 mt-4"> <DialogFooter className="gap-2 mt-4">
<Button <Button
@@ -698,9 +698,9 @@ function PolicyListViewContent({
); );
} }
export default function PolicyListView() { export default function DocumentListView() {
const [queryRef, loadQuery] = const [queryRef, loadQuery] =
useQueryLoader<PolicyListViewQuery>(policyListViewQuery); useQueryLoader<DocumentListViewQuery>(documentListViewQuery);
const { organizationId } = useParams(); const { organizationId } = useParams();
@@ -709,12 +709,12 @@ export default function PolicyListView() {
}, [loadQuery, organizationId]); }, [loadQuery, organizationId]);
if (!queryRef) { if (!queryRef) {
return <PolicyListViewSkeleton />; return <DocumentListViewSkeleton />;
} }
return ( return (
<Suspense fallback={<PolicyListViewSkeleton />}> <Suspense fallback={<DocumentListViewSkeleton />}>
{<PolicyListViewContent queryRef={queryRef} />} {<DocumentListViewContent queryRef={queryRef} />}
</Suspense> </Suspense>
); );
} }

View File

@@ -4,26 +4,26 @@ import { lazy } from "@probo/react-lazy";
import { useLocation } from "react-router"; import { useLocation } from "react-router";
import { ErrorBoundaryWithLocation } from "../ErrorBoundary"; import { ErrorBoundaryWithLocation } from "../ErrorBoundary";
const EditPolicyView = lazy(() => import("./EditPolicyView")); const EditDocumentView = lazy(() => import("./EditDocumentView"));
export function EditPolicyViewSkeleton() { export function EditDocumentViewSkeleton() {
return ( return (
<PageTemplateSkeleton <PageTemplateSkeleton
title="Edit Policy" title="Edit Document"
description="Edit an existing policy" description="Edit an existing document"
> >
<div className="bg-subtle-bg animate-pulse rounded-lg h-[600px]" /> <div className="bg-subtle-bg animate-pulse rounded-lg h-[600px]" />
</PageTemplateSkeleton> </PageTemplateSkeleton>
); );
} }
export function EditPolicyPage() { export function EditDocumentPage() {
const location = useLocation(); const location = useLocation();
return ( return (
<Suspense key={location.pathname} fallback={<EditPolicyViewSkeleton />}> <Suspense key={location.pathname} fallback={<EditDocumentViewSkeleton />}>
<ErrorBoundaryWithLocation> <ErrorBoundaryWithLocation>
<EditPolicyView /> <EditDocumentView />
</ErrorBoundaryWithLocation> </ErrorBoundaryWithLocation>
</Suspense> </Suspense>
); );

View File

@@ -13,27 +13,27 @@ import { Textarea } from "@/components/ui/textarea";
import { Label } from "@/components/ui/label"; import { Label } from "@/components/ui/label";
import { toast } from "@/hooks/use-toast"; import { toast } from "@/hooks/use-toast";
import { Suspense } from "react"; import { Suspense } from "react";
import type { EditPolicyViewQuery } from "./__generated__/EditPolicyViewQuery.graphql"; import type { EditDocumentViewQuery } from "./__generated__/EditDocumentViewQuery.graphql";
import type { EditPolicyViewMutation as EditPolicyViewMutationType } from "./__generated__/EditPolicyViewMutation.graphql"; import type { EditDocumentViewMutation as EditDocumentViewMutationType } from "./__generated__/EditDocumentViewMutation.graphql";
import { PageTemplate } from "@/components/PageTemplate"; import { PageTemplate } from "@/components/PageTemplate";
import { EditPolicyViewSkeleton } from "./EditPolicyPage"; import { EditDocumentViewSkeleton } from "./EditDocumentPage";
const editPolicyViewQuery = graphql` const editDocumentViewQuery = graphql`
query EditPolicyViewQuery( query EditDocumentViewQuery(
$policyId: ID! $documentId: ID!
$organizationId: ID! $organizationId: ID!
$policyVersionId: ID! $documentVersionId: ID!
) { ) {
policyVersion: node(id: $policyVersionId) { documentVersion: node(id: $documentVersionId) {
id id
... on PolicyVersion { ... on DocumentVersion {
content content
} }
} }
policy: node(id: $policyId) { document: node(id: $documentId) {
id id
... on Policy { ... on Document {
title title
owner { owner {
id id
@@ -47,10 +47,10 @@ const editPolicyViewQuery = graphql`
} }
`; `;
const UpdatePolicyMutation = graphql` const UpdateDocumentMutation = graphql`
mutation EditPolicyViewMutation($input: UpdatePolicyVersionInput!) { mutation EditDocumentViewMutation($input: UpdateDocumentVersionInput!) {
updatePolicyVersion(input: $input) { updateDocumentVersion(input: $input) {
policyVersion { documentVersion {
id id
content content
} }
@@ -58,75 +58,75 @@ const UpdatePolicyMutation = graphql`
} }
`; `;
function EditPolicyViewContent({ function EditDocumentViewContent({
queryRef, queryRef,
}: { }: {
queryRef: PreloadedQuery<EditPolicyViewQuery>; queryRef: PreloadedQuery<EditDocumentViewQuery>;
}) { }) {
const navigate = useNavigate(); const navigate = useNavigate();
const { organizationId, policyId, versionId } = useParams(); const { organizationId, documentId, versionId } = useParams();
const data = usePreloadedQuery<EditPolicyViewQuery>( const data = usePreloadedQuery<EditDocumentViewQuery>(
editPolicyViewQuery, editDocumentViewQuery,
queryRef, queryRef,
); );
const [content, setContent] = useState(data.policyVersion.content || ""); const [content, setContent] = useState(data.documentVersion.content || "");
const [updatePolicy, isSubmitting] = const [updateDocument, isSubmitting] =
useMutation<EditPolicyViewMutationType>(UpdatePolicyMutation); useMutation<EditDocumentViewMutationType>(UpdateDocumentMutation);
const handleSubmit = (e: React.FormEvent) => { const handleSubmit = (e: React.FormEvent) => {
e.preventDefault(); e.preventDefault();
updatePolicy({ updateDocument({
variables: { variables: {
input: { input: {
policyVersionId: data.policyVersion.id, documentVersionId: data.documentVersion.id,
content, content,
}, },
}, },
onCompleted: (_, errors) => { onCompleted: (_, errors) => {
if (errors) { if (errors) {
console.error("Error updating policy:", errors); console.error("Error updating document:", errors);
toast({ toast({
title: "Error", title: "Error",
description: "Failed to update policy. Please try again.", description: "Failed to update document. Please try again.",
}); });
return; return;
} }
toast({ toast({
title: "Success", title: "Success",
description: "Policy updated successfully.", description: "Document updated successfully.",
}); });
navigate(`/organizations/${organizationId}/policies/${policyId}`); navigate(`/organizations/${organizationId}/documents/${documentId}`);
}, },
onError: (error) => { onError: (error) => {
console.error("Error updating policy:", error); console.error("Error updating document:", error);
toast({ toast({
title: "Error", title: "Error",
description: "Failed to update policy. Please try again.", description: "Failed to update document. Please try again.",
}); });
}, },
}); });
}; };
return ( return (
<PageTemplate title="Update Policy" description="Update an existing policy"> <PageTemplate title="Update Document" description="Update an existing document">
<form onSubmit={handleSubmit}> <form onSubmit={handleSubmit}>
<div className="grid gap-6"> <div className="grid gap-6">
<Card> <Card>
<CardHeader> <CardHeader>
<CardTitle>Policy Information</CardTitle> <CardTitle>Document Information</CardTitle>
</CardHeader> </CardHeader>
<CardContent className="space-y-4"> <CardContent className="space-y-4">
<div className="space-y-2"> <div className="space-y-2">
<Label htmlFor="content">Policy Content</Label> <Label htmlFor="content">Document Content</Label>
<div className="min-h-[500px]"> <div className="min-h-[500px]">
<Textarea <Textarea
id="content" id="content"
placeholder="Enter policy description" placeholder="Enter document description"
value={content} value={content}
onChange={(e) => setContent(e.target.value)} onChange={(e) => setContent(e.target.value)}
required required
@@ -144,14 +144,14 @@ function EditPolicyViewContent({
variant="outline" variant="outline"
onClick={() => onClick={() =>
navigate( navigate(
`/organizations/${organizationId}/policies/${policyId}`, `/organizations/${organizationId}/documents/${documentId}`,
) )
} }
> >
Cancel Cancel
</Button> </Button>
<Button type="submit" disabled={isSubmitting}> <Button type="submit" disabled={isSubmitting}>
{isSubmitting ? "Updating..." : "Update Policy"} {isSubmitting ? "Updating..." : "Update Document"}
</Button> </Button>
</div> </div>
</div> </div>
@@ -160,26 +160,26 @@ function EditPolicyViewContent({
); );
} }
export default function EditPolicyView() { export default function EditDocumentView() {
const { organizationId, policyId, versionId } = useParams(); const { organizationId, documentId, versionId } = useParams();
const [queryRef, loadQuery] = const [queryRef, loadQuery] =
useQueryLoader<EditPolicyViewQuery>(editPolicyViewQuery); useQueryLoader<EditDocumentViewQuery>(editDocumentViewQuery);
useEffect(() => { useEffect(() => {
loadQuery({ loadQuery({
organizationId: organizationId!, organizationId: organizationId!,
policyId: policyId!, documentId: documentId!,
policyVersionId: versionId!, documentVersionId: versionId!,
}); });
}, [organizationId, policyId, versionId]); }, [organizationId, documentId, versionId]);
if (!queryRef) { if (!queryRef) {
return <EditPolicyViewSkeleton />; return <EditDocumentViewSkeleton />;
} }
return ( return (
<Suspense fallback={<EditPolicyViewSkeleton />}> <Suspense fallback={<EditDocumentViewSkeleton />}>
<EditPolicyViewContent queryRef={queryRef} /> <EditDocumentViewContent queryRef={queryRef} />
</Suspense> </Suspense>
); );
} }

View File

@@ -5,9 +5,9 @@ import { useLocation } from "react-router";
import { ErrorBoundaryWithLocation } from "../ErrorBoundary"; import { ErrorBoundaryWithLocation } from "../ErrorBoundary";
import { lazy } from "@probo/react-lazy"; import { lazy } from "@probo/react-lazy";
const ShowPolicyView = lazy(() => import("./ShowPolicyView")); const ShowDocumentView = lazy(() => import("./ShowDocumentView"));
export function ShowPolicyViewSkeleton() { export function ShowDocumentViewSkeleton() {
return ( return (
<PageTemplateSkeleton <PageTemplateSkeleton
withDescription withDescription
@@ -108,13 +108,13 @@ export function ShowPolicyViewSkeleton() {
); );
} }
export function ShowPolicyPage() { export function ShowDocumentPage() {
const location = useLocation(); const location = useLocation();
return ( return (
<Suspense key={location.pathname} fallback={<ShowPolicyViewSkeleton />}> <Suspense key={location.pathname} fallback={<ShowDocumentViewSkeleton />}>
<ErrorBoundaryWithLocation> <ErrorBoundaryWithLocation>
<ShowPolicyView /> <ShowDocumentView />
</ErrorBoundaryWithLocation> </ErrorBoundaryWithLocation>
</Suspense> </Suspense>
); );

View File

@@ -20,12 +20,12 @@ import {
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { useToast } from "@/hooks/use-toast"; import { useToast } from "@/hooks/use-toast";
import { PageTemplate } from "@/components/PageTemplate"; import { PageTemplate } from "@/components/PageTemplate";
import type { ShowPolicyViewQuery } from "./__generated__/ShowPolicyViewQuery.graphql"; import type { ShowDocumentViewQuery } from "./__generated__/ShowDocumentViewQuery.graphql";
import { ShowPolicyViewPublishMutation } from "./__generated__/ShowPolicyViewPublishMutation.graphql"; import { ShowDocumentViewPublishMutation } from "./__generated__/ShowDocumentViewPublishMutation.graphql";
import { ShowPolicyViewCreateDraftMutation } from "./__generated__/ShowPolicyViewCreateDraftMutation.graphql"; import { ShowDocumentViewCreateDraftMutation } from "./__generated__/ShowDocumentViewCreateDraftMutation.graphql";
import ReactMarkdown from "react-markdown"; import ReactMarkdown from "react-markdown";
import remarkGfm from "remark-gfm"; import remarkGfm from "remark-gfm";
import { ShowPolicyViewSkeleton } from "./ShowPolicyPage"; import { ShowDocumentViewSkeleton } from "./ShowDocumentPage";
import { format } from "date-fns"; import { format } from "date-fns";
import { import {
DropdownMenu, DropdownMenu,
@@ -45,20 +45,20 @@ import { SignaturesModal } from "./SignaturesModal";
import { VersionHistoryModal } from "./VersionHistoryModal"; import { VersionHistoryModal } from "./VersionHistoryModal";
import rehypeRaw from "rehype-raw"; import rehypeRaw from "rehype-raw";
import { createRoot } from "react-dom/client"; import { createRoot } from "react-dom/client";
import { policyVersionsFragment } from "./SignaturesModal"; import { documentVersionsFragment } from "./SignaturesModal";
import type { SignaturesModal_policyVersions$key } from "./__generated__/SignaturesModal_policyVersions.graphql"; import type { SignaturesModal_documentVersions$key } from "./__generated__/SignaturesModal_documentVersions.graphql";
const policyViewQuery = graphql` const documentViewQuery = graphql`
query ShowPolicyViewQuery($policyId: ID!, $organizationId: ID!) { query ShowDocumentViewQuery($documentId: ID!, $organizationId: ID!) {
organization: node(id: $organizationId) { organization: node(id: $organizationId) {
... on Organization { ... on Organization {
name name
} }
} }
node(id: $policyId) { node(id: $documentId) {
id id
... on Policy { ... on Document {
title title
description description
createdAt createdAt
@@ -70,8 +70,8 @@ const policyViewQuery = graphql`
primaryEmailAddress primaryEmailAddress
} }
...SignaturesModal_policyVersions ...SignaturesModal_documentVersions
...VersionHistoryModal_policyVersions ...VersionHistoryModal_documentVersions
latestVersion: versions(first: 1) { latestVersion: versions(first: 1) {
edges { edges {
@@ -95,14 +95,14 @@ const policyViewQuery = graphql`
} }
`; `;
const publishPolicyVersionMutation = graphql` const publishDocumentVersionMutation = graphql`
mutation ShowPolicyViewPublishMutation($input: PublishPolicyVersionInput!) { mutation ShowDocumentViewPublishMutation($input: PublishDocumentVersionInput!) {
publishPolicyVersion(input: $input) { publishDocumentVersion(input: $input) {
policy { document {
id id
currentPublishedVersion currentPublishedVersion
} }
policyVersion { documentVersion {
id id
status status
publishedAt publishedAt
@@ -114,12 +114,12 @@ const publishPolicyVersionMutation = graphql`
} }
`; `;
const createDraftPolicyVersionMutation = graphql` const createDraftDocumentVersionMutation = graphql`
mutation ShowPolicyViewCreateDraftMutation( mutation ShowDocumentViewCreateDraftMutation(
$input: CreateDraftPolicyVersionInput! $input: CreateDraftDocumentVersionInput!
) { ) {
createDraftPolicyVersion(input: $input) { createDraftDocumentVersion(input: $input) {
policyVersionEdge { documentVersionEdge {
node { node {
id id
version version
@@ -130,22 +130,22 @@ const createDraftPolicyVersionMutation = graphql`
} }
`; `;
function ShowPolicyContent({ function ShowDocumentContent({
queryRef, queryRef,
}: { }: {
queryRef: PreloadedQuery<ShowPolicyViewQuery>; queryRef: PreloadedQuery<ShowDocumentViewQuery>;
}) { }) {
const data = usePreloadedQuery<ShowPolicyViewQuery>( const data = usePreloadedQuery<ShowDocumentViewQuery>(
policyViewQuery, documentViewQuery,
queryRef, queryRef,
); );
const policy = data.node; const documentValue = data.node;
const { organizationId } = useParams(); const { organizationId } = useParams();
const navigate = useNavigate(); const navigate = useNavigate();
const { toast } = useToast(); const { toast } = useToast();
const [queryRef2, loadQuery] = const [queryRef2, loadQuery] =
useQueryLoader<ShowPolicyViewQuery>(policyViewQuery); useQueryLoader<ShowDocumentViewQuery>(documentViewQuery);
const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false); const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false);
const [isDeleting, setIsDeleting] = useState(false); const [isDeleting, setIsDeleting] = useState(false);
const [isVersionHistoryOpen, setIsVersionHistoryOpen] = useState(false); const [isVersionHistoryOpen, setIsVersionHistoryOpen] = useState(false);
@@ -153,13 +153,13 @@ function ShowPolicyContent({
const printContentRef = useRef<HTMLDivElement>(null); const printContentRef = useRef<HTMLDivElement>(null);
const [publishDraft, isPublishInFlight] = const [publishDraft, isPublishInFlight] =
useMutation<ShowPolicyViewPublishMutation>(publishPolicyVersionMutation); useMutation<ShowDocumentViewPublishMutation>(publishDocumentVersionMutation);
const [createDraft, isCreateDraftInFlight] = const [createDraft, isCreateDraftInFlight] =
useMutation<ShowPolicyViewCreateDraftMutation>( useMutation<ShowDocumentViewCreateDraftMutation>(
createDraftPolicyVersionMutation, createDraftDocumentVersionMutation,
); );
const latestVersionEdge = policy.latestVersion?.edges[0]; const latestVersionEdge = documentValue.latestVersion?.edges[0];
const latestVersionNode = latestVersionEdge?.node; const latestVersionNode = latestVersionEdge?.node;
const isDraft = latestVersionNode?.status === "DRAFT"; const isDraft = latestVersionNode?.status === "DRAFT";
@@ -168,40 +168,40 @@ function ShowPolicyContent({
// No need to update selectedVersion state since we're using the VersionHistoryModal component // No need to update selectedVersion state since we're using the VersionHistoryModal component
}, []); }, []);
// Handle delete policy // Handle delete document
const handleDeletePolicy = useCallback(() => { const handleDeleteDocument = useCallback(() => {
setIsDeleteDialogOpen(true); setIsDeleteDialogOpen(true);
}, []); }, []);
// Confirm delete policy // Confirm delete document
const confirmDeletePolicy = useCallback(() => { const confirmDeleteDocument = useCallback(() => {
setIsDeleting(true); setIsDeleting(true);
setTimeout(() => { setTimeout(() => {
toast({ toast({
title: "Policy deleted", title: "Document deleted",
description: "The policy has been deleted successfully", description: "The document has been deleted successfully",
}); });
setIsDeleting(false); setIsDeleting(false);
setIsDeleteDialogOpen(false); setIsDeleteDialogOpen(false);
navigate(`/organizations/${organizationId}/policies`); navigate(`/organizations/${organizationId}/documents`);
}, 1000); }, 1000);
}, [toast, navigate, organizationId]); }, [toast, navigate, organizationId]);
// Navigate to publish flow // Navigate to publish flow
const handlePublish = useCallback(() => { const handlePublish = useCallback(() => {
if (!policy.id) return; if (!documentValue.id) return;
publishDraft({ publishDraft({
variables: { variables: {
input: { input: {
policyId: policy.id, documentId: documentValue.id,
}, },
}, },
onCompleted: (_, errors) => { onCompleted: (_, errors) => {
if (errors) { if (errors) {
toast({ toast({
title: "Error publishing policy", title: "Error publishing document",
description: errors[0]?.message || "An unknown error occurred", description: errors[0]?.message || "An unknown error occurred",
variant: "destructive", variant: "destructive",
}); });
@@ -209,22 +209,22 @@ function ShowPolicyContent({
} }
toast({ toast({
title: "Policy published", title: "Document published",
description: `The policy has been published successfully`, description: `The document has been published successfully`,
}); });
// Reload the query to refresh the data // Reload the query to refresh the data
loadQuery({ policyId: policy.id, organizationId: organizationId! }); loadQuery({ documentId: documentValue.id, organizationId: organizationId! });
}, },
onError: (error) => { onError: (error) => {
toast({ toast({
title: "Error publishing policy", title: "Error publishing document",
description: error.message || "An unknown error occurred", description: error.message || "An unknown error occurred",
variant: "destructive", variant: "destructive",
}); });
}, },
}); });
}, [policy.id, publishDraft, toast, loadQuery]); }, [documentValue.id, publishDraft, toast, loadQuery]);
// Open version history modal // Open version history modal
const handleVersionHistoryClick = useCallback(() => { const handleVersionHistoryClick = useCallback(() => {
@@ -241,23 +241,23 @@ function ShowPolicyContent({
}); });
setIsVersionHistoryOpen(false); setIsVersionHistoryOpen(false);
// Reload the query to refresh the data // Reload the query to refresh the data
if (policy.id) { if (documentValue.id) {
loadQuery({ policyId: policy.id, organizationId: organizationId! }); loadQuery({ documentId: documentValue.id, organizationId: organizationId! });
} }
}, },
[policy.id, loadQuery, toast], [documentValue.id, loadQuery, toast],
); );
// Handle edit policy // Handle edit document
const handleEditPolicy = useCallback(() => { const handleEditDocument = useCallback(() => {
if (!policy.id) return; if (!documentValue.id) return;
if (latestVersionNode?.status === "PUBLISHED") { if (latestVersionNode?.status === "PUBLISHED") {
// Create a new draft version first // Create a new draft version first
createDraft({ createDraft({
variables: { variables: {
input: { input: {
policyID: policy.id, documentID: documentValue.id,
}, },
}, },
onCompleted: (response, errors) => { onCompleted: (response, errors) => {
@@ -271,9 +271,9 @@ function ShowPolicyContent({
} }
const newDraftId = const newDraftId =
response.createDraftPolicyVersion.policyVersionEdge.node.id; response.createDraftDocumentVersion.documentVersionEdge.node.id;
navigate( navigate(
`/organizations/${organizationId}/policies/${policy.id}/versions/${newDraftId}/edit`, `/organizations/${organizationId}/documents/${documentValue.id}/versions/${newDraftId}/edit`,
); );
}, },
onError: (error) => { onError: (error) => {
@@ -287,11 +287,11 @@ function ShowPolicyContent({
} else { } else {
// Navigate directly to edit if it's already a draft // Navigate directly to edit if it's already a draft
navigate( navigate(
`/organizations/${organizationId}/policies/${policy.id}/versions/${latestVersionNode?.id}/edit`, `/organizations/${organizationId}/documents/${documentValue.id}/versions/${latestVersionNode?.id}/edit`,
); );
} }
}, [ }, [
policy.id, documentValue.id,
latestVersionNode, latestVersionNode,
createDraft, createDraft,
navigate, navigate,
@@ -306,10 +306,10 @@ function ShowPolicyContent({
return format(date, "MMM d, yyyy"); return format(date, "MMM d, yyyy");
}; };
// Get policy signatures data // Get document signatures data
const policyData = useFragment<SignaturesModal_policyVersions$key>( const documentData = useFragment<SignaturesModal_documentVersions$key>(
policyVersionsFragment, documentVersionsFragment,
policy as unknown as SignaturesModal_policyVersions$key documentValue as unknown as SignaturesModal_documentVersions$key
); );
// Handle PDF download // Handle PDF download
@@ -326,12 +326,12 @@ function ShowPolicyContent({
} }
// Get version nodes and signatures from the fragment data we have // Get version nodes and signatures from the fragment data we have
const versionNodes = policyData?.policyVersions?.edges?.map(edge => edge.node) || []; const versionNodes = documentData?.documentVersions?.edges?.map(edge => edge.node) || [];
const currentVersion = versionNodes.find(v => v.version === latestVersionNode?.version); const currentVersion = versionNodes.find(v => v.version === latestVersionNode?.version);
const signatures = currentVersion?.signatures?.edges?.map(edge => edge.node) || []; const signatures = currentVersion?.signatures?.edges?.map(edge => edge.node) || [];
// Create temporary div to render and capture markdown // Create temporary div to render and capture markdown
const tempDiv = document.createElement('div'); const tempDiv = window.document.createElement('div');
const root = createRoot(tempDiv); const root = createRoot(tempDiv);
// Render the markdown content to HTML // Render the markdown content to HTML
@@ -370,12 +370,12 @@ function ShowPolicyContent({
`; `;
} }
// Create the print document content with the policy document data // Create the print document content with the document document data
printWindow.document.write(` printWindow.document.write(`
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>${policy.title || 'Policy Document'}</title> <title>${documentValue.title || 'Document Document'}</title>
<style> <style>
body { font-family: system-ui, -apple-system, sans-serif; margin: 40px; } body { font-family: system-ui, -apple-system, sans-serif; margin: 40px; }
.header { margin-bottom: 30px; } .header { margin-bottom: 30px; }
@@ -426,12 +426,12 @@ function ShowPolicyContent({
</head> </head>
<body> <body>
<div class="header"> <div class="header">
<h1>${policy.title || 'Policy Document'}</h1> <h1>${documentValue.title || 'Document Document'}</h1>
<div class="metadata"> <div class="metadata">
<div class="metadata-item"><strong>Version:</strong> ${latestVersionNode?.version || 'N/A'}</div> <div class="metadata-item"><strong>Version:</strong> ${latestVersionNode?.version || 'N/A'}</div>
<div class="metadata-item"><strong>Status:</strong> ${latestVersionNode?.status === 'PUBLISHED' ? 'Published' : 'Draft'}</div> <div class="metadata-item"><strong>Status:</strong> ${latestVersionNode?.status === 'PUBLISHED' ? 'Published' : 'Draft'}</div>
<div class="metadata-item"><strong>Published Date:</strong> ${latestVersionNode?.status === 'PUBLISHED' ? formatDate(latestVersionNode.publishedAt || '') : 'Not yet published'}</div> <div class="metadata-item"><strong>Published Date:</strong> ${latestVersionNode?.status === 'PUBLISHED' ? formatDate(latestVersionNode.publishedAt || '') : 'Not yet published'}</div>
<div class="metadata-item"><strong>Owner:</strong> ${policy.owner?.fullName || 'Unknown'}</div> <div class="metadata-item"><strong>Owner:</strong> ${documentValue.owner?.fullName || 'Unknown'}</div>
<div class="metadata-item"><strong>Last Modified:</strong> ${formatDate(latestVersionNode?.updatedAt)}</div> <div class="metadata-item"><strong>Last Modified:</strong> ${formatDate(latestVersionNode?.updatedAt)}</div>
<div class="metadata-item"><strong>Company:</strong> ${data.organization.name}</div> <div class="metadata-item"><strong>Company:</strong> ${data.organization.name}</div>
</div> </div>
@@ -462,11 +462,11 @@ function ShowPolicyContent({
root.unmount(); root.unmount();
}, 100); }, 100);
}, [policy, latestVersionNode, formatDate, toast, policyData, data.organization.name!]); }, [documentValue, latestVersionNode, formatDate, toast, documentData, data.organization.name!]);
return ( return (
<PageTemplate <PageTemplate
title={policy.title!} title={documentValue.title!}
actions={ actions={
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<Button <Button
@@ -523,19 +523,19 @@ function ShowPolicyContent({
</DropdownMenuTrigger> </DropdownMenuTrigger>
<DropdownMenuContent align="end"> <DropdownMenuContent align="end">
<DropdownMenuItem asChild> <DropdownMenuItem asChild>
<div onClick={handleEditPolicy}> <div onClick={handleEditDocument}>
<Edit className="mr-2 h-4 w-4" /> <Edit className="mr-2 h-4 w-4" />
{latestVersionNode?.status === "PUBLISHED" {latestVersionNode?.status === "PUBLISHED"
? "Create new draft" ? "Create new draft"
: "Edit draft policy"} : "Edit draft document"}
</div> </div>
</DropdownMenuItem> </DropdownMenuItem>
<DropdownMenuItem <DropdownMenuItem
onClick={handleDeletePolicy} onClick={handleDeleteDocument}
className="text-danger focus:text-danger focus:bg-danger-bg" className="text-danger focus:text-danger focus:bg-danger-bg"
> >
<Trash2 className="mr-2 h-4 w-4" /> <Trash2 className="mr-2 h-4 w-4" />
Delete policy Delete document
</DropdownMenuItem> </DropdownMenuItem>
</DropdownMenuContent> </DropdownMenuContent>
</DropdownMenu> </DropdownMenu>
@@ -548,7 +548,7 @@ function ShowPolicyContent({
<div className="bg-gray-50 rounded-lg border border-solid-b shadow-sm p-6 mb-4"> <div className="bg-gray-50 rounded-lg border border-solid-b shadow-sm p-6 mb-4">
<div className="grid grid-cols-2 gap-y-3"> <div className="grid grid-cols-2 gap-y-3">
<div> <div>
<span className="font-medium">Document Title:</span> {policy.title} <span className="font-medium">Document Title:</span> {documentValue.title}
</div> </div>
<div> <div>
<span className="font-medium">Version:</span> {latestVersionNode.version || "N/A"} <span className="font-medium">Version:</span> {latestVersionNode.version || "N/A"}
@@ -560,7 +560,7 @@ function ShowPolicyContent({
<span className="font-medium">Published Date:</span> {latestVersionNode.status === "PUBLISHED" ? formatDate(latestVersionNode.publishedAt || "") : "Not yet published"} <span className="font-medium">Published Date:</span> {latestVersionNode.status === "PUBLISHED" ? formatDate(latestVersionNode.publishedAt || "") : "Not yet published"}
</div> </div>
<div> <div>
<span className="font-medium">Owner:</span> {policy.owner?.fullName || "Unknown"} <span className="font-medium">Owner:</span> {documentValue.owner?.fullName || "Unknown"}
</div> </div>
<div> <div>
<span className="font-medium">Last Modified:</span> {formatDate(latestVersionNode.updatedAt)} <span className="font-medium">Last Modified:</span> {formatDate(latestVersionNode.updatedAt)}
@@ -590,7 +590,7 @@ function ShowPolicyContent({
<div> <div>
{latestVersionNode.status === "PUBLISHED" {latestVersionNode.status === "PUBLISHED"
? `Published on ${formatDate(latestVersionNode.publishedAt || "")}${latestVersionNode.publishedBy ? ` by ${latestVersionNode.publishedBy.fullName}` : ""}` ? `Published on ${formatDate(latestVersionNode.publishedAt || "")}${latestVersionNode.publishedBy ? ` by ${latestVersionNode.publishedBy.fullName}` : ""}`
: `Last modified on ${formatDate(latestVersionNode.updatedAt)} by ${policy.owner?.fullName || "Unknown"}`} : `Last modified on ${formatDate(latestVersionNode.updatedAt)} by ${documentValue.owner?.fullName || "Unknown"}`}
</div> </div>
</div> </div>
</div> </div>
@@ -606,15 +606,15 @@ function ShowPolicyContent({
<SignaturesModal <SignaturesModal
isOpen={isSignaturesModalOpen} isOpen={isSignaturesModalOpen}
onClose={() => setIsSignaturesModalOpen(false)} onClose={() => setIsSignaturesModalOpen(false)}
policyRef={policy} documentRef={documentValue}
owner={policy.owner} owner={documentValue.owner}
/> />
{/* Version History Modal */} {/* Version History Modal */}
<VersionHistoryModal <VersionHistoryModal
isOpen={isVersionHistoryOpen} isOpen={isVersionHistoryOpen}
onClose={() => setIsVersionHistoryOpen(false)} onClose={() => setIsVersionHistoryOpen(false)}
policyRef={policy} documentRef={documentValue}
onRestoreVersion={handleRestoreVersion} onRestoreVersion={handleRestoreVersion}
/> />
@@ -622,9 +622,9 @@ function ShowPolicyContent({
<Dialog open={isDeleteDialogOpen} onOpenChange={setIsDeleteDialogOpen}> <Dialog open={isDeleteDialogOpen} onOpenChange={setIsDeleteDialogOpen}>
<DialogContent> <DialogContent>
<DialogHeader> <DialogHeader>
<DialogTitle>Delete Policy</DialogTitle> <DialogTitle>Delete Document</DialogTitle>
<DialogDescription> <DialogDescription>
Are you sure you want to delete the policy "{policy.title}"? This Are you sure you want to delete the document &ldquo;{documentValue.title}&rdquo;? This
action cannot be undone. action cannot be undone.
</DialogDescription> </DialogDescription>
</DialogHeader> </DialogHeader>
@@ -638,7 +638,7 @@ function ShowPolicyContent({
</Button> </Button>
<Button <Button
variant="destructive" variant="destructive"
onClick={confirmDeletePolicy} onClick={confirmDeleteDocument}
disabled={isDeleting} disabled={isDeleting}
> >
{isDeleting ? "Deleting..." : "Delete"} {isDeleting ? "Deleting..." : "Delete"}
@@ -650,22 +650,22 @@ function ShowPolicyContent({
); );
} }
export default function ShowPolicyView() { export default function ShowDocumentView() {
const [queryRef, loadQuery] = const [queryRef, loadQuery] =
useQueryLoader<ShowPolicyViewQuery>(policyViewQuery); useQueryLoader<ShowDocumentViewQuery>(documentViewQuery);
const { policyId, organizationId } = useParams(); const { documentId, organizationId } = useParams();
useEffect(() => { useEffect(() => {
loadQuery({ policyId: policyId!, organizationId: organizationId! }); loadQuery({ documentId: documentId!, organizationId: organizationId! });
}, [loadQuery, policyId, organizationId]); }, [loadQuery, documentId, organizationId]);
if (!queryRef) { if (!queryRef) {
return <ShowPolicyViewSkeleton />; return <ShowDocumentViewSkeleton />;
} }
return ( return (
<Suspense fallback={<ShowPolicyViewSkeleton />}> <Suspense fallback={<ShowDocumentViewSkeleton />}>
<ShowPolicyContent queryRef={queryRef} /> <ShowDocumentContent queryRef={queryRef} />
</Suspense> </Suspense>
); );
} }

View File

@@ -1,7 +1,7 @@
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { format } from "date-fns"; import { format } from "date-fns";
interface PolicyVersionSignature { interface DocumentVersionSignature {
id: string; id: string;
state: "REQUESTED" | "SIGNED"; state: "REQUESTED" | "SIGNED";
signedBy: { signedBy: {
@@ -15,7 +15,7 @@ interface PolicyVersionSignature {
} }
interface SignaturesListProps { interface SignaturesListProps {
signatures: PolicyVersionSignature[]; signatures: DocumentVersionSignature[];
} }
export function SignaturesList({ signatures }: SignaturesListProps) { export function SignaturesList({ signatures }: SignaturesListProps) {

View File

@@ -12,9 +12,9 @@ import {
ConnectionHandler, ConnectionHandler,
} from "react-relay"; } from "react-relay";
import type { import type {
SignaturesModal_policyVersions$data, SignaturesModal_documentVersions$data,
SignaturesModal_policyVersions$key, SignaturesModal_documentVersions$key,
} from "./__generated__/SignaturesModal_policyVersions.graphql"; } from "./__generated__/SignaturesModal_documentVersions.graphql";
import type { SignaturesModalRequestSignatureMutation } from "./__generated__/SignaturesModalRequestSignatureMutation.graphql"; import type { SignaturesModalRequestSignatureMutation } from "./__generated__/SignaturesModalRequestSignatureMutation.graphql";
import type { SignaturesModalOrganizationQuery } from "./__generated__/SignaturesModalOrganizationQuery.graphql"; import type { SignaturesModalOrganizationQuery } from "./__generated__/SignaturesModalOrganizationQuery.graphql";
import { useToast } from "@/hooks/use-toast"; import { useToast } from "@/hooks/use-toast";
@@ -22,10 +22,10 @@ import { useParams } from "react-router";
import { Loader2, CheckCircle2, Clock } from "lucide-react"; import { Loader2, CheckCircle2, Clock } from "lucide-react";
import { PreloadedQuery } from "react-relay"; import { PreloadedQuery } from "react-relay";
export const policyVersionsFragment = graphql` export const documentVersionsFragment = graphql`
fragment SignaturesModal_policyVersions on Policy { fragment SignaturesModal_documentVersions on Document {
title title
policyVersions: versions(first: 10) { documentVersions: versions(first: 10) {
edges { edges {
node { node {
id id
@@ -37,7 +37,7 @@ export const policyVersionsFragment = graphql`
fullName fullName
} }
signatures(first: 100) signatures(first: 100)
@connection(key: "SignaturesModal_policyVersions_signatures") { @connection(key: "SignaturesModal_documentVersions_signatures") {
edges { edges {
node { node {
id id
@@ -66,7 +66,7 @@ const requestSignatureMutation = graphql`
$connections: [ID!]! $connections: [ID!]!
) { ) {
requestSignature(input: $input) { requestSignature(input: $input) {
policyVersionSignatureEdge @prependEdge(connections: $connections) { documentVersionSignatureEdge @prependEdge(connections: $connections) {
node { node {
id id
state state
@@ -108,7 +108,7 @@ const organizationQuery = graphql`
interface SignaturesModalProps { interface SignaturesModalProps {
isOpen: boolean; isOpen: boolean;
onClose: () => void; onClose: () => void;
policyRef: SignaturesModal_policyVersions$key; documentRef: SignaturesModal_documentVersions$key;
owner?: { owner?: {
fullName: string; fullName: string;
} | null; } | null;
@@ -117,16 +117,16 @@ interface SignaturesModalProps {
export function SignaturesModal({ export function SignaturesModal({
isOpen, isOpen,
onClose, onClose,
policyRef, documentRef,
owner, owner,
}: SignaturesModalProps) { }: SignaturesModalProps) {
const data = useFragment<SignaturesModal_policyVersions$key>( const data = useFragment<SignaturesModal_documentVersions$key>(
policyVersionsFragment, documentVersionsFragment,
policyRef, documentRef,
); );
const versionNodes = const versionNodes =
data?.policyVersions?.edges?.map((edge) => edge.node) || []; data?.documentVersions?.edges?.map((edge) => edge.node) || [];
const publishedVersions = versionNodes const publishedVersions = versionNodes
.filter((v) => v.status === "PUBLISHED") .filter((v) => v.status === "PUBLISHED")
.sort((a, b) => b.version - a.version); .sort((a, b) => b.version - a.version);
@@ -177,13 +177,13 @@ export function SignaturesModal({
commitRequestSignature({ commitRequestSignature({
variables: { variables: {
input: { input: {
policyVersionId: selectedVersionData.id, documentVersionId: selectedVersionData.id,
signatoryId: personId, signatoryId: personId,
}, },
connections: [ connections: [
ConnectionHandler.getConnectionID( ConnectionHandler.getConnectionID(
selectedVersionData.id, selectedVersionData.id,
"SignaturesModal_policyVersions_signatures", "SignaturesModal_documentVersions_signatures",
), ),
], ],
}, },
@@ -406,7 +406,7 @@ function PeopleAndSignaturesList({
onRequestSignature: (personId: string) => void; onRequestSignature: (personId: string) => void;
requestingId: string | null; requestingId: string | null;
existingSignatures: Array< existingSignatures: Array<
SignaturesModal_policyVersions$data["policyVersions"]["edges"][0]["node"]["signatures"]["edges"][0]["node"] SignaturesModal_documentVersions$data["documentVersions"]["edges"][0]["node"]["signatures"]["edges"][0]["node"]
>; >;
formatDateTime: (date?: string | null) => string; formatDateTime: (date?: string | null) => string;
}) { }) {

View File

@@ -5,12 +5,12 @@ import { Button } from "@/components/ui/button";
import { useState } from "react"; import { useState } from "react";
import ReactMarkdown from "react-markdown"; import ReactMarkdown from "react-markdown";
import { graphql, useFragment } from "react-relay"; import { graphql, useFragment } from "react-relay";
import type { VersionHistoryModal_policyVersions$key } from "./__generated__/VersionHistoryModal_policyVersions.graphql"; import type { VersionHistoryModal_documentVersions$key } from "./__generated__/VersionHistoryModal_documentVersions.graphql";
import remarkGfm from "remark-gfm"; import remarkGfm from "remark-gfm";
import rehypeRaw from "rehype-raw"; import rehypeRaw from "rehype-raw";
export const policyVersionsFragment = graphql` export const documentVersionsFragment = graphql`
fragment VersionHistoryModal_policyVersions on Policy { fragment VersionHistoryModal_documentVersions on Document {
title title
owner { owner {
fullName fullName
@@ -37,19 +37,19 @@ export const policyVersionsFragment = graphql`
interface VersionHistoryModalProps { interface VersionHistoryModalProps {
isOpen: boolean; isOpen: boolean;
onClose: () => void; onClose: () => void;
policyRef: VersionHistoryModal_policyVersions$key; documentRef: VersionHistoryModal_documentVersions$key;
onRestoreVersion?: (versionNumber: number) => void; onRestoreVersion?: (versionNumber: number) => void;
} }
export function VersionHistoryModal({ export function VersionHistoryModal({
isOpen, isOpen,
onClose, onClose,
policyRef, documentRef,
onRestoreVersion, onRestoreVersion,
}: VersionHistoryModalProps) { }: VersionHistoryModalProps) {
const data = useFragment<VersionHistoryModal_policyVersions$key>( const data = useFragment<VersionHistoryModal_documentVersions$key>(
policyVersionsFragment, documentVersionsFragment,
policyRef, documentRef,
); );
// Safely access and extract version nodes // Safely access and extract version nodes

View File

@@ -1,5 +1,5 @@
/** /**
* @generated SignedSource<<885dc2a54ba3b8d4663e197cfe61d704>> * @generated SignedSource<<095491df1cce828cc3ec9ba9f2ad4183>>
* @lightSyntaxTransform * @lightSyntaxTransform
* @nogrep * @nogrep
*/ */
@@ -9,19 +9,19 @@
// @ts-nocheck // @ts-nocheck
import { ConcreteRequest } from 'relay-runtime'; import { ConcreteRequest } from 'relay-runtime';
export type CreatePolicyInput = { export type CreateDocumentInput = {
content: string; content: string;
organizationId: string; organizationId: string;
ownerId: string; ownerId: string;
title: string; title: string;
}; };
export type PolicyListViewCreateMutation$variables = { export type DocumentListViewCreateMutation$variables = {
connections: ReadonlyArray<string>; connections: ReadonlyArray<string>;
input: CreatePolicyInput; input: CreateDocumentInput;
}; };
export type PolicyListViewCreateMutation$data = { export type DocumentListViewCreateMutation$data = {
readonly createPolicy: { readonly createDocument: {
readonly policyEdge: { readonly documentEdge: {
readonly node: { readonly node: {
readonly createdAt: string; readonly createdAt: string;
readonly description: string; readonly description: string;
@@ -36,9 +36,9 @@ export type PolicyListViewCreateMutation$data = {
}; };
}; };
}; };
export type PolicyListViewCreateMutation = { export type DocumentListViewCreateMutation = {
response: PolicyListViewCreateMutation$data; response: DocumentListViewCreateMutation$data;
variables: PolicyListViewCreateMutation$variables; variables: DocumentListViewCreateMutation$variables;
}; };
const node: ConcreteRequest = (function(){ const node: ConcreteRequest = (function(){
@@ -69,15 +69,15 @@ v3 = {
v4 = { v4 = {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "PolicyEdge", "concreteType": "DocumentEdge",
"kind": "LinkedField", "kind": "LinkedField",
"name": "policyEdge", "name": "documentEdge",
"plural": false, "plural": false,
"selections": [ "selections": [
{ {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "Policy", "concreteType": "Document",
"kind": "LinkedField", "kind": "LinkedField",
"name": "node", "name": "node",
"plural": false, "plural": false,
@@ -144,14 +144,14 @@ return {
], ],
"kind": "Fragment", "kind": "Fragment",
"metadata": null, "metadata": null,
"name": "PolicyListViewCreateMutation", "name": "DocumentListViewCreateMutation",
"selections": [ "selections": [
{ {
"alias": null, "alias": null,
"args": (v2/*: any*/), "args": (v2/*: any*/),
"concreteType": "CreatePolicyPayload", "concreteType": "CreateDocumentPayload",
"kind": "LinkedField", "kind": "LinkedField",
"name": "createPolicy", "name": "createDocument",
"plural": false, "plural": false,
"selections": [ "selections": [
(v4/*: any*/) (v4/*: any*/)
@@ -169,14 +169,14 @@ return {
(v0/*: any*/) (v0/*: any*/)
], ],
"kind": "Operation", "kind": "Operation",
"name": "PolicyListViewCreateMutation", "name": "DocumentListViewCreateMutation",
"selections": [ "selections": [
{ {
"alias": null, "alias": null,
"args": (v2/*: any*/), "args": (v2/*: any*/),
"concreteType": "CreatePolicyPayload", "concreteType": "CreateDocumentPayload",
"kind": "LinkedField", "kind": "LinkedField",
"name": "createPolicy", "name": "createDocument",
"plural": false, "plural": false,
"selections": [ "selections": [
(v4/*: any*/), (v4/*: any*/),
@@ -187,7 +187,7 @@ return {
"handle": "prependEdge", "handle": "prependEdge",
"key": "", "key": "",
"kind": "LinkedHandle", "kind": "LinkedHandle",
"name": "policyEdge", "name": "documentEdge",
"handleArgs": [ "handleArgs": [
{ {
"kind": "Variable", "kind": "Variable",
@@ -202,16 +202,16 @@ return {
] ]
}, },
"params": { "params": {
"cacheID": "f7aae6d7a0d276e71caec643e43b5ee5", "cacheID": "006fad3aafaae7d03f5d85cd78ea39fb",
"id": null, "id": null,
"metadata": {}, "metadata": {},
"name": "PolicyListViewCreateMutation", "name": "DocumentListViewCreateMutation",
"operationKind": "mutation", "operationKind": "mutation",
"text": "mutation PolicyListViewCreateMutation(\n $input: CreatePolicyInput!\n) {\n createPolicy(input: $input) {\n policyEdge {\n node {\n id\n title\n description\n createdAt\n updatedAt\n owner {\n id\n fullName\n }\n }\n }\n }\n}\n" "text": "mutation DocumentListViewCreateMutation(\n $input: CreateDocumentInput!\n) {\n createDocument(input: $input) {\n documentEdge {\n node {\n id\n title\n description\n createdAt\n updatedAt\n owner {\n id\n fullName\n }\n }\n }\n }\n}\n"
} }
}; };
})(); })();
(node as any).hash = "d55ac010a7ad352d830d3a38f2f8d5a8"; (node as any).hash = "0b6f4540b8bc9dc8168ba33ed6340311";
export default node; export default node;

View File

@@ -1,5 +1,5 @@
/** /**
* @generated SignedSource<<c71120e2c59cabbcb2f9e55dacd2be6c>> * @generated SignedSource<<f20fbf3a0fd45a8f408e5fd364c9dfee>>
* @lightSyntaxTransform * @lightSyntaxTransform
* @nogrep * @nogrep
*/ */
@@ -9,21 +9,21 @@
// @ts-nocheck // @ts-nocheck
import { ConcreteRequest } from 'relay-runtime'; import { ConcreteRequest } from 'relay-runtime';
export type DeletePolicyInput = { export type DeleteDocumentInput = {
policyId: string; documentId: string;
}; };
export type PolicyListViewDeleteMutation$variables = { export type DocumentListViewDeleteMutation$variables = {
connections: ReadonlyArray<string>; connections: ReadonlyArray<string>;
input: DeletePolicyInput; input: DeleteDocumentInput;
}; };
export type PolicyListViewDeleteMutation$data = { export type DocumentListViewDeleteMutation$data = {
readonly deletePolicy: { readonly deleteDocument: {
readonly deletedPolicyId: string; readonly deletedDocumentId: string;
}; };
}; };
export type PolicyListViewDeleteMutation = { export type DocumentListViewDeleteMutation = {
response: PolicyListViewDeleteMutation$data; response: DocumentListViewDeleteMutation$data;
variables: PolicyListViewDeleteMutation$variables; variables: DocumentListViewDeleteMutation$variables;
}; };
const node: ConcreteRequest = (function(){ const node: ConcreteRequest = (function(){
@@ -48,7 +48,7 @@ v3 = {
"alias": null, "alias": null,
"args": null, "args": null,
"kind": "ScalarField", "kind": "ScalarField",
"name": "deletedPolicyId", "name": "deletedDocumentId",
"storageKey": null "storageKey": null
}; };
return { return {
@@ -59,14 +59,14 @@ return {
], ],
"kind": "Fragment", "kind": "Fragment",
"metadata": null, "metadata": null,
"name": "PolicyListViewDeleteMutation", "name": "DocumentListViewDeleteMutation",
"selections": [ "selections": [
{ {
"alias": null, "alias": null,
"args": (v2/*: any*/), "args": (v2/*: any*/),
"concreteType": "DeletePolicyPayload", "concreteType": "DeleteDocumentPayload",
"kind": "LinkedField", "kind": "LinkedField",
"name": "deletePolicy", "name": "deleteDocument",
"plural": false, "plural": false,
"selections": [ "selections": [
(v3/*: any*/) (v3/*: any*/)
@@ -84,14 +84,14 @@ return {
(v0/*: any*/) (v0/*: any*/)
], ],
"kind": "Operation", "kind": "Operation",
"name": "PolicyListViewDeleteMutation", "name": "DocumentListViewDeleteMutation",
"selections": [ "selections": [
{ {
"alias": null, "alias": null,
"args": (v2/*: any*/), "args": (v2/*: any*/),
"concreteType": "DeletePolicyPayload", "concreteType": "DeleteDocumentPayload",
"kind": "LinkedField", "kind": "LinkedField",
"name": "deletePolicy", "name": "deleteDocument",
"plural": false, "plural": false,
"selections": [ "selections": [
(v3/*: any*/), (v3/*: any*/),
@@ -102,7 +102,7 @@ return {
"handle": "deleteEdge", "handle": "deleteEdge",
"key": "", "key": "",
"kind": "ScalarHandle", "kind": "ScalarHandle",
"name": "deletedPolicyId", "name": "deletedDocumentId",
"handleArgs": [ "handleArgs": [
{ {
"kind": "Variable", "kind": "Variable",
@@ -117,16 +117,16 @@ return {
] ]
}, },
"params": { "params": {
"cacheID": "3a182fce4a0616599bea274ddf7b95a1", "cacheID": "61bee9d714b5ee08e1653d0ad426c6f5",
"id": null, "id": null,
"metadata": {}, "metadata": {},
"name": "PolicyListViewDeleteMutation", "name": "DocumentListViewDeleteMutation",
"operationKind": "mutation", "operationKind": "mutation",
"text": "mutation PolicyListViewDeleteMutation(\n $input: DeletePolicyInput!\n) {\n deletePolicy(input: $input) {\n deletedPolicyId\n }\n}\n" "text": "mutation DocumentListViewDeleteMutation(\n $input: DeleteDocumentInput!\n) {\n deleteDocument(input: $input) {\n deletedDocumentId\n }\n}\n"
} }
}; };
})(); })();
(node as any).hash = "d2a47c3563b6dcbbb88e78b954345768"; (node as any).hash = "f0da5a5c332d17752d23c2fbfcd0e503";
export default node; export default node;

View File

@@ -1,5 +1,5 @@
/** /**
* @generated SignedSource<<fbe65b0fb14443a15a43bd3d4100118f>> * @generated SignedSource<<4ae1fa075cd3c3fd2ae9d63e3ec0ae02>>
* @lightSyntaxTransform * @lightSyntaxTransform
* @nogrep * @nogrep
*/ */
@@ -10,14 +10,14 @@
import { ConcreteRequest } from 'relay-runtime'; import { ConcreteRequest } from 'relay-runtime';
import { FragmentRefs } from "relay-runtime"; import { FragmentRefs } from "relay-runtime";
export type PolicyStatus = "DRAFT" | "PUBLISHED"; export type DocumentStatus = "DRAFT" | "PUBLISHED";
export type PolicyVersionSignatureState = "REQUESTED" | "SIGNED"; export type DocumentVersionSignatureState = "REQUESTED" | "SIGNED";
export type PolicyListViewQuery$variables = { export type DocumentListViewQuery$variables = {
organizationId: string; organizationId: string;
}; };
export type PolicyListViewQuery$data = { export type DocumentListViewQuery$data = {
readonly organization: { readonly organization: {
readonly policies?: { readonly documents?: {
readonly edges: ReadonlyArray<{ readonly edges: ReadonlyArray<{
readonly node: { readonly node: {
readonly createdAt: string; readonly createdAt: string;
@@ -38,11 +38,11 @@ export type PolicyListViewQuery$data = {
readonly edges: ReadonlyArray<{ readonly edges: ReadonlyArray<{
readonly node: { readonly node: {
readonly id: string; readonly id: string;
readonly state: PolicyVersionSignatureState; readonly state: DocumentVersionSignatureState;
}; };
}>; }>;
}; };
readonly status: PolicyStatus; readonly status: DocumentStatus;
readonly updatedAt: string; readonly updatedAt: string;
}; };
}>; }>;
@@ -58,9 +58,9 @@ export type PolicyListViewQuery$data = {
}; };
}; };
}; };
export type PolicyListViewQuery = { export type DocumentListViewQuery = {
response: PolicyListViewQuery$data; response: DocumentListViewQuery$data;
variables: PolicyListViewQuery$variables; variables: DocumentListViewQuery$variables;
}; };
const node: ConcreteRequest = (function(){ const node: ConcreteRequest = (function(){
@@ -167,7 +167,7 @@ v11 = [
{ {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "PolicyEdge", "concreteType": "DocumentEdge",
"kind": "LinkedField", "kind": "LinkedField",
"name": "edges", "name": "edges",
"plural": true, "plural": true,
@@ -175,7 +175,7 @@ v11 = [
{ {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "Policy", "concreteType": "Document",
"kind": "LinkedField", "kind": "LinkedField",
"name": "node", "name": "node",
"plural": false, "plural": false,
@@ -232,7 +232,7 @@ v11 = [
"value": 1 "value": 1
} }
], ],
"concreteType": "PolicyVersionConnection", "concreteType": "DocumentVersionConnection",
"kind": "LinkedField", "kind": "LinkedField",
"name": "versions", "name": "versions",
"plural": false, "plural": false,
@@ -240,7 +240,7 @@ v11 = [
{ {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "PolicyVersionEdge", "concreteType": "DocumentVersionEdge",
"kind": "LinkedField", "kind": "LinkedField",
"name": "edges", "name": "edges",
"plural": true, "plural": true,
@@ -248,7 +248,7 @@ v11 = [
{ {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "PolicyVersion", "concreteType": "DocumentVersion",
"kind": "LinkedField", "kind": "LinkedField",
"name": "node", "name": "node",
"plural": false, "plural": false,
@@ -267,7 +267,7 @@ v11 = [
"args": [ "args": [
(v7/*: any*/) (v7/*: any*/)
], ],
"concreteType": "PolicyVersionSignatureConnection", "concreteType": "DocumentVersionSignatureConnection",
"kind": "LinkedField", "kind": "LinkedField",
"name": "signatures", "name": "signatures",
"plural": false, "plural": false,
@@ -275,7 +275,7 @@ v11 = [
{ {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "PolicyVersionSignatureEdge", "concreteType": "DocumentVersionSignatureEdge",
"kind": "LinkedField", "kind": "LinkedField",
"name": "edges", "name": "edges",
"plural": true, "plural": true,
@@ -283,7 +283,7 @@ v11 = [
{ {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "PolicyVersionSignature", "concreteType": "DocumentVersionSignature",
"kind": "LinkedField", "kind": "LinkedField",
"name": "node", "name": "node",
"plural": false, "plural": false,
@@ -351,7 +351,7 @@ return {
"argumentDefinitions": (v0/*: any*/), "argumentDefinitions": (v0/*: any*/),
"kind": "Fragment", "kind": "Fragment",
"metadata": null, "metadata": null,
"name": "PolicyListViewQuery", "name": "DocumentListViewQuery",
"selections": [ "selections": [
{ {
"alias": null, "alias": null,
@@ -382,16 +382,16 @@ return {
"name": "PeopleSelector_organization" "name": "PeopleSelector_organization"
}, },
{ {
"alias": "policies", "alias": "documents",
"args": [ "args": [
(v4/*: any*/) (v4/*: any*/)
], ],
"concreteType": "PolicyConnection", "concreteType": "DocumentConnection",
"kind": "LinkedField", "kind": "LinkedField",
"name": "__PolicyListView_policies_connection", "name": "__DocumentListView_documents_connection",
"plural": false, "plural": false,
"selections": (v11/*: any*/), "selections": (v11/*: any*/),
"storageKey": "__PolicyListView_policies_connection(orderBy:{\"direction\":\"ASC\",\"field\":\"TITLE\"})" "storageKey": "__DocumentListView_documents_connection(orderBy:{\"direction\":\"ASC\",\"field\":\"TITLE\"})"
} }
], ],
"type": "Organization", "type": "Organization",
@@ -408,7 +408,7 @@ return {
"operation": { "operation": {
"argumentDefinitions": (v0/*: any*/), "argumentDefinitions": (v0/*: any*/),
"kind": "Operation", "kind": "Operation",
"name": "PolicyListViewQuery", "name": "DocumentListViewQuery",
"selections": [ "selections": [
{ {
"alias": null, "alias": null,
@@ -493,21 +493,21 @@ return {
{ {
"alias": null, "alias": null,
"args": (v14/*: any*/), "args": (v14/*: any*/),
"concreteType": "PolicyConnection", "concreteType": "DocumentConnection",
"kind": "LinkedField", "kind": "LinkedField",
"name": "policies", "name": "documents",
"plural": false, "plural": false,
"selections": (v11/*: any*/), "selections": (v11/*: any*/),
"storageKey": "policies(first:50,orderBy:{\"direction\":\"ASC\",\"field\":\"TITLE\"})" "storageKey": "documents(first:50,orderBy:{\"direction\":\"ASC\",\"field\":\"TITLE\"})"
}, },
{ {
"alias": null, "alias": null,
"args": (v14/*: any*/), "args": (v14/*: any*/),
"filters": (v13/*: any*/), "filters": (v13/*: any*/),
"handle": "connection", "handle": "connection",
"key": "PolicyListView_policies", "key": "DocumentListView_documents",
"kind": "LinkedHandle", "kind": "LinkedHandle",
"name": "policies" "name": "documents"
} }
], ],
"type": "Organization", "type": "Organization",
@@ -519,7 +519,7 @@ return {
] ]
}, },
"params": { "params": {
"cacheID": "1a9f6afc7b288a1051294afe154f14c4", "cacheID": "6b91a4a77bedb9f66abeaeec8c1c5535",
"id": null, "id": null,
"metadata": { "metadata": {
"connection": [ "connection": [
@@ -529,18 +529,18 @@ return {
"direction": "forward", "direction": "forward",
"path": [ "path": [
"organization", "organization",
"policies" "documents"
] ]
} }
] ]
}, },
"name": "PolicyListViewQuery", "name": "DocumentListViewQuery",
"operationKind": "query", "operationKind": "query",
"text": "query PolicyListViewQuery(\n $organizationId: ID!\n) {\n viewer {\n user {\n id\n }\n id\n }\n organization: node(id: $organizationId) {\n __typename\n ... on Organization {\n ...PeopleSelector_organization\n policies(first: 50, orderBy: {field: TITLE, direction: ASC}) {\n edges {\n node {\n id\n title\n description\n currentPublishedVersion\n createdAt\n updatedAt\n owner {\n id\n fullName\n }\n versions(first: 1) {\n edges {\n node {\n id\n status\n updatedAt\n signatures(first: 100) {\n edges {\n node {\n id\n state\n }\n }\n }\n }\n }\n }\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n id\n }\n}\n\nfragment PeopleSelector_organization on Organization {\n id\n peoples(first: 100, orderBy: {direction: ASC, field: FULL_NAME}) {\n edges {\n node {\n id\n fullName\n primaryEmailAddress\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n}\n" "text": "query DocumentListViewQuery(\n $organizationId: ID!\n) {\n viewer {\n user {\n id\n }\n id\n }\n organization: node(id: $organizationId) {\n __typename\n ... on Organization {\n ...PeopleSelector_organization\n documents(first: 50, orderBy: {field: TITLE, direction: ASC}) {\n edges {\n node {\n id\n title\n description\n currentPublishedVersion\n createdAt\n updatedAt\n owner {\n id\n fullName\n }\n versions(first: 1) {\n edges {\n node {\n id\n status\n updatedAt\n signatures(first: 100) {\n edges {\n node {\n id\n state\n }\n }\n }\n }\n }\n }\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n id\n }\n}\n\nfragment PeopleSelector_organization on Organization {\n id\n peoples(first: 100, orderBy: {direction: ASC, field: FULL_NAME}) {\n edges {\n node {\n id\n fullName\n primaryEmailAddress\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n}\n"
} }
}; };
})(); })();
(node as any).hash = "0aa2374fc681f6d130fbf03586707d5a"; (node as any).hash = "df33668bcdfe69a122a8846bb1d66df1";
export default node; export default node;

View File

@@ -1,5 +1,5 @@
/** /**
* @generated SignedSource<<ec7d0ef29b8366117ddf75e75669f5fa>> * @generated SignedSource<<25fe683751dd38b0c417c7df9a7f773f>>
* @lightSyntaxTransform * @lightSyntaxTransform
* @nogrep * @nogrep
*/ */
@@ -12,17 +12,17 @@ import { ConcreteRequest } from 'relay-runtime';
export type SendSigningNotificationsInput = { export type SendSigningNotificationsInput = {
organizationId: string; organizationId: string;
}; };
export type PolicyListViewSendSigningNotificationsMutation$variables = { export type DocumentListViewSendSigningNotificationsMutation$variables = {
input: SendSigningNotificationsInput; input: SendSigningNotificationsInput;
}; };
export type PolicyListViewSendSigningNotificationsMutation$data = { export type DocumentListViewSendSigningNotificationsMutation$data = {
readonly sendSigningNotifications: { readonly sendSigningNotifications: {
readonly success: boolean; readonly success: boolean;
}; };
}; };
export type PolicyListViewSendSigningNotificationsMutation = { export type DocumentListViewSendSigningNotificationsMutation = {
response: PolicyListViewSendSigningNotificationsMutation$data; response: DocumentListViewSendSigningNotificationsMutation$data;
variables: PolicyListViewSendSigningNotificationsMutation$variables; variables: DocumentListViewSendSigningNotificationsMutation$variables;
}; };
const node: ConcreteRequest = (function(){ const node: ConcreteRequest = (function(){
@@ -64,7 +64,7 @@ return {
"argumentDefinitions": (v0/*: any*/), "argumentDefinitions": (v0/*: any*/),
"kind": "Fragment", "kind": "Fragment",
"metadata": null, "metadata": null,
"name": "PolicyListViewSendSigningNotificationsMutation", "name": "DocumentListViewSendSigningNotificationsMutation",
"selections": (v1/*: any*/), "selections": (v1/*: any*/),
"type": "Mutation", "type": "Mutation",
"abstractKey": null "abstractKey": null
@@ -73,20 +73,20 @@ return {
"operation": { "operation": {
"argumentDefinitions": (v0/*: any*/), "argumentDefinitions": (v0/*: any*/),
"kind": "Operation", "kind": "Operation",
"name": "PolicyListViewSendSigningNotificationsMutation", "name": "DocumentListViewSendSigningNotificationsMutation",
"selections": (v1/*: any*/) "selections": (v1/*: any*/)
}, },
"params": { "params": {
"cacheID": "a6b25b9e4abf4243131b90b47f4e2ef4", "cacheID": "0eb5a217a3b01f80c0ec446df15b0c40",
"id": null, "id": null,
"metadata": {}, "metadata": {},
"name": "PolicyListViewSendSigningNotificationsMutation", "name": "DocumentListViewSendSigningNotificationsMutation",
"operationKind": "mutation", "operationKind": "mutation",
"text": "mutation PolicyListViewSendSigningNotificationsMutation(\n $input: SendSigningNotificationsInput!\n) {\n sendSigningNotifications(input: $input) {\n success\n }\n}\n" "text": "mutation DocumentListViewSendSigningNotificationsMutation(\n $input: SendSigningNotificationsInput!\n) {\n sendSigningNotifications(input: $input) {\n success\n }\n}\n"
} }
}; };
})(); })();
(node as any).hash = "71b0a1e7d209ed71a9bb6552eaf95cee"; (node as any).hash = "8a959080f5aa7cc752ce039bd7383dfa";
export default node; export default node;

View File

@@ -1,5 +1,5 @@
/** /**
* @generated SignedSource<<d8d76cb73e37916ddc34017550ff3702>> * @generated SignedSource<<544173fd0ab2731cb9d3a976212ceca5>>
* @lightSyntaxTransform * @lightSyntaxTransform
* @nogrep * @nogrep
*/ */
@@ -9,24 +9,24 @@
// @ts-nocheck // @ts-nocheck
import { ConcreteRequest } from 'relay-runtime'; import { ConcreteRequest } from 'relay-runtime';
export type UpdatePolicyVersionInput = { export type UpdateDocumentVersionInput = {
content: string; content: string;
policyVersionId: string; documentVersionId: string;
}; };
export type EditPolicyViewMutation$variables = { export type EditDocumentViewMutation$variables = {
input: UpdatePolicyVersionInput; input: UpdateDocumentVersionInput;
}; };
export type EditPolicyViewMutation$data = { export type EditDocumentViewMutation$data = {
readonly updatePolicyVersion: { readonly updateDocumentVersion: {
readonly policyVersion: { readonly documentVersion: {
readonly content: string; readonly content: string;
readonly id: string; readonly id: string;
}; };
}; };
}; };
export type EditPolicyViewMutation = { export type EditDocumentViewMutation = {
response: EditPolicyViewMutation$data; response: EditDocumentViewMutation$data;
variables: EditPolicyViewMutation$variables; variables: EditDocumentViewMutation$variables;
}; };
const node: ConcreteRequest = (function(){ const node: ConcreteRequest = (function(){
@@ -47,17 +47,17 @@ v1 = [
"variableName": "input" "variableName": "input"
} }
], ],
"concreteType": "UpdatePolicyVersionPayload", "concreteType": "UpdateDocumentVersionPayload",
"kind": "LinkedField", "kind": "LinkedField",
"name": "updatePolicyVersion", "name": "updateDocumentVersion",
"plural": false, "plural": false,
"selections": [ "selections": [
{ {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "PolicyVersion", "concreteType": "DocumentVersion",
"kind": "LinkedField", "kind": "LinkedField",
"name": "policyVersion", "name": "documentVersion",
"plural": false, "plural": false,
"selections": [ "selections": [
{ {
@@ -86,7 +86,7 @@ return {
"argumentDefinitions": (v0/*: any*/), "argumentDefinitions": (v0/*: any*/),
"kind": "Fragment", "kind": "Fragment",
"metadata": null, "metadata": null,
"name": "EditPolicyViewMutation", "name": "EditDocumentViewMutation",
"selections": (v1/*: any*/), "selections": (v1/*: any*/),
"type": "Mutation", "type": "Mutation",
"abstractKey": null "abstractKey": null
@@ -95,20 +95,20 @@ return {
"operation": { "operation": {
"argumentDefinitions": (v0/*: any*/), "argumentDefinitions": (v0/*: any*/),
"kind": "Operation", "kind": "Operation",
"name": "EditPolicyViewMutation", "name": "EditDocumentViewMutation",
"selections": (v1/*: any*/) "selections": (v1/*: any*/)
}, },
"params": { "params": {
"cacheID": "02b56043d606c6237dd502a7695fea50", "cacheID": "92e3e1e6d3bf1a2066b2e71c437c3b4e",
"id": null, "id": null,
"metadata": {}, "metadata": {},
"name": "EditPolicyViewMutation", "name": "EditDocumentViewMutation",
"operationKind": "mutation", "operationKind": "mutation",
"text": "mutation EditPolicyViewMutation(\n $input: UpdatePolicyVersionInput!\n) {\n updatePolicyVersion(input: $input) {\n policyVersion {\n id\n content\n }\n }\n}\n" "text": "mutation EditDocumentViewMutation(\n $input: UpdateDocumentVersionInput!\n) {\n updateDocumentVersion(input: $input) {\n documentVersion {\n id\n content\n }\n }\n}\n"
} }
}; };
})(); })();
(node as any).hash = "556fbcc4fadc0011c1a2154dcffeb389"; (node as any).hash = "14fc2fdfcdb2ccb827e237d5fc1f0a6f";
export default node; export default node;

View File

@@ -1,5 +1,5 @@
/** /**
* @generated SignedSource<<7738a95cc83ee25c08f6ddc556f144c1>> * @generated SignedSource<<d1a5426a3bb5920a1d2f94e4f689c93f>>
* @lightSyntaxTransform * @lightSyntaxTransform
* @nogrep * @nogrep
*/ */
@@ -10,16 +10,13 @@
import { ConcreteRequest } from 'relay-runtime'; import { ConcreteRequest } from 'relay-runtime';
import { FragmentRefs } from "relay-runtime"; import { FragmentRefs } from "relay-runtime";
export type EditPolicyViewQuery$variables = { export type EditDocumentViewQuery$variables = {
documentId: string;
documentVersionId: string;
organizationId: string; organizationId: string;
policyId: string;
policyVersionId: string;
}; };
export type EditPolicyViewQuery$data = { export type EditDocumentViewQuery$data = {
readonly organization: { readonly document: {
readonly " $fragmentSpreads": FragmentRefs<"PeopleSelector_organization">;
};
readonly policy: {
readonly id: string; readonly id: string;
readonly owner?: { readonly owner?: {
readonly fullName: string; readonly fullName: string;
@@ -27,37 +24,40 @@ export type EditPolicyViewQuery$data = {
}; };
readonly title?: string; readonly title?: string;
}; };
readonly policyVersion: { readonly documentVersion: {
readonly content?: string; readonly content?: string;
readonly id: string; readonly id: string;
}; };
readonly organization: {
readonly " $fragmentSpreads": FragmentRefs<"PeopleSelector_organization">;
};
}; };
export type EditPolicyViewQuery = { export type EditDocumentViewQuery = {
response: EditPolicyViewQuery$data; response: EditDocumentViewQuery$data;
variables: EditPolicyViewQuery$variables; variables: EditDocumentViewQuery$variables;
}; };
const node: ConcreteRequest = (function(){ const node: ConcreteRequest = (function(){
var v0 = { var v0 = {
"defaultValue": null, "defaultValue": null,
"kind": "LocalArgument", "kind": "LocalArgument",
"name": "organizationId" "name": "documentId"
}, },
v1 = { v1 = {
"defaultValue": null, "defaultValue": null,
"kind": "LocalArgument", "kind": "LocalArgument",
"name": "policyId" "name": "documentVersionId"
}, },
v2 = { v2 = {
"defaultValue": null, "defaultValue": null,
"kind": "LocalArgument", "kind": "LocalArgument",
"name": "policyVersionId" "name": "organizationId"
}, },
v3 = [ v3 = [
{ {
"kind": "Variable", "kind": "Variable",
"name": "id", "name": "id",
"variableName": "policyVersionId" "variableName": "documentVersionId"
} }
], ],
v4 = { v4 = {
@@ -78,14 +78,14 @@ v5 = {
"storageKey": null "storageKey": null
} }
], ],
"type": "PolicyVersion", "type": "DocumentVersion",
"abstractKey": null "abstractKey": null
}, },
v6 = [ v6 = [
{ {
"kind": "Variable", "kind": "Variable",
"name": "id", "name": "id",
"variableName": "policyId" "variableName": "documentId"
} }
], ],
v7 = { v7 = {
@@ -119,7 +119,7 @@ v8 = {
"storageKey": null "storageKey": null
} }
], ],
"type": "Policy", "type": "Document",
"abstractKey": null "abstractKey": null
}, },
v9 = [ v9 = [
@@ -160,10 +160,10 @@ return {
], ],
"kind": "Fragment", "kind": "Fragment",
"metadata": null, "metadata": null,
"name": "EditPolicyViewQuery", "name": "EditDocumentViewQuery",
"selections": [ "selections": [
{ {
"alias": "policyVersion", "alias": "documentVersion",
"args": (v3/*: any*/), "args": (v3/*: any*/),
"concreteType": null, "concreteType": null,
"kind": "LinkedField", "kind": "LinkedField",
@@ -176,7 +176,7 @@ return {
"storageKey": null "storageKey": null
}, },
{ {
"alias": "policy", "alias": "document",
"args": (v6/*: any*/), "args": (v6/*: any*/),
"concreteType": null, "concreteType": null,
"kind": "LinkedField", "kind": "LinkedField",
@@ -211,15 +211,15 @@ return {
"kind": "Request", "kind": "Request",
"operation": { "operation": {
"argumentDefinitions": [ "argumentDefinitions": [
(v1/*: any*/),
(v0/*: any*/), (v0/*: any*/),
(v2/*: any*/) (v2/*: any*/),
(v1/*: any*/)
], ],
"kind": "Operation", "kind": "Operation",
"name": "EditPolicyViewQuery", "name": "EditDocumentViewQuery",
"selections": [ "selections": [
{ {
"alias": "policyVersion", "alias": "documentVersion",
"args": (v3/*: any*/), "args": (v3/*: any*/),
"concreteType": null, "concreteType": null,
"kind": "LinkedField", "kind": "LinkedField",
@@ -233,7 +233,7 @@ return {
"storageKey": null "storageKey": null
}, },
{ {
"alias": "policy", "alias": "document",
"args": (v6/*: any*/), "args": (v6/*: any*/),
"concreteType": null, "concreteType": null,
"kind": "LinkedField", "kind": "LinkedField",
@@ -355,16 +355,16 @@ return {
] ]
}, },
"params": { "params": {
"cacheID": "4d586701fc5f2e4976bb87d9be61c594", "cacheID": "44dcce3514fd8798e8b7bb0c23f9f982",
"id": null, "id": null,
"metadata": {}, "metadata": {},
"name": "EditPolicyViewQuery", "name": "EditDocumentViewQuery",
"operationKind": "query", "operationKind": "query",
"text": "query EditPolicyViewQuery(\n $policyId: ID!\n $organizationId: ID!\n $policyVersionId: ID!\n) {\n policyVersion: node(id: $policyVersionId) {\n __typename\n id\n ... on PolicyVersion {\n content\n }\n }\n policy: node(id: $policyId) {\n __typename\n id\n ... on Policy {\n title\n owner {\n id\n fullName\n }\n }\n }\n organization: node(id: $organizationId) {\n __typename\n ...PeopleSelector_organization\n id\n }\n}\n\nfragment PeopleSelector_organization on Organization {\n id\n peoples(first: 100, orderBy: {direction: ASC, field: FULL_NAME}) {\n edges {\n node {\n id\n fullName\n primaryEmailAddress\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n}\n" "text": "query EditDocumentViewQuery(\n $documentId: ID!\n $organizationId: ID!\n $documentVersionId: ID!\n) {\n documentVersion: node(id: $documentVersionId) {\n __typename\n id\n ... on DocumentVersion {\n content\n }\n }\n document: node(id: $documentId) {\n __typename\n id\n ... on Document {\n title\n owner {\n id\n fullName\n }\n }\n }\n organization: node(id: $organizationId) {\n __typename\n ...PeopleSelector_organization\n id\n }\n}\n\nfragment PeopleSelector_organization on Organization {\n id\n peoples(first: 100, orderBy: {direction: ASC, field: FULL_NAME}) {\n edges {\n node {\n id\n fullName\n primaryEmailAddress\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n}\n"
} }
}; };
})(); })();
(node as any).hash = "2a934195ed33bd073e3976e8cc19a925"; (node as any).hash = "90a8a811c0c8a08a1112a72537cbd76d";
export default node; export default node;

View File

@@ -1,5 +1,5 @@
/** /**
* @generated SignedSource<<290d3c4fb382c7b99c60eeee5cfa8c5a>> * @generated SignedSource<<70539298ec9a6ffd64b14fa98fdd283e>>
* @lightSyntaxTransform * @lightSyntaxTransform
* @nogrep * @nogrep
*/ */
@@ -9,27 +9,27 @@
// @ts-nocheck // @ts-nocheck
import { ConcreteRequest } from 'relay-runtime'; import { ConcreteRequest } from 'relay-runtime';
export type PolicyStatus = "DRAFT" | "PUBLISHED"; export type DocumentStatus = "DRAFT" | "PUBLISHED";
export type CreateDraftPolicyVersionInput = { export type CreateDraftDocumentVersionInput = {
policyID: string; documentID: string;
}; };
export type ShowPolicyViewCreateDraftMutation$variables = { export type ShowDocumentViewCreateDraftMutation$variables = {
input: CreateDraftPolicyVersionInput; input: CreateDraftDocumentVersionInput;
}; };
export type ShowPolicyViewCreateDraftMutation$data = { export type ShowDocumentViewCreateDraftMutation$data = {
readonly createDraftPolicyVersion: { readonly createDraftDocumentVersion: {
readonly policyVersionEdge: { readonly documentVersionEdge: {
readonly node: { readonly node: {
readonly id: string; readonly id: string;
readonly status: PolicyStatus; readonly status: DocumentStatus;
readonly version: number; readonly version: number;
}; };
}; };
}; };
}; };
export type ShowPolicyViewCreateDraftMutation = { export type ShowDocumentViewCreateDraftMutation = {
response: ShowPolicyViewCreateDraftMutation$data; response: ShowDocumentViewCreateDraftMutation$data;
variables: ShowPolicyViewCreateDraftMutation$variables; variables: ShowDocumentViewCreateDraftMutation$variables;
}; };
const node: ConcreteRequest = (function(){ const node: ConcreteRequest = (function(){
@@ -50,23 +50,23 @@ v1 = [
"variableName": "input" "variableName": "input"
} }
], ],
"concreteType": "CreateDraftPolicyVersionPayload", "concreteType": "CreateDraftDocumentVersionPayload",
"kind": "LinkedField", "kind": "LinkedField",
"name": "createDraftPolicyVersion", "name": "createDraftDocumentVersion",
"plural": false, "plural": false,
"selections": [ "selections": [
{ {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "PolicyVersionEdge", "concreteType": "DocumentVersionEdge",
"kind": "LinkedField", "kind": "LinkedField",
"name": "policyVersionEdge", "name": "documentVersionEdge",
"plural": false, "plural": false,
"selections": [ "selections": [
{ {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "PolicyVersion", "concreteType": "DocumentVersion",
"kind": "LinkedField", "kind": "LinkedField",
"name": "node", "name": "node",
"plural": false, "plural": false,
@@ -107,7 +107,7 @@ return {
"argumentDefinitions": (v0/*: any*/), "argumentDefinitions": (v0/*: any*/),
"kind": "Fragment", "kind": "Fragment",
"metadata": null, "metadata": null,
"name": "ShowPolicyViewCreateDraftMutation", "name": "ShowDocumentViewCreateDraftMutation",
"selections": (v1/*: any*/), "selections": (v1/*: any*/),
"type": "Mutation", "type": "Mutation",
"abstractKey": null "abstractKey": null
@@ -116,20 +116,20 @@ return {
"operation": { "operation": {
"argumentDefinitions": (v0/*: any*/), "argumentDefinitions": (v0/*: any*/),
"kind": "Operation", "kind": "Operation",
"name": "ShowPolicyViewCreateDraftMutation", "name": "ShowDocumentViewCreateDraftMutation",
"selections": (v1/*: any*/) "selections": (v1/*: any*/)
}, },
"params": { "params": {
"cacheID": "e96d226e93260cd989dc122193fbcbce", "cacheID": "6ca94698731c59c1d5881a1dd3092277",
"id": null, "id": null,
"metadata": {}, "metadata": {},
"name": "ShowPolicyViewCreateDraftMutation", "name": "ShowDocumentViewCreateDraftMutation",
"operationKind": "mutation", "operationKind": "mutation",
"text": "mutation ShowPolicyViewCreateDraftMutation(\n $input: CreateDraftPolicyVersionInput!\n) {\n createDraftPolicyVersion(input: $input) {\n policyVersionEdge {\n node {\n id\n version\n status\n }\n }\n }\n}\n" "text": "mutation ShowDocumentViewCreateDraftMutation(\n $input: CreateDraftDocumentVersionInput!\n) {\n createDraftDocumentVersion(input: $input) {\n documentVersionEdge {\n node {\n id\n version\n status\n }\n }\n }\n}\n"
} }
}; };
})(); })();
(node as any).hash = "49282edca41fc2bdca1a1c6db4b2dc11"; (node as any).hash = "70edae5e8a303869b1686bb02fe4b22e";
export default node; export default node;

View File

@@ -1,5 +1,5 @@
/** /**
* @generated SignedSource<<024ec8d58aa5f37adad3ac5e98c15a90>> * @generated SignedSource<<91076d34daad785f7fce9f5a2cbc4018>>
* @lightSyntaxTransform * @lightSyntaxTransform
* @nogrep * @nogrep
*/ */
@@ -9,32 +9,32 @@
// @ts-nocheck // @ts-nocheck
import { ConcreteRequest } from 'relay-runtime'; import { ConcreteRequest } from 'relay-runtime';
export type PolicyStatus = "DRAFT" | "PUBLISHED"; export type DocumentStatus = "DRAFT" | "PUBLISHED";
export type PublishPolicyVersionInput = { export type PublishDocumentVersionInput = {
policyId: string; documentId: string;
}; };
export type ShowPolicyViewPublishMutation$variables = { export type ShowDocumentViewPublishMutation$variables = {
input: PublishPolicyVersionInput; input: PublishDocumentVersionInput;
}; };
export type ShowPolicyViewPublishMutation$data = { export type ShowDocumentViewPublishMutation$data = {
readonly publishPolicyVersion: { readonly publishDocumentVersion: {
readonly policy: { readonly document: {
readonly currentPublishedVersion: number | null | undefined; readonly currentPublishedVersion: number | null | undefined;
readonly id: string; readonly id: string;
}; };
readonly policyVersion: { readonly documentVersion: {
readonly id: string; readonly id: string;
readonly publishedAt: string | null | undefined; readonly publishedAt: string | null | undefined;
readonly publishedBy: { readonly publishedBy: {
readonly fullName: string; readonly fullName: string;
} | null | undefined; } | null | undefined;
readonly status: PolicyStatus; readonly status: DocumentStatus;
}; };
}; };
}; };
export type ShowPolicyViewPublishMutation = { export type ShowDocumentViewPublishMutation = {
response: ShowPolicyViewPublishMutation$data; response: ShowDocumentViewPublishMutation$data;
variables: ShowPolicyViewPublishMutation$variables; variables: ShowDocumentViewPublishMutation$variables;
}; };
const node: ConcreteRequest = (function(){ const node: ConcreteRequest = (function(){
@@ -62,9 +62,9 @@ v2 = {
v3 = { v3 = {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "Policy", "concreteType": "Document",
"kind": "LinkedField", "kind": "LinkedField",
"name": "policy", "name": "document",
"plural": false, "plural": false,
"selections": [ "selections": [
(v2/*: any*/), (v2/*: any*/),
@@ -104,23 +104,23 @@ return {
"argumentDefinitions": (v0/*: any*/), "argumentDefinitions": (v0/*: any*/),
"kind": "Fragment", "kind": "Fragment",
"metadata": null, "metadata": null,
"name": "ShowPolicyViewPublishMutation", "name": "ShowDocumentViewPublishMutation",
"selections": [ "selections": [
{ {
"alias": null, "alias": null,
"args": (v1/*: any*/), "args": (v1/*: any*/),
"concreteType": "PublishPolicyVersionPayload", "concreteType": "PublishDocumentVersionPayload",
"kind": "LinkedField", "kind": "LinkedField",
"name": "publishPolicyVersion", "name": "publishDocumentVersion",
"plural": false, "plural": false,
"selections": [ "selections": [
(v3/*: any*/), (v3/*: any*/),
{ {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "PolicyVersion", "concreteType": "DocumentVersion",
"kind": "LinkedField", "kind": "LinkedField",
"name": "policyVersion", "name": "documentVersion",
"plural": false, "plural": false,
"selections": [ "selections": [
(v2/*: any*/), (v2/*: any*/),
@@ -152,23 +152,23 @@ return {
"operation": { "operation": {
"argumentDefinitions": (v0/*: any*/), "argumentDefinitions": (v0/*: any*/),
"kind": "Operation", "kind": "Operation",
"name": "ShowPolicyViewPublishMutation", "name": "ShowDocumentViewPublishMutation",
"selections": [ "selections": [
{ {
"alias": null, "alias": null,
"args": (v1/*: any*/), "args": (v1/*: any*/),
"concreteType": "PublishPolicyVersionPayload", "concreteType": "PublishDocumentVersionPayload",
"kind": "LinkedField", "kind": "LinkedField",
"name": "publishPolicyVersion", "name": "publishDocumentVersion",
"plural": false, "plural": false,
"selections": [ "selections": [
(v3/*: any*/), (v3/*: any*/),
{ {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "PolicyVersion", "concreteType": "DocumentVersion",
"kind": "LinkedField", "kind": "LinkedField",
"name": "policyVersion", "name": "documentVersion",
"plural": false, "plural": false,
"selections": [ "selections": [
(v2/*: any*/), (v2/*: any*/),
@@ -196,16 +196,16 @@ return {
] ]
}, },
"params": { "params": {
"cacheID": "2047a011abeae6642230cb7b31080b08", "cacheID": "794539aab3ddce5d004e72d10b980ca4",
"id": null, "id": null,
"metadata": {}, "metadata": {},
"name": "ShowPolicyViewPublishMutation", "name": "ShowDocumentViewPublishMutation",
"operationKind": "mutation", "operationKind": "mutation",
"text": "mutation ShowPolicyViewPublishMutation(\n $input: PublishPolicyVersionInput!\n) {\n publishPolicyVersion(input: $input) {\n policy {\n id\n currentPublishedVersion\n }\n policyVersion {\n id\n status\n publishedAt\n publishedBy {\n fullName\n id\n }\n }\n }\n}\n" "text": "mutation ShowDocumentViewPublishMutation(\n $input: PublishDocumentVersionInput!\n) {\n publishDocumentVersion(input: $input) {\n document {\n id\n currentPublishedVersion\n }\n documentVersion {\n id\n status\n publishedAt\n publishedBy {\n fullName\n id\n }\n }\n }\n}\n"
} }
}; };
})(); })();
(node as any).hash = "d81485a797858cf5f2834cf131d248cc"; (node as any).hash = "66e590251b58966c2ac09625759332f7";
export default node; export default node;

View File

@@ -1,5 +1,5 @@
/** /**
* @generated SignedSource<<09afc0438feb0aa6a5a8a95f93d70951>> * @generated SignedSource<<f7c8f2df8a102d1bd15cb053d146a8b1>>
* @lightSyntaxTransform * @lightSyntaxTransform
* @nogrep * @nogrep
*/ */
@@ -10,12 +10,12 @@
import { ConcreteRequest } from 'relay-runtime'; import { ConcreteRequest } from 'relay-runtime';
import { FragmentRefs } from "relay-runtime"; import { FragmentRefs } from "relay-runtime";
export type PolicyStatus = "DRAFT" | "PUBLISHED"; export type DocumentStatus = "DRAFT" | "PUBLISHED";
export type ShowPolicyViewQuery$variables = { export type ShowDocumentViewQuery$variables = {
documentId: string;
organizationId: string; organizationId: string;
policyId: string;
}; };
export type ShowPolicyViewQuery$data = { export type ShowDocumentViewQuery$data = {
readonly node: { readonly node: {
readonly createdAt?: string; readonly createdAt?: string;
readonly currentPublishedVersion?: number | null | undefined; readonly currentPublishedVersion?: number | null | undefined;
@@ -32,7 +32,7 @@ export type ShowPolicyViewQuery$data = {
readonly publishedBy: { readonly publishedBy: {
readonly fullName: string; readonly fullName: string;
} | null | undefined; } | null | undefined;
readonly status: PolicyStatus; readonly status: DocumentStatus;
readonly updatedAt: string; readonly updatedAt: string;
readonly version: number; readonly version: number;
}; };
@@ -45,36 +45,38 @@ export type ShowPolicyViewQuery$data = {
}; };
readonly title?: string; readonly title?: string;
readonly updatedAt?: string; readonly updatedAt?: string;
readonly " $fragmentSpreads": FragmentRefs<"SignaturesModal_policyVersions" | "VersionHistoryModal_policyVersions">; readonly " $fragmentSpreads": FragmentRefs<"SignaturesModal_documentVersions" | "VersionHistoryModal_documentVersions">;
}; };
readonly organization: { readonly organization: {
readonly name?: string; readonly name?: string;
}; };
}; };
export type ShowPolicyViewQuery = { export type ShowDocumentViewQuery = {
response: ShowPolicyViewQuery$data; response: ShowDocumentViewQuery$data;
variables: ShowPolicyViewQuery$variables; variables: ShowDocumentViewQuery$variables;
}; };
const node: ConcreteRequest = (function(){ const node: ConcreteRequest = (function(){
var v0 = { var v0 = [
{
"defaultValue": null,
"kind": "LocalArgument",
"name": "documentId"
},
{
"defaultValue": null, "defaultValue": null,
"kind": "LocalArgument", "kind": "LocalArgument",
"name": "organizationId" "name": "organizationId"
}, }
v1 = { ],
"defaultValue": null, v1 = [
"kind": "LocalArgument",
"name": "policyId"
},
v2 = [
{ {
"kind": "Variable", "kind": "Variable",
"name": "id", "name": "id",
"variableName": "organizationId" "variableName": "organizationId"
} }
], ],
v3 = { v2 = {
"kind": "InlineFragment", "kind": "InlineFragment",
"selections": [ "selections": [
{ {
@@ -88,63 +90,63 @@ v3 = {
"type": "Organization", "type": "Organization",
"abstractKey": null "abstractKey": null
}, },
v4 = [ v3 = [
{ {
"kind": "Variable", "kind": "Variable",
"name": "id", "name": "id",
"variableName": "policyId" "variableName": "documentId"
} }
], ],
v5 = { v4 = {
"alias": null, "alias": null,
"args": null, "args": null,
"kind": "ScalarField", "kind": "ScalarField",
"name": "id", "name": "id",
"storageKey": null "storageKey": null
}, },
v6 = { v5 = {
"alias": null, "alias": null,
"args": null, "args": null,
"kind": "ScalarField", "kind": "ScalarField",
"name": "title", "name": "title",
"storageKey": null "storageKey": null
}, },
v7 = { v6 = {
"alias": null, "alias": null,
"args": null, "args": null,
"kind": "ScalarField", "kind": "ScalarField",
"name": "description", "name": "description",
"storageKey": null "storageKey": null
}, },
v8 = { v7 = {
"alias": null, "alias": null,
"args": null, "args": null,
"kind": "ScalarField", "kind": "ScalarField",
"name": "createdAt", "name": "createdAt",
"storageKey": null "storageKey": null
}, },
v9 = { v8 = {
"alias": null, "alias": null,
"args": null, "args": null,
"kind": "ScalarField", "kind": "ScalarField",
"name": "updatedAt", "name": "updatedAt",
"storageKey": null "storageKey": null
}, },
v10 = { v9 = {
"alias": null, "alias": null,
"args": null, "args": null,
"kind": "ScalarField", "kind": "ScalarField",
"name": "currentPublishedVersion", "name": "currentPublishedVersion",
"storageKey": null "storageKey": null
}, },
v11 = { v10 = {
"alias": null, "alias": null,
"args": null, "args": null,
"kind": "ScalarField", "kind": "ScalarField",
"name": "fullName", "name": "fullName",
"storageKey": null "storageKey": null
}, },
v12 = { v11 = {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "People", "concreteType": "People",
@@ -152,8 +154,8 @@ v12 = {
"name": "owner", "name": "owner",
"plural": false, "plural": false,
"selections": [ "selections": [
(v5/*: any*/), (v4/*: any*/),
(v11/*: any*/), (v10/*: any*/),
{ {
"alias": null, "alias": null,
"args": null, "args": null,
@@ -164,70 +166,70 @@ v12 = {
], ],
"storageKey": null "storageKey": null
}, },
v13 = [ v12 = [
{ {
"kind": "Literal", "kind": "Literal",
"name": "first", "name": "first",
"value": 1 "value": 1
} }
], ],
v14 = { v13 = {
"alias": null, "alias": null,
"args": null, "args": null,
"kind": "ScalarField", "kind": "ScalarField",
"name": "version", "name": "version",
"storageKey": null "storageKey": null
}, },
v15 = { v14 = {
"alias": null, "alias": null,
"args": null, "args": null,
"kind": "ScalarField", "kind": "ScalarField",
"name": "status", "name": "status",
"storageKey": null "storageKey": null
}, },
v16 = { v15 = {
"alias": null, "alias": null,
"args": null, "args": null,
"kind": "ScalarField", "kind": "ScalarField",
"name": "content", "name": "content",
"storageKey": null "storageKey": null
}, },
v17 = { v16 = {
"alias": null, "alias": null,
"args": null, "args": null,
"kind": "ScalarField", "kind": "ScalarField",
"name": "changelog", "name": "changelog",
"storageKey": null "storageKey": null
}, },
v18 = { v17 = {
"alias": null, "alias": null,
"args": null, "args": null,
"kind": "ScalarField", "kind": "ScalarField",
"name": "publishedAt", "name": "publishedAt",
"storageKey": null "storageKey": null
}, },
v19 = { v18 = {
"alias": null, "alias": null,
"args": null, "args": null,
"kind": "ScalarField", "kind": "ScalarField",
"name": "__typename", "name": "__typename",
"storageKey": null "storageKey": null
}, },
v20 = [ v19 = [
(v11/*: any*/), (v10/*: any*/),
(v5/*: any*/) (v4/*: any*/)
], ],
v21 = { v20 = {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "People", "concreteType": "People",
"kind": "LinkedField", "kind": "LinkedField",
"name": "publishedBy", "name": "publishedBy",
"plural": false, "plural": false,
"selections": (v20/*: any*/), "selections": (v19/*: any*/),
"storageKey": null "storageKey": null
}, },
v22 = [ v21 = [
{ {
"kind": "Literal", "kind": "Literal",
"name": "first", "name": "first",
@@ -236,58 +238,55 @@ v22 = [
]; ];
return { return {
"fragment": { "fragment": {
"argumentDefinitions": [ "argumentDefinitions": (v0/*: any*/),
(v0/*: any*/),
(v1/*: any*/)
],
"kind": "Fragment", "kind": "Fragment",
"metadata": null, "metadata": null,
"name": "ShowPolicyViewQuery", "name": "ShowDocumentViewQuery",
"selections": [ "selections": [
{ {
"alias": "organization", "alias": "organization",
"args": (v2/*: any*/), "args": (v1/*: any*/),
"concreteType": null, "concreteType": null,
"kind": "LinkedField", "kind": "LinkedField",
"name": "node", "name": "node",
"plural": false, "plural": false,
"selections": [ "selections": [
(v3/*: any*/) (v2/*: any*/)
], ],
"storageKey": null "storageKey": null
}, },
{ {
"alias": null, "alias": null,
"args": (v4/*: any*/), "args": (v3/*: any*/),
"concreteType": null, "concreteType": null,
"kind": "LinkedField", "kind": "LinkedField",
"name": "node", "name": "node",
"plural": false, "plural": false,
"selections": [ "selections": [
(v5/*: any*/), (v4/*: any*/),
{ {
"kind": "InlineFragment", "kind": "InlineFragment",
"selections": [ "selections": [
(v5/*: any*/),
(v6/*: any*/), (v6/*: any*/),
(v7/*: any*/), (v7/*: any*/),
(v8/*: any*/), (v8/*: any*/),
(v9/*: any*/), (v9/*: any*/),
(v10/*: any*/), (v11/*: any*/),
(v12/*: any*/),
{ {
"args": null, "args": null,
"kind": "FragmentSpread", "kind": "FragmentSpread",
"name": "SignaturesModal_policyVersions" "name": "SignaturesModal_documentVersions"
}, },
{ {
"args": null, "args": null,
"kind": "FragmentSpread", "kind": "FragmentSpread",
"name": "VersionHistoryModal_policyVersions" "name": "VersionHistoryModal_documentVersions"
}, },
{ {
"alias": "latestVersion", "alias": "latestVersion",
"args": (v13/*: any*/), "args": (v12/*: any*/),
"concreteType": "PolicyVersionConnection", "concreteType": "DocumentVersionConnection",
"kind": "LinkedField", "kind": "LinkedField",
"name": "versions", "name": "versions",
"plural": false, "plural": false,
@@ -295,7 +294,7 @@ return {
{ {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "PolicyVersionEdge", "concreteType": "DocumentVersionEdge",
"kind": "LinkedField", "kind": "LinkedField",
"name": "edges", "name": "edges",
"plural": true, "plural": true,
@@ -303,17 +302,17 @@ return {
{ {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "PolicyVersion", "concreteType": "DocumentVersion",
"kind": "LinkedField", "kind": "LinkedField",
"name": "node", "name": "node",
"plural": false, "plural": false,
"selections": [ "selections": [
(v5/*: any*/), (v4/*: any*/),
(v13/*: any*/),
(v14/*: any*/), (v14/*: any*/),
(v15/*: any*/), (v15/*: any*/),
(v16/*: any*/), (v16/*: any*/),
(v17/*: any*/), (v17/*: any*/),
(v18/*: any*/),
{ {
"alias": null, "alias": null,
"args": null, "args": null,
@@ -322,12 +321,12 @@ return {
"name": "publishedBy", "name": "publishedBy",
"plural": false, "plural": false,
"selections": [ "selections": [
(v11/*: any*/) (v10/*: any*/)
], ],
"storageKey": null "storageKey": null
}, },
(v8/*: any*/), (v7/*: any*/),
(v9/*: any*/) (v8/*: any*/)
], ],
"storageKey": null "storageKey": null
} }
@@ -338,7 +337,7 @@ return {
"storageKey": "versions(first:1)" "storageKey": "versions(first:1)"
} }
], ],
"type": "Policy", "type": "Document",
"abstractKey": null "abstractKey": null
} }
], ],
@@ -350,48 +349,45 @@ return {
}, },
"kind": "Request", "kind": "Request",
"operation": { "operation": {
"argumentDefinitions": [ "argumentDefinitions": (v0/*: any*/),
(v1/*: any*/),
(v0/*: any*/)
],
"kind": "Operation", "kind": "Operation",
"name": "ShowPolicyViewQuery", "name": "ShowDocumentViewQuery",
"selections": [ "selections": [
{ {
"alias": "organization", "alias": "organization",
"args": (v2/*: any*/), "args": (v1/*: any*/),
"concreteType": null, "concreteType": null,
"kind": "LinkedField", "kind": "LinkedField",
"name": "node", "name": "node",
"plural": false, "plural": false,
"selections": [ "selections": [
(v19/*: any*/), (v18/*: any*/),
(v3/*: any*/), (v2/*: any*/),
(v5/*: any*/) (v4/*: any*/)
], ],
"storageKey": null "storageKey": null
}, },
{ {
"alias": null, "alias": null,
"args": (v4/*: any*/), "args": (v3/*: any*/),
"concreteType": null, "concreteType": null,
"kind": "LinkedField", "kind": "LinkedField",
"name": "node", "name": "node",
"plural": false, "plural": false,
"selections": [ "selections": [
(v19/*: any*/), (v18/*: any*/),
(v5/*: any*/), (v4/*: any*/),
{ {
"kind": "InlineFragment", "kind": "InlineFragment",
"selections": [ "selections": [
(v5/*: any*/),
(v6/*: any*/), (v6/*: any*/),
(v7/*: any*/), (v7/*: any*/),
(v8/*: any*/), (v8/*: any*/),
(v9/*: any*/), (v9/*: any*/),
(v10/*: any*/), (v11/*: any*/),
(v12/*: any*/),
{ {
"alias": "policyVersions", "alias": "documentVersions",
"args": [ "args": [
{ {
"kind": "Literal", "kind": "Literal",
@@ -399,7 +395,7 @@ return {
"value": 10 "value": 10
} }
], ],
"concreteType": "PolicyVersionConnection", "concreteType": "DocumentVersionConnection",
"kind": "LinkedField", "kind": "LinkedField",
"name": "versions", "name": "versions",
"plural": false, "plural": false,
@@ -407,7 +403,7 @@ return {
{ {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "PolicyVersionEdge", "concreteType": "DocumentVersionEdge",
"kind": "LinkedField", "kind": "LinkedField",
"name": "edges", "name": "edges",
"plural": true, "plural": true,
@@ -415,21 +411,21 @@ return {
{ {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "PolicyVersion", "concreteType": "DocumentVersion",
"kind": "LinkedField", "kind": "LinkedField",
"name": "node", "name": "node",
"plural": false, "plural": false,
"selections": [ "selections": [
(v5/*: any*/), (v4/*: any*/),
(v13/*: any*/),
(v14/*: any*/), (v14/*: any*/),
(v15/*: any*/), (v17/*: any*/),
(v18/*: any*/), (v8/*: any*/),
(v9/*: any*/), (v20/*: any*/),
(v21/*: any*/),
{ {
"alias": null, "alias": null,
"args": (v22/*: any*/), "args": (v21/*: any*/),
"concreteType": "PolicyVersionSignatureConnection", "concreteType": "DocumentVersionSignatureConnection",
"kind": "LinkedField", "kind": "LinkedField",
"name": "signatures", "name": "signatures",
"plural": false, "plural": false,
@@ -437,7 +433,7 @@ return {
{ {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "PolicyVersionSignatureEdge", "concreteType": "DocumentVersionSignatureEdge",
"kind": "LinkedField", "kind": "LinkedField",
"name": "edges", "name": "edges",
"plural": true, "plural": true,
@@ -445,12 +441,12 @@ return {
{ {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "PolicyVersionSignature", "concreteType": "DocumentVersionSignature",
"kind": "LinkedField", "kind": "LinkedField",
"name": "node", "name": "node",
"plural": false, "plural": false,
"selections": [ "selections": [
(v5/*: any*/), (v4/*: any*/),
{ {
"alias": null, "alias": null,
"args": null, "args": null,
@@ -479,7 +475,7 @@ return {
"kind": "LinkedField", "kind": "LinkedField",
"name": "signedBy", "name": "signedBy",
"plural": false, "plural": false,
"selections": (v20/*: any*/), "selections": (v19/*: any*/),
"storageKey": null "storageKey": null
}, },
{ {
@@ -489,10 +485,10 @@ return {
"kind": "LinkedField", "kind": "LinkedField",
"name": "requestedBy", "name": "requestedBy",
"plural": false, "plural": false,
"selections": (v20/*: any*/), "selections": (v19/*: any*/),
"storageKey": null "storageKey": null
}, },
(v19/*: any*/) (v18/*: any*/)
], ],
"storageKey": null "storageKey": null
}, },
@@ -536,10 +532,10 @@ return {
}, },
{ {
"alias": null, "alias": null,
"args": (v22/*: any*/), "args": (v21/*: any*/),
"filters": null, "filters": null,
"handle": "connection", "handle": "connection",
"key": "SignaturesModal_policyVersions_signatures", "key": "SignaturesModal_documentVersions_signatures",
"kind": "LinkedHandle", "kind": "LinkedHandle",
"name": "signatures" "name": "signatures"
} }
@@ -561,7 +557,7 @@ return {
"value": 20 "value": 20
} }
], ],
"concreteType": "PolicyVersionConnection", "concreteType": "DocumentVersionConnection",
"kind": "LinkedField", "kind": "LinkedField",
"name": "versions", "name": "versions",
"plural": false, "plural": false,
@@ -569,7 +565,7 @@ return {
{ {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "PolicyVersionEdge", "concreteType": "DocumentVersionEdge",
"kind": "LinkedField", "kind": "LinkedField",
"name": "edges", "name": "edges",
"plural": true, "plural": true,
@@ -577,19 +573,19 @@ return {
{ {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "PolicyVersion", "concreteType": "DocumentVersion",
"kind": "LinkedField", "kind": "LinkedField",
"name": "node", "name": "node",
"plural": false, "plural": false,
"selections": [ "selections": [
(v5/*: any*/), (v4/*: any*/),
(v13/*: any*/),
(v14/*: any*/), (v14/*: any*/),
(v15/*: any*/), (v15/*: any*/),
(v16/*: any*/), (v16/*: any*/),
(v17/*: any*/), (v17/*: any*/),
(v18/*: any*/), (v8/*: any*/),
(v9/*: any*/), (v20/*: any*/)
(v21/*: any*/)
], ],
"storageKey": null "storageKey": null
} }
@@ -601,8 +597,8 @@ return {
}, },
{ {
"alias": "latestVersion", "alias": "latestVersion",
"args": (v13/*: any*/), "args": (v12/*: any*/),
"concreteType": "PolicyVersionConnection", "concreteType": "DocumentVersionConnection",
"kind": "LinkedField", "kind": "LinkedField",
"name": "versions", "name": "versions",
"plural": false, "plural": false,
@@ -610,7 +606,7 @@ return {
{ {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "PolicyVersionEdge", "concreteType": "DocumentVersionEdge",
"kind": "LinkedField", "kind": "LinkedField",
"name": "edges", "name": "edges",
"plural": true, "plural": true,
@@ -618,20 +614,20 @@ return {
{ {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "PolicyVersion", "concreteType": "DocumentVersion",
"kind": "LinkedField", "kind": "LinkedField",
"name": "node", "name": "node",
"plural": false, "plural": false,
"selections": [ "selections": [
(v5/*: any*/), (v4/*: any*/),
(v13/*: any*/),
(v14/*: any*/), (v14/*: any*/),
(v15/*: any*/), (v15/*: any*/),
(v16/*: any*/), (v16/*: any*/),
(v17/*: any*/), (v17/*: any*/),
(v18/*: any*/), (v20/*: any*/),
(v21/*: any*/), (v7/*: any*/),
(v8/*: any*/), (v8/*: any*/)
(v9/*: any*/)
], ],
"storageKey": null "storageKey": null
} }
@@ -642,7 +638,7 @@ return {
"storageKey": "versions(first:1)" "storageKey": "versions(first:1)"
} }
], ],
"type": "Policy", "type": "Document",
"abstractKey": null "abstractKey": null
} }
], ],
@@ -651,16 +647,16 @@ return {
] ]
}, },
"params": { "params": {
"cacheID": "643b6f01d617d7f7fa6995afe4960c3c", "cacheID": "16dd0ba75fa5a1339b59fa3e6bb9a6be",
"id": null, "id": null,
"metadata": {}, "metadata": {},
"name": "ShowPolicyViewQuery", "name": "ShowDocumentViewQuery",
"operationKind": "query", "operationKind": "query",
"text": "query ShowPolicyViewQuery(\n $policyId: ID!\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n ... on Organization {\n name\n }\n id\n }\n node(id: $policyId) {\n __typename\n id\n ... on Policy {\n title\n description\n createdAt\n updatedAt\n currentPublishedVersion\n owner {\n id\n fullName\n primaryEmailAddress\n }\n ...SignaturesModal_policyVersions\n ...VersionHistoryModal_policyVersions\n latestVersion: versions(first: 1) {\n edges {\n node {\n id\n version\n status\n content\n changelog\n publishedAt\n publishedBy {\n fullName\n id\n }\n createdAt\n updatedAt\n }\n }\n }\n }\n }\n}\n\nfragment SignaturesModal_policyVersions on Policy {\n title\n policyVersions: versions(first: 10) {\n edges {\n node {\n id\n version\n status\n publishedAt\n updatedAt\n publishedBy {\n fullName\n id\n }\n signatures(first: 100) {\n edges {\n node {\n id\n state\n signedAt\n requestedAt\n signedBy {\n fullName\n id\n }\n requestedBy {\n fullName\n id\n }\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n }\n }\n}\n\nfragment VersionHistoryModal_policyVersions on Policy {\n title\n owner {\n fullName\n id\n }\n versionHistory: versions(first: 20) {\n edges {\n node {\n id\n version\n status\n content\n changelog\n publishedAt\n updatedAt\n publishedBy {\n fullName\n id\n }\n }\n }\n }\n}\n" "text": "query ShowDocumentViewQuery(\n $documentId: ID!\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n ... on Organization {\n name\n }\n id\n }\n node(id: $documentId) {\n __typename\n id\n ... on Document {\n title\n description\n createdAt\n updatedAt\n currentPublishedVersion\n owner {\n id\n fullName\n primaryEmailAddress\n }\n ...SignaturesModal_documentVersions\n ...VersionHistoryModal_documentVersions\n latestVersion: versions(first: 1) {\n edges {\n node {\n id\n version\n status\n content\n changelog\n publishedAt\n publishedBy {\n fullName\n id\n }\n createdAt\n updatedAt\n }\n }\n }\n }\n }\n}\n\nfragment SignaturesModal_documentVersions on Document {\n title\n documentVersions: versions(first: 10) {\n edges {\n node {\n id\n version\n status\n publishedAt\n updatedAt\n publishedBy {\n fullName\n id\n }\n signatures(first: 100) {\n edges {\n node {\n id\n state\n signedAt\n requestedAt\n signedBy {\n fullName\n id\n }\n requestedBy {\n fullName\n id\n }\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n }\n }\n}\n\nfragment VersionHistoryModal_documentVersions on Document {\n title\n owner {\n fullName\n id\n }\n versionHistory: versions(first: 20) {\n edges {\n node {\n id\n version\n status\n content\n changelog\n publishedAt\n updatedAt\n publishedBy {\n fullName\n id\n }\n }\n }\n }\n}\n"
} }
}; };
})(); })();
(node as any).hash = "56b534c0a468ccee10939c7d6c731bfd"; (node as any).hash = "df52189b2fac349ac8588c518a4fce55";
export default node; export default node;

View File

@@ -1,5 +1,5 @@
/** /**
* @generated SignedSource<<fda822cf46d8b9a49852a53edd8e363d>> * @generated SignedSource<<b2f20948e0455b0ec2b79cc461e11242>>
* @lightSyntaxTransform * @lightSyntaxTransform
* @nogrep * @nogrep
*/ */
@@ -9,9 +9,9 @@
// @ts-nocheck // @ts-nocheck
import { ConcreteRequest } from 'relay-runtime'; import { ConcreteRequest } from 'relay-runtime';
export type PolicyVersionSignatureState = "REQUESTED" | "SIGNED"; export type DocumentVersionSignatureState = "REQUESTED" | "SIGNED";
export type RequestSignatureInput = { export type RequestSignatureInput = {
policyVersionId: string; documentVersionId: string;
signatoryId: string; signatoryId: string;
}; };
export type SignaturesModalRequestSignatureMutation$variables = { export type SignaturesModalRequestSignatureMutation$variables = {
@@ -20,7 +20,7 @@ export type SignaturesModalRequestSignatureMutation$variables = {
}; };
export type SignaturesModalRequestSignatureMutation$data = { export type SignaturesModalRequestSignatureMutation$data = {
readonly requestSignature: { readonly requestSignature: {
readonly policyVersionSignatureEdge: { readonly documentVersionSignatureEdge: {
readonly node: { readonly node: {
readonly id: string; readonly id: string;
readonly requestedAt: string; readonly requestedAt: string;
@@ -32,7 +32,7 @@ export type SignaturesModalRequestSignatureMutation$data = {
readonly fullName: string; readonly fullName: string;
readonly id: string; readonly id: string;
}; };
readonly state: PolicyVersionSignatureState; readonly state: DocumentVersionSignatureState;
}; };
}; };
}; };
@@ -130,15 +130,15 @@ return {
{ {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "PolicyVersionSignatureEdge", "concreteType": "DocumentVersionSignatureEdge",
"kind": "LinkedField", "kind": "LinkedField",
"name": "policyVersionSignatureEdge", "name": "documentVersionSignatureEdge",
"plural": false, "plural": false,
"selections": [ "selections": [
{ {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "PolicyVersionSignature", "concreteType": "DocumentVersionSignature",
"kind": "LinkedField", "kind": "LinkedField",
"name": "node", "name": "node",
"plural": false, "plural": false,
@@ -193,15 +193,15 @@ return {
{ {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "PolicyVersionSignatureEdge", "concreteType": "DocumentVersionSignatureEdge",
"kind": "LinkedField", "kind": "LinkedField",
"name": "policyVersionSignatureEdge", "name": "documentVersionSignatureEdge",
"plural": false, "plural": false,
"selections": [ "selections": [
{ {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "PolicyVersionSignature", "concreteType": "DocumentVersionSignature",
"kind": "LinkedField", "kind": "LinkedField",
"name": "node", "name": "node",
"plural": false, "plural": false,
@@ -234,7 +234,7 @@ return {
"handle": "prependEdge", "handle": "prependEdge",
"key": "", "key": "",
"kind": "LinkedHandle", "kind": "LinkedHandle",
"name": "policyVersionSignatureEdge", "name": "documentVersionSignatureEdge",
"handleArgs": [ "handleArgs": [
{ {
"kind": "Variable", "kind": "Variable",
@@ -249,16 +249,16 @@ return {
] ]
}, },
"params": { "params": {
"cacheID": "4c6a5b6ed95c76c157f8627409a4481b", "cacheID": "e3606c0b910024de4f5223961365d7cc",
"id": null, "id": null,
"metadata": {}, "metadata": {},
"name": "SignaturesModalRequestSignatureMutation", "name": "SignaturesModalRequestSignatureMutation",
"operationKind": "mutation", "operationKind": "mutation",
"text": "mutation SignaturesModalRequestSignatureMutation(\n $input: RequestSignatureInput!\n) {\n requestSignature(input: $input) {\n policyVersionSignatureEdge {\n node {\n id\n state\n signedAt\n requestedAt\n signedBy {\n fullName\n id\n }\n requestedBy {\n fullName\n id\n }\n }\n }\n }\n}\n" "text": "mutation SignaturesModalRequestSignatureMutation(\n $input: RequestSignatureInput!\n) {\n requestSignature(input: $input) {\n documentVersionSignatureEdge {\n node {\n id\n state\n signedAt\n requestedAt\n signedBy {\n fullName\n id\n }\n requestedBy {\n fullName\n id\n }\n }\n }\n }\n}\n"
} }
}; };
})(); })();
(node as any).hash = "2b17fe4feae2614a6697c63a7334a1cf"; (node as any).hash = "9cb16becf1319afbef638f6461179984";
export default node; export default node;

View File

@@ -1,5 +1,5 @@
/** /**
* @generated SignedSource<<ee81b03b50b0bc65932295b898b856d4>> * @generated SignedSource<<58ee8eb503fb92a720f2033c229e6895>>
* @lightSyntaxTransform * @lightSyntaxTransform
* @nogrep * @nogrep
*/ */
@@ -9,11 +9,11 @@
// @ts-nocheck // @ts-nocheck
import { ReaderFragment } from 'relay-runtime'; import { ReaderFragment } from 'relay-runtime';
export type PolicyStatus = "DRAFT" | "PUBLISHED"; export type DocumentStatus = "DRAFT" | "PUBLISHED";
export type PolicyVersionSignatureState = "REQUESTED" | "SIGNED"; export type DocumentVersionSignatureState = "REQUESTED" | "SIGNED";
import { FragmentRefs } from "relay-runtime"; import { FragmentRefs } from "relay-runtime";
export type SignaturesModal_policyVersions$data = { export type SignaturesModal_documentVersions$data = {
readonly policyVersions: { readonly documentVersions: {
readonly edges: ReadonlyArray<{ readonly edges: ReadonlyArray<{
readonly node: { readonly node: {
readonly id: string; readonly id: string;
@@ -34,22 +34,22 @@ export type SignaturesModal_policyVersions$data = {
readonly fullName: string; readonly fullName: string;
readonly id: string; readonly id: string;
}; };
readonly state: PolicyVersionSignatureState; readonly state: DocumentVersionSignatureState;
}; };
}>; }>;
}; };
readonly status: PolicyStatus; readonly status: DocumentStatus;
readonly updatedAt: string; readonly updatedAt: string;
readonly version: number; readonly version: number;
}; };
}>; }>;
}; };
readonly title: string; readonly title: string;
readonly " $fragmentType": "SignaturesModal_policyVersions"; readonly " $fragmentType": "SignaturesModal_documentVersions";
}; };
export type SignaturesModal_policyVersions$key = { export type SignaturesModal_documentVersions$key = {
readonly " $data"?: SignaturesModal_policyVersions$data; readonly " $data"?: SignaturesModal_documentVersions$data;
readonly " $fragmentSpreads": FragmentRefs<"SignaturesModal_policyVersions">; readonly " $fragmentSpreads": FragmentRefs<"SignaturesModal_documentVersions">;
}; };
const node: ReaderFragment = (function(){ const node: ReaderFragment = (function(){
@@ -83,7 +83,7 @@ return {
} }
] ]
}, },
"name": "SignaturesModal_policyVersions", "name": "SignaturesModal_documentVersions",
"selections": [ "selections": [
{ {
"alias": null, "alias": null,
@@ -93,7 +93,7 @@ return {
"storageKey": null "storageKey": null
}, },
{ {
"alias": "policyVersions", "alias": "documentVersions",
"args": [ "args": [
{ {
"kind": "Literal", "kind": "Literal",
@@ -101,7 +101,7 @@ return {
"value": 10 "value": 10
} }
], ],
"concreteType": "PolicyVersionConnection", "concreteType": "DocumentVersionConnection",
"kind": "LinkedField", "kind": "LinkedField",
"name": "versions", "name": "versions",
"plural": false, "plural": false,
@@ -109,7 +109,7 @@ return {
{ {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "PolicyVersionEdge", "concreteType": "DocumentVersionEdge",
"kind": "LinkedField", "kind": "LinkedField",
"name": "edges", "name": "edges",
"plural": true, "plural": true,
@@ -117,7 +117,7 @@ return {
{ {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "PolicyVersion", "concreteType": "DocumentVersion",
"kind": "LinkedField", "kind": "LinkedField",
"name": "node", "name": "node",
"plural": false, "plural": false,
@@ -164,15 +164,15 @@ return {
{ {
"alias": "signatures", "alias": "signatures",
"args": null, "args": null,
"concreteType": "PolicyVersionSignatureConnection", "concreteType": "DocumentVersionSignatureConnection",
"kind": "LinkedField", "kind": "LinkedField",
"name": "__SignaturesModal_policyVersions_signatures_connection", "name": "__SignaturesModal_documentVersions_signatures_connection",
"plural": false, "plural": false,
"selections": [ "selections": [
{ {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "PolicyVersionSignatureEdge", "concreteType": "DocumentVersionSignatureEdge",
"kind": "LinkedField", "kind": "LinkedField",
"name": "edges", "name": "edges",
"plural": true, "plural": true,
@@ -180,7 +180,7 @@ return {
{ {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "PolicyVersionSignature", "concreteType": "DocumentVersionSignature",
"kind": "LinkedField", "kind": "LinkedField",
"name": "node", "name": "node",
"plural": false, "plural": false,
@@ -288,11 +288,11 @@ return {
"storageKey": "versions(first:10)" "storageKey": "versions(first:10)"
} }
], ],
"type": "Policy", "type": "Document",
"abstractKey": null "abstractKey": null
}; };
})(); })();
(node as any).hash = "da9bf0fc12618afb0f9ec8f2337b9b9b"; (node as any).hash = "1e33c172b26b47a8fe21fdd66c9b4c26";
export default node; export default node;

View File

@@ -1,5 +1,5 @@
/** /**
* @generated SignedSource<<21626cad90fcb579071d73bc47e3fb7a>> * @generated SignedSource<<a88582302d627481e4214530f287e233>>
* @lightSyntaxTransform * @lightSyntaxTransform
* @nogrep * @nogrep
*/ */
@@ -9,9 +9,9 @@
// @ts-nocheck // @ts-nocheck
import { ReaderFragment } from 'relay-runtime'; import { ReaderFragment } from 'relay-runtime';
export type PolicyStatus = "DRAFT" | "PUBLISHED"; export type DocumentStatus = "DRAFT" | "PUBLISHED";
import { FragmentRefs } from "relay-runtime"; import { FragmentRefs } from "relay-runtime";
export type VersionHistoryModal_policyVersions$data = { export type VersionHistoryModal_documentVersions$data = {
readonly owner: { readonly owner: {
readonly fullName: string; readonly fullName: string;
}; };
@@ -26,17 +26,17 @@ export type VersionHistoryModal_policyVersions$data = {
readonly publishedBy: { readonly publishedBy: {
readonly fullName: string; readonly fullName: string;
} | null | undefined; } | null | undefined;
readonly status: PolicyStatus; readonly status: DocumentStatus;
readonly updatedAt: string; readonly updatedAt: string;
readonly version: number; readonly version: number;
}; };
}>; }>;
}; };
readonly " $fragmentType": "VersionHistoryModal_policyVersions"; readonly " $fragmentType": "VersionHistoryModal_documentVersions";
}; };
export type VersionHistoryModal_policyVersions$key = { export type VersionHistoryModal_documentVersions$key = {
readonly " $data"?: VersionHistoryModal_policyVersions$data; readonly " $data"?: VersionHistoryModal_documentVersions$data;
readonly " $fragmentSpreads": FragmentRefs<"VersionHistoryModal_policyVersions">; readonly " $fragmentSpreads": FragmentRefs<"VersionHistoryModal_documentVersions">;
}; };
const node: ReaderFragment = (function(){ const node: ReaderFragment = (function(){
@@ -53,7 +53,7 @@ return {
"argumentDefinitions": [], "argumentDefinitions": [],
"kind": "Fragment", "kind": "Fragment",
"metadata": null, "metadata": null,
"name": "VersionHistoryModal_policyVersions", "name": "VersionHistoryModal_documentVersions",
"selections": [ "selections": [
{ {
"alias": null, "alias": null,
@@ -81,7 +81,7 @@ return {
"value": 20 "value": 20
} }
], ],
"concreteType": "PolicyVersionConnection", "concreteType": "DocumentVersionConnection",
"kind": "LinkedField", "kind": "LinkedField",
"name": "versions", "name": "versions",
"plural": false, "plural": false,
@@ -89,7 +89,7 @@ return {
{ {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "PolicyVersionEdge", "concreteType": "DocumentVersionEdge",
"kind": "LinkedField", "kind": "LinkedField",
"name": "edges", "name": "edges",
"plural": true, "plural": true,
@@ -97,7 +97,7 @@ return {
{ {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "PolicyVersion", "concreteType": "DocumentVersion",
"kind": "LinkedField", "kind": "LinkedField",
"name": "node", "name": "node",
"plural": false, "plural": false,
@@ -171,11 +171,11 @@ return {
"storageKey": "versions(first:20)" "storageKey": "versions(first:20)"
} }
], ],
"type": "Policy", "type": "Document",
"abstractKey": null "abstractKey": null
}; };
})(); })();
(node as any).hash = "09cd9142880cfbb239ce866ea81afe48"; (node as any).hash = "ffcba061a60a144c663de41a48e784d1";
export default node; export default node;

View File

@@ -35,13 +35,13 @@ import {
} from "./__generated__/ControlOrganizationMeasuresQuery.graphql"; } from "./__generated__/ControlOrganizationMeasuresQuery.graphql";
import { ControlFragment_Control$key } from "./__generated__/ControlFragment_Control.graphql"; import { ControlFragment_Control$key } from "./__generated__/ControlFragment_Control.graphql";
import { import {
ControlLinkedPoliciesQuery$data, ControlLinkedDocumentsQuery$data,
ControlLinkedPoliciesQuery, ControlLinkedDocumentsQuery,
} from "./__generated__/ControlLinkedPoliciesQuery.graphql"; } from "./__generated__/ControlLinkedDocumentsQuery.graphql";
import { import {
ControlOrganizationPoliciesQuery$data, ControlOrganizationDocumentsQuery$data,
ControlOrganizationPoliciesQuery, ControlOrganizationDocumentsQuery,
} from "./__generated__/ControlOrganizationPoliciesQuery.graphql"; } from "./__generated__/ControlOrganizationDocumentsQuery.graphql";
const controlFragment = graphql` const controlFragment = graphql`
fragment ControlFragment_Control on Control { fragment ControlFragment_Control on Control {
@@ -96,13 +96,13 @@ const organizationMeasuresQuery = graphql`
} }
`; `;
// Query to fetch linked policies // Query to fetch linked documents
const linkedPoliciesQuery = graphql` const linkedDocumentsQuery = graphql`
query ControlLinkedPoliciesQuery($controlId: ID!) { query ControlLinkedDocumentsQuery($controlId: ID!) {
control: node(id: $controlId) { control: node(id: $controlId) {
id id
... on Control { ... on Control {
policies(first: 100) @connection(key: "Control__policies") { documents(first: 100) @connection(key: "Control__documents") {
edges { edges {
node { node {
id id
@@ -123,13 +123,13 @@ const linkedPoliciesQuery = graphql`
} }
`; `;
// Query to fetch all policies for the organization // Query to fetch all documents for the organization
const organizationPoliciesQuery = graphql` const organizationDocumentsQuery = graphql`
query ControlOrganizationPoliciesQuery($organizationId: ID!) { query ControlOrganizationDocumentsQuery($organizationId: ID!) {
organization: node(id: $organizationId) { organization: node(id: $organizationId) {
id id
... on Organization { ... on Organization {
policies(first: 100) @connection(key: "Organization__policies") { documents(first: 100) @connection(key: "Organization__documents") {
edges { edges {
node { node {
id id
@@ -176,12 +176,12 @@ const deleteMeasureMappingMutation = graphql`
} }
`; `;
// Mutation to create a mapping between a control and a policy // Mutation to create a mapping between a control and a document
const createPolicyMappingMutation = graphql` const createDocumentMappingMutation = graphql`
mutation ControlCreatePolicyMappingMutation( mutation ControlCreateDocumentMappingMutation(
$input: CreateControlPolicyMappingInput! $input: CreateControlDocumentMappingInput!
) { ) {
createControlPolicyMapping(input: $input) { createControlDocumentMapping(input: $input) {
controlEdge { controlEdge {
node { node {
id id
@@ -191,13 +191,13 @@ const createPolicyMappingMutation = graphql`
} }
`; `;
// Mutation to delete a mapping between a control and a policy // Mutation to delete a mapping between a control and a document
const deletePolicyMappingMutation = graphql` const deleteDocumentMappingMutation = graphql`
mutation ControlDeletePolicyMappingMutation( mutation ControlDeleteDocumentMappingMutation(
$input: DeleteControlPolicyMappingInput! $input: DeleteControlDocumentMappingInput!
) { ) {
deleteControlPolicyMapping(input: $input) { deleteControlDocumentMapping(input: $input) {
deletedPolicyId deletedDocumentId
} }
} }
`; `;
@@ -228,17 +228,17 @@ export function Control({
const [isUnlinkingMeasure, setIsUnlinkingMeasure] = useState(false); const [isUnlinkingMeasure, setIsUnlinkingMeasure] = useState(false);
const [categoryFilter, setCategoryFilter] = useState<string | null>(null); const [categoryFilter, setCategoryFilter] = useState<string | null>(null);
// Policy state // Document state
const [isPolicyMappingDialogOpen, setIsPolicyMappingDialogOpen] = const [isDocumentMappingDialogOpen, setIsDocumentMappingDialogOpen] =
useState(false); useState(false);
const [linkedPoliciesData, setLinkedPoliciesData] = const [linkedDocumentsData, setLinkedDocumentsData] =
useState<ControlLinkedPoliciesQuery$data | null>(null); useState<ControlLinkedDocumentsQuery$data | null>(null);
const [organizationPoliciesData, setOrganizationPoliciesData] = const [organizationDocumentsData, setOrganizationDocumentsData] =
useState<ControlOrganizationPoliciesQuery$data | null>(null); useState<ControlOrganizationDocumentsQuery$data | null>(null);
const [policySearchQuery, setPolicySearchQuery] = useState(""); const [documentSearchQuery, setDocumentSearchQuery] = useState("");
const [isLoadingPolicies, setIsLoadingPolicies] = useState(false); const [isLoadingDocuments, setIsLoadingDocuments] = useState(false);
const [isLinkingPolicy, setIsLinkingPolicy] = useState(false); const [isLinkingDocument, setIsLinkingDocument] = useState(false);
const [isUnlinkingPolicy, setIsUnlinkingPolicy] = useState(false); const [isUnlinkingDocument, setIsUnlinkingDocument] = useState(false);
// Create mutation hooks // Create mutation hooks
const [commitCreateMeasureMapping] = useMutation( const [commitCreateMeasureMapping] = useMutation(
@@ -247,8 +247,8 @@ export function Control({
const [commitDeleteMeasureMapping] = useMutation( const [commitDeleteMeasureMapping] = useMutation(
deleteMeasureMappingMutation deleteMeasureMappingMutation
); );
const [commitCreatePolicyMapping] = useMutation(createPolicyMappingMutation); const [commitCreateDocumentMapping] = useMutation(createDocumentMappingMutation);
const [commitDeletePolicyMapping] = useMutation(deletePolicyMappingMutation); const [commitDeleteDocumentMapping] = useMutation(deleteDocumentMappingMutation);
// Load initial linked measures data // Load initial linked measures data
useEffect(() => { useEffect(() => {
@@ -508,242 +508,242 @@ export function Control({
setIsMeasureMappingDialogOpen(true); setIsMeasureMappingDialogOpen(true);
}, [loadMeasuresData]); }, [loadMeasuresData]);
// Load initial linked policies data // Load initial linked documents data
useEffect(() => { useEffect(() => {
if (control.id) { if (control.id) {
setIsLoadingPolicies(true); setIsLoadingDocuments(true);
fetchQuery<ControlLinkedPoliciesQuery>(environment, linkedPoliciesQuery, { fetchQuery<ControlLinkedDocumentsQuery>(environment, linkedDocumentsQuery, {
controlId: control.id, controlId: control.id,
}).subscribe({ }).subscribe({
next: (data) => { next: (data) => {
setLinkedPoliciesData(data); setLinkedDocumentsData(data);
setIsLoadingPolicies(false); setIsLoadingDocuments(false);
}, },
error: (error: Error) => { error: (error: Error) => {
console.error("Error loading initial policies:", error); console.error("Error loading initial documents:", error);
setIsLoadingPolicies(false); setIsLoadingDocuments(false);
}, },
}); });
} }
}, [control.id, environment]); }, [control.id, environment]);
// Load policies data // Load documents data
const loadPoliciesData = useCallback(() => { const loadDocumentsData = useCallback(() => {
if (!organizationId || !control.id) return; if (!organizationId || !control.id) return;
setIsLoadingPolicies(true); setIsLoadingDocuments(true);
// Fetch all policies for the organization // Fetch all documents for the organization
fetchQuery<ControlOrganizationPoliciesQuery>( fetchQuery<ControlOrganizationDocumentsQuery>(
environment, environment,
organizationPoliciesQuery, organizationDocumentsQuery,
{ {
organizationId, organizationId,
} }
).subscribe({ ).subscribe({
next: (data) => { next: (data) => {
setOrganizationPoliciesData(data); setOrganizationDocumentsData(data);
}, },
complete: () => { complete: () => {
// Fetch linked policies for this control // Fetch linked documents for this control
fetchQuery<ControlLinkedPoliciesQuery>( fetchQuery<ControlLinkedDocumentsQuery>(
environment, environment,
linkedPoliciesQuery, linkedDocumentsQuery,
{ {
controlId: control.id, controlId: control.id,
} }
).subscribe({ ).subscribe({
next: (data) => { next: (data) => {
setLinkedPoliciesData(data); setLinkedDocumentsData(data);
setIsLoadingPolicies(false); setIsLoadingDocuments(false);
}, },
error: (error: Error) => { error: (error: Error) => {
console.error("Error fetching linked policies:", error); console.error("Error fetching linked documents:", error);
setIsLoadingPolicies(false); setIsLoadingDocuments(false);
toast({ toast({
title: "Error", title: "Error",
description: "Failed to load linked policies.", description: "Failed to load linked documents.",
variant: "destructive", variant: "destructive",
}); });
}, },
}); });
}, },
error: (error: Error) => { error: (error: Error) => {
console.error("Error fetching organization policies:", error); console.error("Error fetching organization documents:", error);
setIsLoadingPolicies(false); setIsLoadingDocuments(false);
toast({ toast({
title: "Error", title: "Error",
description: "Failed to load policies.", description: "Failed to load documents.",
variant: "destructive", variant: "destructive",
}); });
}, },
}); });
}, [control.id, environment, organizationId, toast]); }, [control.id, environment, organizationId, toast]);
// Policy helper functions // Document helper functions
const getPolicies = useCallback(() => { const getDocuments = useCallback(() => {
if (!organizationPoliciesData?.organization?.policies?.edges) return []; if (!organizationDocumentsData?.organization?.documents?.edges) return [];
return organizationPoliciesData.organization.policies.edges.map( return organizationDocumentsData.organization.documents.edges.map(
(edge) => edge.node (edge) => edge.node
); );
}, [organizationPoliciesData]); }, [organizationDocumentsData]);
const getLinkedPolicies = useCallback(() => { const getLinkedDocuments = useCallback(() => {
if (!linkedPoliciesData?.control?.policies?.edges) return []; if (!linkedDocumentsData?.control?.documents?.edges) return [];
return linkedPoliciesData.control.policies.edges.map((edge) => edge.node); return linkedDocumentsData.control.documents.edges.map((edge) => edge.node);
}, [linkedPoliciesData]); }, [linkedDocumentsData]);
const isPolicyLinked = useCallback( const isDocumentLinked = useCallback(
(policyId: string) => { (documentId: string) => {
const linkedPolicies = getLinkedPolicies(); const linkedDocuments = getLinkedDocuments();
return linkedPolicies.some((policy) => policy.id === policyId); return linkedDocuments.some((document) => document.id === documentId);
}, },
[getLinkedPolicies] [getLinkedDocuments]
); );
const filteredPolicies = useCallback(() => { const filteredDocuments = useCallback(() => {
const policies = getPolicies(); const documents = getDocuments();
if (!policySearchQuery) return policies; if (!documentSearchQuery) return documents;
return policies.filter((policy) => { return documents.filter((document) => {
return ( return (
!policySearchQuery || !documentSearchQuery ||
policy.title?.toLowerCase().includes(policySearchQuery.toLowerCase()) || document.title?.toLowerCase().includes(documentSearchQuery.toLowerCase()) ||
(policy.description && (document.description &&
policy.description document.description
.toLowerCase() .toLowerCase()
.includes(policySearchQuery.toLowerCase())) .includes(documentSearchQuery.toLowerCase()))
); );
}); });
}, [getPolicies, policySearchQuery]); }, [getDocuments, documentSearchQuery]);
// Policy link/unlink handlers // Document link/unlink handlers
const handleLinkPolicy = useCallback( const handleLinkDocument = useCallback(
(policyId: string) => { (documentId: string) => {
if (!control.id) return; if (!control.id) return;
setIsLinkingPolicy(true); setIsLinkingDocument(true);
commitCreatePolicyMapping({ commitCreateDocumentMapping({
variables: { variables: {
input: { input: {
controlId: control.id, controlId: control.id,
policyId: policyId, documentId: documentId,
}, },
}, },
onCompleted: (_, errors) => { onCompleted: (_, errors) => {
setIsLinkingPolicy(false); setIsLinkingDocument(false);
if (errors) { if (errors) {
console.error("Error linking policy:", errors); console.error("Error linking document:", errors);
toast({ toast({
title: "Error", title: "Error",
description: "Failed to link policy. Please try again.", description: "Failed to link document. Please try again.",
variant: "destructive", variant: "destructive",
}); });
return; return;
} }
// Refresh linked policies data // Refresh linked documents data
fetchQuery<ControlLinkedPoliciesQuery>( fetchQuery<ControlLinkedDocumentsQuery>(
environment, environment,
linkedPoliciesQuery, linkedDocumentsQuery,
{ {
controlId: control.id, controlId: control.id,
} }
).subscribe({ ).subscribe({
next: (data) => { next: (data) => {
setLinkedPoliciesData(data); setLinkedDocumentsData(data);
}, },
error: (error: Error) => { error: (error: Error) => {
console.error("Error refreshing linked policies:", error); console.error("Error refreshing linked documents:", error);
}, },
}); });
toast({ toast({
title: "Success", title: "Success",
description: "Policy successfully linked to control.", description: "Document successfully linked to control.",
}); });
}, },
onError: (error) => { onError: (error) => {
setIsLinkingPolicy(false); setIsLinkingDocument(false);
console.error("Error linking policy:", error); console.error("Error linking document:", error);
toast({ toast({
title: "Error", title: "Error",
description: "Failed to link policy. Please try again.", description: "Failed to link document. Please try again.",
variant: "destructive", variant: "destructive",
}); });
}, },
}); });
}, },
[commitCreatePolicyMapping, control.id, environment, toast] [commitCreateDocumentMapping, control.id, environment, toast]
); );
const handleUnlinkPolicy = useCallback( const handleUnlinkDocument = useCallback(
(policyId: string) => { (documentId: string) => {
if (!control.id) return; if (!control.id) return;
setIsUnlinkingPolicy(true); setIsUnlinkingDocument(true);
commitDeletePolicyMapping({ commitDeleteDocumentMapping({
variables: { variables: {
input: { input: {
controlId: control.id, controlId: control.id,
policyId: policyId, documentId: documentId,
}, },
}, },
onCompleted: (_, errors) => { onCompleted: (_, errors) => {
setIsUnlinkingPolicy(false); setIsUnlinkingDocument(false);
if (errors) { if (errors) {
console.error("Error unlinking policy:", errors); console.error("Error unlinking document:", errors);
toast({ toast({
title: "Error", title: "Error",
description: "Failed to unlink policy. Please try again.", description: "Failed to unlink document. Please try again.",
variant: "destructive", variant: "destructive",
}); });
return; return;
} }
// Refresh linked policies data // Refresh linked documents data
fetchQuery<ControlLinkedPoliciesQuery>( fetchQuery<ControlLinkedDocumentsQuery>(
environment, environment,
linkedPoliciesQuery, linkedDocumentsQuery,
{ {
controlId: control.id, controlId: control.id,
} }
).subscribe({ ).subscribe({
next: (data) => { next: (data) => {
setLinkedPoliciesData(data); setLinkedDocumentsData(data);
}, },
error: (error: Error) => { error: (error: Error) => {
console.error("Error refreshing linked policies:", error); console.error("Error refreshing linked documents:", error);
}, },
}); });
toast({ toast({
title: "Success", title: "Success",
description: "Policy successfully unlinked from control.", description: "Document successfully unlinked from control.",
}); });
}, },
onError: (error) => { onError: (error) => {
setIsUnlinkingPolicy(false); setIsUnlinkingDocument(false);
console.error("Error unlinking policy:", error); console.error("Error unlinking document:", error);
toast({ toast({
title: "Error", title: "Error",
description: "Failed to unlink policy. Please try again.", description: "Failed to unlink document. Please try again.",
variant: "destructive", variant: "destructive",
}); });
}, },
}); });
}, },
[commitDeletePolicyMapping, control.id, environment, toast] [commitDeleteDocumentMapping, control.id, environment, toast]
); );
const handleOpenPolicyMappingDialog = useCallback(() => { const handleOpenDocumentMappingDialog = useCallback(() => {
loadPoliciesData(); loadDocumentsData();
setIsPolicyMappingDialogOpen(true); setIsDocumentMappingDialogOpen(true);
}, [loadPoliciesData]); }, [loadDocumentsData]);
const formatState = (state: string | undefined): string => { const formatState = (state: string | undefined): string => {
if (!state) return "Unknown"; if (!state) return "Unknown";
@@ -1045,19 +1045,19 @@ export function Control({
</div> </div>
</div> </div>
{/* Policies Section */} {/* Documents Section */}
<div className="mt-8"> <div className="mt-8">
{/* Policy Mapping Dialog */} {/* Document Mapping Dialog */}
<Dialog <Dialog
open={isPolicyMappingDialogOpen} open={isDocumentMappingDialogOpen}
onOpenChange={setIsPolicyMappingDialogOpen} onOpenChange={setIsDocumentMappingDialogOpen}
> >
<DialogContent className="max-w-3xl max-h-[80vh] overflow-hidden flex flex-col"> <DialogContent className="max-w-3xl max-h-[80vh] overflow-hidden flex flex-col">
<DialogHeader> <DialogHeader>
<DialogTitle>Link Policies to Control</DialogTitle> <DialogTitle>Link Documents to Control</DialogTitle>
<DialogDescription> <DialogDescription>
Search and select policies to link to this control. This helps Search and select documents to link to this control. This helps
track which policies address this control. track which documents address this control.
</DialogDescription> </DialogDescription>
</DialogHeader> </DialogHeader>
@@ -1066,9 +1066,9 @@ export function Control({
<div className="relative"> <div className="relative">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-tertiary" /> <Search className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-tertiary" />
<Input <Input
placeholder="Search policies by name or content..." placeholder="Search documents by name or content..."
value={policySearchQuery} value={documentSearchQuery}
onChange={(e) => setPolicySearchQuery(e.target.value)} onChange={(e) => setDocumentSearchQuery(e.target.value)}
className="w-full pl-10" className="w-full pl-10"
/> />
</div> </div>
@@ -1076,16 +1076,16 @@ export function Control({
</div> </div>
<div className="flex-1 overflow-hidden"> <div className="flex-1 overflow-hidden">
{isLoadingPolicies ? ( {isLoadingDocuments ? (
<div className="flex items-center justify-center h-full"> <div className="flex items-center justify-center h-full">
<Loader2 className="w-8 h-8 animate-spin text-info" /> <Loader2 className="w-8 h-8 animate-spin text-info" />
<span className="ml-2">Loading policies...</span> <span className="ml-2">Loading documents...</span>
</div> </div>
) : ( ) : (
<div className="max-h-[50vh] overflow-y-auto pr-2"> <div className="max-h-[50vh] overflow-y-auto pr-2">
{filteredPolicies().length === 0 ? ( {filteredDocuments().length === 0 ? (
<div className="text-center py-8 text-secondary"> <div className="text-center py-8 text-secondary">
No policies found. Try adjusting your search. No documents found. Try adjusting your search.
</div> </div>
) : ( ) : (
<table className="w-full bg-level-1"> <table className="w-full bg-level-1">
@@ -1101,27 +1101,27 @@ export function Control({
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{filteredPolicies().map((policy) => { {filteredDocuments().map((document) => {
const isLinked = isPolicyLinked(policy.id); const isLinked = isDocumentLinked(document.id);
return ( return (
<tr <tr
key={policy.id} key={document.id}
className="border-b hover:bg-invert-bg" className="border-b hover:bg-invert-bg"
> >
<td className="py-3 px-4"> <td className="py-3 px-4">
<div className="font-medium"> <div className="font-medium">
{policy.title} {document.title}
</div> </div>
{policy.description && ( {document.description && (
<div className="text-xs text-secondary line-clamp-1 mt-0.5"> <div className="text-xs text-secondary line-clamp-1 mt-0.5">
{policy.description} {document.description}
</div> </div>
)} )}
</td> </td>
<td className="py-3 px-4"> <td className="py-3 px-4">
{policy.updatedAt {document.updatedAt
? new Date( ? new Date(
policy.updatedAt document.updatedAt
).toLocaleDateString() ).toLocaleDateString()
: "Not set"} : "Not set"}
</td> </td>
@@ -1131,12 +1131,12 @@ export function Control({
variant="outline" variant="outline"
size="sm" size="sm"
onClick={() => onClick={() =>
handleUnlinkPolicy(policy.id) handleUnlinkDocument(document.id)
} }
disabled={isUnlinkingPolicy} disabled={isUnlinkingDocument}
className="text-xs h-7 text-danger border-danger-b hover:bg-h-danger-bg" className="text-xs h-7 text-danger border-danger-b hover:bg-h-danger-bg"
> >
{isUnlinkingPolicy ? ( {isUnlinkingDocument ? (
<Loader2 className="w-4 h-4 animate-spin" /> <Loader2 className="w-4 h-4 animate-spin" />
) : ( ) : (
<X className="w-4 h-4" /> <X className="w-4 h-4" />
@@ -1148,12 +1148,12 @@ export function Control({
variant="secondary" variant="secondary"
size="sm" size="sm"
onClick={() => onClick={() =>
handleLinkPolicy(policy.id) handleLinkDocument(document.id)
} }
disabled={isLinkingPolicy} disabled={isLinkingDocument}
className="text-xs h-7 text-info border-info-b hover:bg-h-info-bg" className="text-xs h-7 text-info border-info-b hover:bg-h-info-bg"
> >
{isLinkingPolicy ? ( {isLinkingDocument ? (
<Loader2 className="w-4 h-4 animate-spin" /> <Loader2 className="w-4 h-4 animate-spin" />
) : ( ) : (
<LinkIcon className="w-4 h-4" /> <LinkIcon className="w-4 h-4" />
@@ -1173,35 +1173,35 @@ export function Control({
</div> </div>
<DialogFooter className="mt-4"> <DialogFooter className="mt-4">
<Button onClick={() => setIsPolicyMappingDialogOpen(false)}> <Button onClick={() => setIsDocumentMappingDialogOpen(false)}>
Close Close
</Button> </Button>
</DialogFooter> </DialogFooter>
</DialogContent> </DialogContent>
</Dialog> </Dialog>
{/* Linked Policies List */} {/* Linked Documents List */}
<div> <div>
<div className="flex justify-between items-center mb-4"> <div className="flex justify-between items-center mb-4">
<h3 className="text-xl font-medium text-secondary">Policies</h3> <h3 className="text-xl font-medium text-secondary">Documents</h3>
<Button <Button
variant="outline" variant="outline"
size="sm" size="sm"
className="flex items-center gap-1" className="flex items-center gap-1"
onClick={handleOpenPolicyMappingDialog} onClick={handleOpenDocumentMappingDialog}
> >
<LinkIcon className="w-4 h-4" /> <LinkIcon className="w-4 h-4" />
<span>Link Policies</span> <span>Link Documents</span>
</Button> </Button>
</div> </div>
{isLoadingPolicies ? ( {isLoadingDocuments ? (
<div className="flex items-center justify-center h-24"> <div className="flex items-center justify-center h-24">
<Loader2 className="w-6 h-6 animate-spin text-info" /> <Loader2 className="w-6 h-6 animate-spin text-info" />
<span className="ml-2">Loading policies...</span> <span className="ml-2">Loading documents...</span>
</div> </div>
) : linkedPoliciesData?.control?.policies?.edges && ) : linkedDocumentsData?.control?.documents?.edges &&
linkedPoliciesData.control.policies.edges.length > 0 ? ( linkedDocumentsData.control.documents.edges.length > 0 ? (
<div className="overflow-x-auto border rounded-md"> <div className="overflow-x-auto border rounded-md">
<table className="w-full"> <table className="w-full">
<thead> <thead>
@@ -1214,22 +1214,22 @@ export function Control({
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{getLinkedPolicies().map((policy) => ( {getLinkedDocuments().map((document) => (
<tr <tr
key={policy.id} key={document.id}
className="border-b hover:bg-invert-bg" className="border-b hover:bg-invert-bg"
> >
<td className="py-3 px-4"> <td className="py-3 px-4">
<div className="font-medium">{policy.title}</div> <div className="font-medium">{document.title}</div>
{policy.description && ( {document.description && (
<div className="text-xs text-secondary line-clamp-1 mt-0.5"> <div className="text-xs text-secondary line-clamp-1 mt-0.5">
{policy.description} {document.description}
</div> </div>
)} )}
</td> </td>
<td className="py-3 px-4"> <td className="py-3 px-4">
{policy.updatedAt {document.updatedAt
? new Date(policy.updatedAt).toLocaleDateString() ? new Date(document.updatedAt).toLocaleDateString()
: "Not set"} : "Not set"}
</td> </td>
<td className="py-3 px-4 text-right whitespace-nowrap"> <td className="py-3 px-4 text-right whitespace-nowrap">
@@ -1241,7 +1241,7 @@ export function Control({
className="text-xs h-7" className="text-xs h-7"
> >
<Link <Link
to={`/organizations/${organizationId}/policies/${policy.id}`} to={`/organizations/${organizationId}/documents/${document.id}`}
> >
View View
</Link> </Link>
@@ -1249,8 +1249,8 @@ export function Control({
<Button <Button
variant="outline" variant="outline"
size="sm" size="sm"
onClick={() => handleUnlinkPolicy(policy.id)} onClick={() => handleUnlinkDocument(document.id)}
disabled={isUnlinkingPolicy} disabled={isUnlinkingDocument}
className="text-xs h-7 text-danger border-danger-b hover:bg-h-danger-bg" className="text-xs h-7 text-danger border-danger-b hover:bg-h-danger-bg"
> >
Unlink Unlink
@@ -1264,8 +1264,8 @@ export function Control({
</div> </div>
) : ( ) : (
<div className="text-center py-8 text-secondary border rounded-md"> <div className="text-center py-8 text-secondary border rounded-md">
No policies linked to this control yet. Click &quot;Link No documents linked to this control yet. Click &quot;Link
Policies&quot; to connect some. Documents&quot; to connect some.
</div> </div>
)} )}
</div> </div>

View File

@@ -1,5 +1,5 @@
/** /**
* @generated SignedSource<<9e8a7131004ab3ef4f20c36c904bd9db>> * @generated SignedSource<<50d6cda002b6548d568947de29ef3971>>
* @lightSyntaxTransform * @lightSyntaxTransform
* @nogrep * @nogrep
*/ */
@@ -9,15 +9,15 @@
// @ts-nocheck // @ts-nocheck
import { ConcreteRequest } from 'relay-runtime'; import { ConcreteRequest } from 'relay-runtime';
export type CreateControlPolicyMappingInput = { export type CreateControlDocumentMappingInput = {
controlId: string; controlId: string;
policyId: string; documentId: string;
}; };
export type ControlCreatePolicyMappingMutation$variables = { export type ControlCreateDocumentMappingMutation$variables = {
input: CreateControlPolicyMappingInput; input: CreateControlDocumentMappingInput;
}; };
export type ControlCreatePolicyMappingMutation$data = { export type ControlCreateDocumentMappingMutation$data = {
readonly createControlPolicyMapping: { readonly createControlDocumentMapping: {
readonly controlEdge: { readonly controlEdge: {
readonly node: { readonly node: {
readonly id: string; readonly id: string;
@@ -25,9 +25,9 @@ export type ControlCreatePolicyMappingMutation$data = {
}; };
}; };
}; };
export type ControlCreatePolicyMappingMutation = { export type ControlCreateDocumentMappingMutation = {
response: ControlCreatePolicyMappingMutation$data; response: ControlCreateDocumentMappingMutation$data;
variables: ControlCreatePolicyMappingMutation$variables; variables: ControlCreateDocumentMappingMutation$variables;
}; };
const node: ConcreteRequest = (function(){ const node: ConcreteRequest = (function(){
@@ -48,9 +48,9 @@ v1 = [
"variableName": "input" "variableName": "input"
} }
], ],
"concreteType": "CreateControlPolicyMappingPayload", "concreteType": "CreateControlDocumentMappingPayload",
"kind": "LinkedField", "kind": "LinkedField",
"name": "createControlPolicyMapping", "name": "createControlDocumentMapping",
"plural": false, "plural": false,
"selections": [ "selections": [
{ {
@@ -91,7 +91,7 @@ return {
"argumentDefinitions": (v0/*: any*/), "argumentDefinitions": (v0/*: any*/),
"kind": "Fragment", "kind": "Fragment",
"metadata": null, "metadata": null,
"name": "ControlCreatePolicyMappingMutation", "name": "ControlCreateDocumentMappingMutation",
"selections": (v1/*: any*/), "selections": (v1/*: any*/),
"type": "Mutation", "type": "Mutation",
"abstractKey": null "abstractKey": null
@@ -100,20 +100,20 @@ return {
"operation": { "operation": {
"argumentDefinitions": (v0/*: any*/), "argumentDefinitions": (v0/*: any*/),
"kind": "Operation", "kind": "Operation",
"name": "ControlCreatePolicyMappingMutation", "name": "ControlCreateDocumentMappingMutation",
"selections": (v1/*: any*/) "selections": (v1/*: any*/)
}, },
"params": { "params": {
"cacheID": "d2cf3e45fcc9109399c3b80addb03b20", "cacheID": "44eba73b10ac45d65d97c96098260898",
"id": null, "id": null,
"metadata": {}, "metadata": {},
"name": "ControlCreatePolicyMappingMutation", "name": "ControlCreateDocumentMappingMutation",
"operationKind": "mutation", "operationKind": "mutation",
"text": "mutation ControlCreatePolicyMappingMutation(\n $input: CreateControlPolicyMappingInput!\n) {\n createControlPolicyMapping(input: $input) {\n controlEdge {\n node {\n id\n }\n }\n }\n}\n" "text": "mutation ControlCreateDocumentMappingMutation(\n $input: CreateControlDocumentMappingInput!\n) {\n createControlDocumentMapping(input: $input) {\n controlEdge {\n node {\n id\n }\n }\n }\n}\n"
} }
}; };
})(); })();
(node as any).hash = "9deabb78c91eca04673b23cf5d0b68f5"; (node as any).hash = "8ffd23b4cc3ce09756891fcde03c33cd";
export default node; export default node;

View File

@@ -1,5 +1,5 @@
/** /**
* @generated SignedSource<<16f8815c8b1db694fb8cd18be95c3f53>> * @generated SignedSource<<a39e2bd50fb3d78ac40f96740496fcac>>
* @lightSyntaxTransform * @lightSyntaxTransform
* @nogrep * @nogrep
*/ */
@@ -9,21 +9,21 @@
// @ts-nocheck // @ts-nocheck
import { ConcreteRequest } from 'relay-runtime'; import { ConcreteRequest } from 'relay-runtime';
export type DeleteControlPolicyMappingInput = { export type DeleteControlDocumentMappingInput = {
controlId: string; controlId: string;
policyId: string; documentId: string;
}; };
export type ControlDeletePolicyMappingMutation$variables = { export type ControlDeleteDocumentMappingMutation$variables = {
input: DeleteControlPolicyMappingInput; input: DeleteControlDocumentMappingInput;
}; };
export type ControlDeletePolicyMappingMutation$data = { export type ControlDeleteDocumentMappingMutation$data = {
readonly deleteControlPolicyMapping: { readonly deleteControlDocumentMapping: {
readonly deletedPolicyId: string; readonly deletedDocumentId: string;
}; };
}; };
export type ControlDeletePolicyMappingMutation = { export type ControlDeleteDocumentMappingMutation = {
response: ControlDeletePolicyMappingMutation$data; response: ControlDeleteDocumentMappingMutation$data;
variables: ControlDeletePolicyMappingMutation$variables; variables: ControlDeleteDocumentMappingMutation$variables;
}; };
const node: ConcreteRequest = (function(){ const node: ConcreteRequest = (function(){
@@ -44,16 +44,16 @@ v1 = [
"variableName": "input" "variableName": "input"
} }
], ],
"concreteType": "DeleteControlPolicyMappingPayload", "concreteType": "DeleteControlDocumentMappingPayload",
"kind": "LinkedField", "kind": "LinkedField",
"name": "deleteControlPolicyMapping", "name": "deleteControlDocumentMapping",
"plural": false, "plural": false,
"selections": [ "selections": [
{ {
"alias": null, "alias": null,
"args": null, "args": null,
"kind": "ScalarField", "kind": "ScalarField",
"name": "deletedPolicyId", "name": "deletedDocumentId",
"storageKey": null "storageKey": null
} }
], ],
@@ -65,7 +65,7 @@ return {
"argumentDefinitions": (v0/*: any*/), "argumentDefinitions": (v0/*: any*/),
"kind": "Fragment", "kind": "Fragment",
"metadata": null, "metadata": null,
"name": "ControlDeletePolicyMappingMutation", "name": "ControlDeleteDocumentMappingMutation",
"selections": (v1/*: any*/), "selections": (v1/*: any*/),
"type": "Mutation", "type": "Mutation",
"abstractKey": null "abstractKey": null
@@ -74,20 +74,20 @@ return {
"operation": { "operation": {
"argumentDefinitions": (v0/*: any*/), "argumentDefinitions": (v0/*: any*/),
"kind": "Operation", "kind": "Operation",
"name": "ControlDeletePolicyMappingMutation", "name": "ControlDeleteDocumentMappingMutation",
"selections": (v1/*: any*/) "selections": (v1/*: any*/)
}, },
"params": { "params": {
"cacheID": "ae87d43859683362f6c7024e7f371425", "cacheID": "de5f0d5a1db8bf370f893e99e58729df",
"id": null, "id": null,
"metadata": {}, "metadata": {},
"name": "ControlDeletePolicyMappingMutation", "name": "ControlDeleteDocumentMappingMutation",
"operationKind": "mutation", "operationKind": "mutation",
"text": "mutation ControlDeletePolicyMappingMutation(\n $input: DeleteControlPolicyMappingInput!\n) {\n deleteControlPolicyMapping(input: $input) {\n deletedPolicyId\n }\n}\n" "text": "mutation ControlDeleteDocumentMappingMutation(\n $input: DeleteControlDocumentMappingInput!\n) {\n deleteControlDocumentMapping(input: $input) {\n deletedDocumentId\n }\n}\n"
} }
}; };
})(); })();
(node as any).hash = "39306cd73fd5af5c603272f0bba45a8f"; (node as any).hash = "d7e9d7d588053130899fe2f52399a99d";
export default node; export default node;

View File

@@ -0,0 +1,301 @@
/**
* @generated SignedSource<<0368d1546d67e840ab9a22f8864fde5a>>
* @lightSyntaxTransform
* @nogrep
*/
/* tslint:disable */
/* eslint-disable */
// @ts-nocheck
import { ConcreteRequest } from 'relay-runtime';
export type ControlLinkedDocumentsQuery$variables = {
controlId: string;
};
export type ControlLinkedDocumentsQuery$data = {
readonly control: {
readonly documents?: {
readonly edges: ReadonlyArray<{
readonly node: {
readonly createdAt: string;
readonly currentPublishedVersion: number | null | undefined;
readonly description: string;
readonly id: string;
readonly owner: {
readonly fullName: string;
readonly id: string;
};
readonly title: string;
readonly updatedAt: string;
};
}>;
};
readonly id: string;
};
};
export type ControlLinkedDocumentsQuery = {
response: ControlLinkedDocumentsQuery$data;
variables: ControlLinkedDocumentsQuery$variables;
};
const node: ConcreteRequest = (function(){
var v0 = [
{
"defaultValue": null,
"kind": "LocalArgument",
"name": "controlId"
}
],
v1 = [
{
"kind": "Variable",
"name": "id",
"variableName": "controlId"
}
],
v2 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "id",
"storageKey": null
},
v3 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "__typename",
"storageKey": null
},
v4 = [
{
"alias": null,
"args": null,
"concreteType": "DocumentEdge",
"kind": "LinkedField",
"name": "edges",
"plural": true,
"selections": [
{
"alias": null,
"args": null,
"concreteType": "Document",
"kind": "LinkedField",
"name": "node",
"plural": false,
"selections": [
(v2/*: any*/),
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "title",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "description",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "currentPublishedVersion",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "createdAt",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "updatedAt",
"storageKey": null
},
{
"alias": null,
"args": null,
"concreteType": "People",
"kind": "LinkedField",
"name": "owner",
"plural": false,
"selections": [
(v2/*: any*/),
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "fullName",
"storageKey": null
}
],
"storageKey": null
},
(v3/*: any*/)
],
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "cursor",
"storageKey": null
}
],
"storageKey": null
},
{
"alias": null,
"args": null,
"concreteType": "PageInfo",
"kind": "LinkedField",
"name": "pageInfo",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "endCursor",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "hasNextPage",
"storageKey": null
}
],
"storageKey": null
}
],
v5 = [
{
"kind": "Literal",
"name": "first",
"value": 100
}
];
return {
"fragment": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Fragment",
"metadata": null,
"name": "ControlLinkedDocumentsQuery",
"selections": [
{
"alias": "control",
"args": (v1/*: any*/),
"concreteType": null,
"kind": "LinkedField",
"name": "node",
"plural": false,
"selections": [
(v2/*: any*/),
{
"kind": "InlineFragment",
"selections": [
{
"alias": "documents",
"args": null,
"concreteType": "DocumentConnection",
"kind": "LinkedField",
"name": "__Control__documents_connection",
"plural": false,
"selections": (v4/*: any*/),
"storageKey": null
}
],
"type": "Control",
"abstractKey": null
}
],
"storageKey": null
}
],
"type": "Query",
"abstractKey": null
},
"kind": "Request",
"operation": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Operation",
"name": "ControlLinkedDocumentsQuery",
"selections": [
{
"alias": "control",
"args": (v1/*: any*/),
"concreteType": null,
"kind": "LinkedField",
"name": "node",
"plural": false,
"selections": [
(v3/*: any*/),
(v2/*: any*/),
{
"kind": "InlineFragment",
"selections": [
{
"alias": null,
"args": (v5/*: any*/),
"concreteType": "DocumentConnection",
"kind": "LinkedField",
"name": "documents",
"plural": false,
"selections": (v4/*: any*/),
"storageKey": "documents(first:100)"
},
{
"alias": null,
"args": (v5/*: any*/),
"filters": null,
"handle": "connection",
"key": "Control__documents",
"kind": "LinkedHandle",
"name": "documents"
}
],
"type": "Control",
"abstractKey": null
}
],
"storageKey": null
}
]
},
"params": {
"cacheID": "991da084547d2b0790d0698baf953be0",
"id": null,
"metadata": {
"connection": [
{
"count": null,
"cursor": null,
"direction": "forward",
"path": [
"control",
"documents"
]
}
]
},
"name": "ControlLinkedDocumentsQuery",
"operationKind": "query",
"text": "query ControlLinkedDocumentsQuery(\n $controlId: ID!\n) {\n control: node(id: $controlId) {\n __typename\n id\n ... on Control {\n documents(first: 100) {\n edges {\n node {\n id\n title\n description\n currentPublishedVersion\n createdAt\n updatedAt\n owner {\n id\n fullName\n }\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n }\n}\n"
}
};
})();
(node as any).hash = "ec0ce0c9a248664a239bb048da0bb76c";
export default node;

View File

@@ -9,13 +9,13 @@
// @ts-nocheck // @ts-nocheck
import { ConcreteRequest } from 'relay-runtime'; import { ConcreteRequest } from 'relay-runtime';
export type ControlLinkedPoliciesQuery$variables = { export type ControlLinkedDocumentsQuery$variables = {
controlId: string; controlId: string;
}; };
export type ControlLinkedPoliciesQuery$data = { export type ControlLinkedDocumentsQuery$data = {
readonly control: { readonly control: {
readonly id: string; readonly id: string;
readonly policies?: { readonly documents?: {
readonly edges: ReadonlyArray<{ readonly edges: ReadonlyArray<{
readonly node: { readonly node: {
readonly createdAt: string; readonly createdAt: string;
@@ -33,9 +33,9 @@ export type ControlLinkedPoliciesQuery$data = {
}; };
}; };
}; };
export type ControlLinkedPoliciesQuery = { export type ControlLinkedDocumentsQuery = {
response: ControlLinkedPoliciesQuery$data; response: ControlLinkedDocumentsQuery$data;
variables: ControlLinkedPoliciesQuery$variables; variables: ControlLinkedDocumentsQuery$variables;
}; };
const node: ConcreteRequest = (function(){ const node: ConcreteRequest = (function(){
@@ -71,7 +71,7 @@ v4 = [
{ {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "PolicyEdge", "concreteType": "DocumentEdge",
"kind": "LinkedField", "kind": "LinkedField",
"name": "edges", "name": "edges",
"plural": true, "plural": true,
@@ -79,7 +79,7 @@ v4 = [
{ {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "Policy", "concreteType": "Document",
"kind": "LinkedField", "kind": "LinkedField",
"name": "node", "name": "node",
"plural": false, "plural": false,
@@ -191,7 +191,7 @@ return {
"argumentDefinitions": (v0/*: any*/), "argumentDefinitions": (v0/*: any*/),
"kind": "Fragment", "kind": "Fragment",
"metadata": null, "metadata": null,
"name": "ControlLinkedPoliciesQuery", "name": "ControlLinkedDocumentsQuery",
"selections": [ "selections": [
{ {
"alias": "control", "alias": "control",
@@ -206,11 +206,11 @@ return {
"kind": "InlineFragment", "kind": "InlineFragment",
"selections": [ "selections": [
{ {
"alias": "policies", "alias": "documents",
"args": null, "args": null,
"concreteType": "PolicyConnection", "concreteType": "DocumentConnection",
"kind": "LinkedField", "kind": "LinkedField",
"name": "__Control__policies_connection", "name": "__Control__documents_connection",
"plural": false, "plural": false,
"selections": (v4/*: any*/), "selections": (v4/*: any*/),
"storageKey": null "storageKey": null
@@ -230,7 +230,7 @@ return {
"operation": { "operation": {
"argumentDefinitions": (v0/*: any*/), "argumentDefinitions": (v0/*: any*/),
"kind": "Operation", "kind": "Operation",
"name": "ControlLinkedPoliciesQuery", "name": "ControlLinkedDocumentsQuery",
"selections": [ "selections": [
{ {
"alias": "control", "alias": "control",
@@ -248,21 +248,21 @@ return {
{ {
"alias": null, "alias": null,
"args": (v5/*: any*/), "args": (v5/*: any*/),
"concreteType": "PolicyConnection", "concreteType": "DocumentConnection",
"kind": "LinkedField", "kind": "LinkedField",
"name": "policies", "name": "documents",
"plural": false, "plural": false,
"selections": (v4/*: any*/), "selections": (v4/*: any*/),
"storageKey": "policies(first:100)" "storageKey": "documents(first:100)"
}, },
{ {
"alias": null, "alias": null,
"args": (v5/*: any*/), "args": (v5/*: any*/),
"filters": null, "filters": null,
"handle": "connection", "handle": "connection",
"key": "Control__policies", "key": "Control__documents",
"kind": "LinkedHandle", "kind": "LinkedHandle",
"name": "policies" "name": "documents"
} }
], ],
"type": "Control", "type": "Control",
@@ -284,14 +284,14 @@ return {
"direction": "forward", "direction": "forward",
"path": [ "path": [
"control", "control",
"policies" "documents"
] ]
} }
] ]
}, },
"name": "ControlLinkedPoliciesQuery", "name": "ControlLinkedDocumentsQuery",
"operationKind": "query", "operationKind": "query",
"text": "query ControlLinkedPoliciesQuery(\n $controlId: ID!\n) {\n control: node(id: $controlId) {\n __typename\n id\n ... on Control {\n policies(first: 100) {\n edges {\n node {\n id\n title\n description\n currentPublishedVersion\n createdAt\n updatedAt\n owner {\n id\n fullName\n }\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n }\n}\n" "text": "query ControlLinkedDocumentsQuery(\n $controlId: ID!\n) {\n control: node(id: $controlId) {\n __typename\n id\n ... on Control {\n documents(first: 100) {\n edges {\n node {\n id\n title\n description\n currentPublishedVersion\n createdAt\n updatedAt\n owner {\n id\n fullName\n }\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n }\n}\n"
} }
}; };
})(); })();

View File

@@ -0,0 +1,301 @@
/**
* @generated SignedSource<<2b85a8642da3bc98edc1342bd07841ae>>
* @lightSyntaxTransform
* @nogrep
*/
/* tslint:disable */
/* eslint-disable */
// @ts-nocheck
import { ConcreteRequest } from 'relay-runtime';
export type ControlOrganizationDocumentsQuery$variables = {
organizationId: string;
};
export type ControlOrganizationDocumentsQuery$data = {
readonly organization: {
readonly documents?: {
readonly edges: ReadonlyArray<{
readonly node: {
readonly createdAt: string;
readonly currentPublishedVersion: number | null | undefined;
readonly description: string;
readonly id: string;
readonly owner: {
readonly fullName: string;
readonly id: string;
};
readonly title: string;
readonly updatedAt: string;
};
}>;
};
readonly id: string;
};
};
export type ControlOrganizationDocumentsQuery = {
response: ControlOrganizationDocumentsQuery$data;
variables: ControlOrganizationDocumentsQuery$variables;
};
const node: ConcreteRequest = (function(){
var v0 = [
{
"defaultValue": null,
"kind": "LocalArgument",
"name": "organizationId"
}
],
v1 = [
{
"kind": "Variable",
"name": "id",
"variableName": "organizationId"
}
],
v2 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "id",
"storageKey": null
},
v3 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "__typename",
"storageKey": null
},
v4 = [
{
"alias": null,
"args": null,
"concreteType": "DocumentEdge",
"kind": "LinkedField",
"name": "edges",
"plural": true,
"selections": [
{
"alias": null,
"args": null,
"concreteType": "Document",
"kind": "LinkedField",
"name": "node",
"plural": false,
"selections": [
(v2/*: any*/),
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "title",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "description",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "currentPublishedVersion",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "createdAt",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "updatedAt",
"storageKey": null
},
{
"alias": null,
"args": null,
"concreteType": "People",
"kind": "LinkedField",
"name": "owner",
"plural": false,
"selections": [
(v2/*: any*/),
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "fullName",
"storageKey": null
}
],
"storageKey": null
},
(v3/*: any*/)
],
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "cursor",
"storageKey": null
}
],
"storageKey": null
},
{
"alias": null,
"args": null,
"concreteType": "PageInfo",
"kind": "LinkedField",
"name": "pageInfo",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "endCursor",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "hasNextPage",
"storageKey": null
}
],
"storageKey": null
}
],
v5 = [
{
"kind": "Literal",
"name": "first",
"value": 100
}
];
return {
"fragment": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Fragment",
"metadata": null,
"name": "ControlOrganizationDocumentsQuery",
"selections": [
{
"alias": "organization",
"args": (v1/*: any*/),
"concreteType": null,
"kind": "LinkedField",
"name": "node",
"plural": false,
"selections": [
(v2/*: any*/),
{
"kind": "InlineFragment",
"selections": [
{
"alias": "documents",
"args": null,
"concreteType": "DocumentConnection",
"kind": "LinkedField",
"name": "__Organization__documents_connection",
"plural": false,
"selections": (v4/*: any*/),
"storageKey": null
}
],
"type": "Organization",
"abstractKey": null
}
],
"storageKey": null
}
],
"type": "Query",
"abstractKey": null
},
"kind": "Request",
"operation": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Operation",
"name": "ControlOrganizationDocumentsQuery",
"selections": [
{
"alias": "organization",
"args": (v1/*: any*/),
"concreteType": null,
"kind": "LinkedField",
"name": "node",
"plural": false,
"selections": [
(v3/*: any*/),
(v2/*: any*/),
{
"kind": "InlineFragment",
"selections": [
{
"alias": null,
"args": (v5/*: any*/),
"concreteType": "DocumentConnection",
"kind": "LinkedField",
"name": "documents",
"plural": false,
"selections": (v4/*: any*/),
"storageKey": "documents(first:100)"
},
{
"alias": null,
"args": (v5/*: any*/),
"filters": null,
"handle": "connection",
"key": "Organization__documents",
"kind": "LinkedHandle",
"name": "documents"
}
],
"type": "Organization",
"abstractKey": null
}
],
"storageKey": null
}
]
},
"params": {
"cacheID": "6607215b906f016d5f1f7a432f9eb41b",
"id": null,
"metadata": {
"connection": [
{
"count": null,
"cursor": null,
"direction": "forward",
"path": [
"organization",
"documents"
]
}
]
},
"name": "ControlOrganizationDocumentsQuery",
"operationKind": "query",
"text": "query ControlOrganizationDocumentsQuery(\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n id\n ... on Organization {\n documents(first: 100) {\n edges {\n node {\n id\n title\n description\n currentPublishedVersion\n createdAt\n updatedAt\n owner {\n id\n fullName\n }\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n }\n}\n"
}
};
})();
(node as any).hash = "99469ffc117f4f1dea4c96eb818d8fc3";
export default node;

View File

@@ -9,13 +9,13 @@
// @ts-nocheck // @ts-nocheck
import { ConcreteRequest } from 'relay-runtime'; import { ConcreteRequest } from 'relay-runtime';
export type ControlOrganizationPoliciesQuery$variables = { export type ControlOrganizationDocumentsQuery$variables = {
organizationId: string; organizationId: string;
}; };
export type ControlOrganizationPoliciesQuery$data = { export type ControlOrganizationDocumentsQuery$data = {
readonly organization: { readonly organization: {
readonly id: string; readonly id: string;
readonly policies?: { readonly documents?: {
readonly edges: ReadonlyArray<{ readonly edges: ReadonlyArray<{
readonly node: { readonly node: {
readonly createdAt: string; readonly createdAt: string;
@@ -33,9 +33,9 @@ export type ControlOrganizationPoliciesQuery$data = {
}; };
}; };
}; };
export type ControlOrganizationPoliciesQuery = { export type ControlOrganizationDocumentsQuery = {
response: ControlOrganizationPoliciesQuery$data; response: ControlOrganizationDocumentsQuery$data;
variables: ControlOrganizationPoliciesQuery$variables; variables: ControlOrganizationDocumentsQuery$variables;
}; };
const node: ConcreteRequest = (function(){ const node: ConcreteRequest = (function(){
@@ -71,7 +71,7 @@ v4 = [
{ {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "PolicyEdge", "concreteType": "DocumentEdge",
"kind": "LinkedField", "kind": "LinkedField",
"name": "edges", "name": "edges",
"plural": true, "plural": true,
@@ -79,7 +79,7 @@ v4 = [
{ {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "Policy", "concreteType": "Document",
"kind": "LinkedField", "kind": "LinkedField",
"name": "node", "name": "node",
"plural": false, "plural": false,
@@ -191,7 +191,7 @@ return {
"argumentDefinitions": (v0/*: any*/), "argumentDefinitions": (v0/*: any*/),
"kind": "Fragment", "kind": "Fragment",
"metadata": null, "metadata": null,
"name": "ControlOrganizationPoliciesQuery", "name": "ControlOrganizationDocumentsQuery",
"selections": [ "selections": [
{ {
"alias": "organization", "alias": "organization",
@@ -206,11 +206,11 @@ return {
"kind": "InlineFragment", "kind": "InlineFragment",
"selections": [ "selections": [
{ {
"alias": "policies", "alias": "documents",
"args": null, "args": null,
"concreteType": "PolicyConnection", "concreteType": "DocumentConnection",
"kind": "LinkedField", "kind": "LinkedField",
"name": "__Organization__policies_connection", "name": "__Organization__documents_connection",
"plural": false, "plural": false,
"selections": (v4/*: any*/), "selections": (v4/*: any*/),
"storageKey": null "storageKey": null
@@ -230,7 +230,7 @@ return {
"operation": { "operation": {
"argumentDefinitions": (v0/*: any*/), "argumentDefinitions": (v0/*: any*/),
"kind": "Operation", "kind": "Operation",
"name": "ControlOrganizationPoliciesQuery", "name": "ControlOrganizationDocumentsQuery",
"selections": [ "selections": [
{ {
"alias": "organization", "alias": "organization",
@@ -248,21 +248,21 @@ return {
{ {
"alias": null, "alias": null,
"args": (v5/*: any*/), "args": (v5/*: any*/),
"concreteType": "PolicyConnection", "concreteType": "DocumentConnection",
"kind": "LinkedField", "kind": "LinkedField",
"name": "policies", "name": "documents",
"plural": false, "plural": false,
"selections": (v4/*: any*/), "selections": (v4/*: any*/),
"storageKey": "policies(first:100)" "storageKey": "documents(first:100)"
}, },
{ {
"alias": null, "alias": null,
"args": (v5/*: any*/), "args": (v5/*: any*/),
"filters": null, "filters": null,
"handle": "connection", "handle": "connection",
"key": "Organization__policies", "key": "Organization__documents",
"kind": "LinkedHandle", "kind": "LinkedHandle",
"name": "policies" "name": "documents"
} }
], ],
"type": "Organization", "type": "Organization",
@@ -284,14 +284,14 @@ return {
"direction": "forward", "direction": "forward",
"path": [ "path": [
"organization", "organization",
"policies" "documents"
] ]
} }
] ]
}, },
"name": "ControlOrganizationPoliciesQuery", "name": "ControlOrganizationDocumentsQuery",
"operationKind": "query", "operationKind": "query",
"text": "query ControlOrganizationPoliciesQuery(\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n id\n ... on Organization {\n policies(first: 100) {\n edges {\n node {\n id\n title\n description\n currentPublishedVersion\n createdAt\n updatedAt\n owner {\n id\n fullName\n }\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n }\n}\n" "text": "query ControlOrganizationDocumentsQuery(\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n id\n ... on Organization {\n documents(first: 100) {\n edges {\n node {\n id\n title\n description\n currentPublishedVersion\n createdAt\n updatedAt\n owner {\n id\n fullName\n }\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n }\n}\n"
} }
}; };
})(); })();

View File

@@ -60,11 +60,11 @@ import {
import { ShowRiskViewCreateRiskMeasureMappingMutation } from "./__generated__/ShowRiskViewCreateRiskMeasureMappingMutation.graphql"; import { ShowRiskViewCreateRiskMeasureMappingMutation } from "./__generated__/ShowRiskViewCreateRiskMeasureMappingMutation.graphql";
import { ShowRiskViewDeleteRiskMeasureMappingMutation } from "./__generated__/ShowRiskViewDeleteRiskMeasureMappingMutation.graphql"; import { ShowRiskViewDeleteRiskMeasureMappingMutation } from "./__generated__/ShowRiskViewDeleteRiskMeasureMappingMutation.graphql";
import { import {
ShowRiskViewOrganizationPoliciesQuery, ShowRiskViewOrganizationDocumentsQuery,
ShowRiskViewOrganizationPoliciesQuery$data, ShowRiskViewOrganizationDocumentsQuery$data,
} from "./__generated__/ShowRiskViewOrganizationPoliciesQuery.graphql"; } from "./__generated__/ShowRiskViewOrganizationDocumentsQuery.graphql";
import { ShowRiskViewCreateRiskPolicyMappingMutation } from "./__generated__/ShowRiskViewCreateRiskPolicyMappingMutation.graphql"; import { ShowRiskViewCreateRiskDocumentMappingMutation } from "./__generated__/ShowRiskViewCreateRiskDocumentMappingMutation.graphql";
import { ShowRiskViewDeleteRiskPolicyMappingMutation } from "./__generated__/ShowRiskViewDeleteRiskPolicyMappingMutation.graphql"; import { ShowRiskViewDeleteRiskDocumentMappingMutation } from "./__generated__/ShowRiskViewDeleteRiskDocumentMappingMutation.graphql";
const showRiskViewQuery = graphql` const showRiskViewQuery = graphql`
query ShowRiskViewQuery($riskId: ID!) { query ShowRiskViewQuery($riskId: ID!) {
@@ -97,7 +97,7 @@ const showRiskViewQuery = graphql`
} }
} }
} }
policies(first: 100) @connection(key: "Risk__policies") { documents(first: 100) @connection(key: "Risk__documents") {
edges { edges {
node { node {
id id
@@ -144,13 +144,13 @@ const organizationMeasuresQuery = graphql`
} }
`; `;
// Add query to fetch all policies for the organization // Add query to fetch all documents for the organization
const organizationPoliciesQuery = graphql` const organizationDocumentsQuery = graphql`
query ShowRiskViewOrganizationPoliciesQuery($organizationId: ID!) { query ShowRiskViewOrganizationDocumentsQuery($organizationId: ID!) {
organization: node(id: $organizationId) { organization: node(id: $organizationId) {
id id
... on Organization { ... on Organization {
policies(first: 100) @connection(key: "Organization__policies") { documents(first: 100) @connection(key: "Organization__documents") {
edges { edges {
node { node {
id id
@@ -189,12 +189,12 @@ const deleteRiskMeasureMappingMutation = graphql`
} }
`; `;
// Add mutation to create risk-policy mapping // Add mutation to create risk-document mapping
const createRiskPolicyMappingMutation = graphql` const createRiskDocumentMappingMutation = graphql`
mutation ShowRiskViewCreateRiskPolicyMappingMutation( mutation ShowRiskViewCreateRiskDocumentMappingMutation(
$input: CreateRiskPolicyMappingInput! $input: CreateRiskDocumentMappingInput!
) { ) {
createRiskPolicyMapping(input: $input) { createRiskDocumentMapping(input: $input) {
riskEdge { riskEdge {
node { node {
id id
@@ -204,13 +204,13 @@ const createRiskPolicyMappingMutation = graphql`
} }
`; `;
// Add mutation to delete risk-policy mapping // Add mutation to delete risk-document mapping
const deleteRiskPolicyMappingMutation = graphql` const deleteRiskDocumentMappingMutation = graphql`
mutation ShowRiskViewDeleteRiskPolicyMappingMutation( mutation ShowRiskViewDeleteRiskDocumentMappingMutation(
$input: DeleteRiskPolicyMappingInput! $input: DeleteRiskDocumentMappingInput!
) { ) {
deleteRiskPolicyMapping(input: $input) { deleteRiskDocumentMapping(input: $input) {
deletedPolicyId deletedDocumentId
} }
} }
`; `;
@@ -377,8 +377,8 @@ function ShowRiskViewContent({
risk.residualImpact! risk.residualImpact!
); );
// Fix typing for policies // Fix typing for documents
const policies = risk.policies?.edges?.map((edge) => edge.node) || []; const documents = risk.documents?.edges?.map((edge) => edge.node) || [];
// Fix typing for controls // Fix typing for controls
const controls = risk.controls?.edges?.map((edge) => edge.node) || []; const controls = risk.controls?.edges?.map((edge) => edge.node) || [];
@@ -397,16 +397,16 @@ function ShowRiskViewContent({
Record<string, boolean> Record<string, boolean>
>({}); >({});
// Add state for policy mapping dialog // Add state for document mapping dialog
const [isPolicyDialogOpen, setIsPolicyDialogOpen] = useState(false); const [isDocumentDialogOpen, setIsDocumentDialogOpen] = useState(false);
const [organizationPoliciesData, setOrganizationPoliciesData] = const [organizationDocumentsData, setOrganizationDocumentsData] =
useState<ShowRiskViewOrganizationPoliciesQuery$data | null>(null); useState<ShowRiskViewOrganizationDocumentsQuery$data | null>(null);
const [policySearchQuery, setPolicySearchQuery] = useState(""); const [documentSearchQuery, setDocumentSearchQuery] = useState("");
const [isLoadingPolicies, setIsLoadingPolicies] = useState(false); const [isLoadingDocuments, setIsLoadingDocuments] = useState(false);
const [linkingPolicies, setLinkingPolicies] = useState< const [linkingDocuments, setLinkingDocuments] = useState<
Record<string, boolean> Record<string, boolean>
>({}); >({});
const [unlinkingPolicies, setUnlinkingPolicies] = useState< const [unlinkingDocuments, setUnlinkingDocuments] = useState<
Record<string, boolean> Record<string, boolean>
>({}); >({});
@@ -420,14 +420,14 @@ function ShowRiskViewContent({
deleteRiskMeasureMappingMutation deleteRiskMeasureMappingMutation
); );
// Setup policy mutation hooks // Setup document mutation hooks
const [createRiskPolicyMapping] = const [createRiskDocumentMapping] =
useMutation<ShowRiskViewCreateRiskPolicyMappingMutation>( useMutation<ShowRiskViewCreateRiskDocumentMappingMutation>(
createRiskPolicyMappingMutation createRiskDocumentMappingMutation
); );
const [deleteRiskPolicyMapping] = const [deleteRiskDocumentMapping] =
useMutation<ShowRiskViewDeleteRiskPolicyMappingMutation>( useMutation<ShowRiskViewDeleteRiskDocumentMappingMutation>(
deleteRiskPolicyMappingMutation deleteRiskDocumentMappingMutation
); );
// Clear filters when dialog closes // Clear filters when dialog closes
@@ -440,14 +440,14 @@ function ShowRiskViewContent({
} }
}, [isMeasureDialogOpen]); }, [isMeasureDialogOpen]);
// Clear filters when policy dialog closes // Clear filters when document dialog closes
useEffect(() => { useEffect(() => {
if (!isPolicyDialogOpen) { if (!isDocumentDialogOpen) {
setPolicySearchQuery(""); setDocumentSearchQuery("");
setLinkingPolicies({}); setLinkingDocuments({});
setUnlinkingPolicies({}); setUnlinkingDocuments({});
} }
}, [isPolicyDialogOpen]); }, [isDocumentDialogOpen]);
// Load measures data when needed // Load measures data when needed
const loadMeasuresData = useCallback(() => { const loadMeasuresData = useCallback(() => {
@@ -479,30 +479,30 @@ function ShowRiskViewContent({
}); });
}, [risk.id, environment, organizationId, toast]); }, [risk.id, environment, organizationId, toast]);
// Load policies data when needed // Load documents data when needed
const loadPoliciesData = useCallback(() => { const loadDocumentsData = useCallback(() => {
if (!organizationId || !risk.id) return; if (!organizationId || !risk.id) return;
setIsLoadingPolicies(true); setIsLoadingDocuments(true);
// Fetch all policies for the organization // Fetch all documents for the organization
fetchQuery<ShowRiskViewOrganizationPoliciesQuery>( fetchQuery<ShowRiskViewOrganizationDocumentsQuery>(
environment, environment,
organizationPoliciesQuery, organizationDocumentsQuery,
{ {
organizationId, organizationId,
} }
).subscribe({ ).subscribe({
next: (data) => { next: (data) => {
setOrganizationPoliciesData(data); setOrganizationDocumentsData(data);
setIsLoadingPolicies(false); setIsLoadingDocuments(false);
}, },
error: (error: Error) => { error: (error: Error) => {
console.error("Error fetching organization policies:", error); console.error("Error fetching organization documents:", error);
setIsLoadingPolicies(false); setIsLoadingDocuments(false);
toast({ toast({
title: "Error", title: "Error",
description: "Failed to load policies.", description: "Failed to load documents.",
variant: "destructive", variant: "destructive",
}); });
}, },
@@ -554,25 +554,25 @@ function ShowRiskViewContent({
}); });
}, [getMeasures, measureSearchQuery, categoryFilter]); }, [getMeasures, measureSearchQuery, categoryFilter]);
// Helper functions for policies // Helper functions for documents
const getPolicies = useCallback(() => { const getDocuments = useCallback(() => {
if (!organizationPoliciesData?.organization?.policies?.edges) return []; if (!organizationDocumentsData?.organization?.documents?.edges) return [];
return organizationPoliciesData.organization.policies.edges.map( return organizationDocumentsData.organization.documents.edges.map(
(edge) => edge.node (edge) => edge.node
); );
}, [organizationPoliciesData]); }, [organizationDocumentsData]);
const filteredPolicies = useCallback(() => { const filteredDocuments = useCallback(() => {
const policies = getPolicies(); const documents = getDocuments();
if (!policySearchQuery) return policies; if (!documentSearchQuery) return documents;
return policies.filter((policy) => { return documents.filter((document) => {
return ( return (
!policySearchQuery || !documentSearchQuery ||
policy.title.toLowerCase().includes(policySearchQuery.toLowerCase()) document.title.toLowerCase().includes(documentSearchQuery.toLowerCase())
); );
}); });
}, [getPolicies, policySearchQuery]); }, [getDocuments, documentSearchQuery]);
// Handle linking a measure to this risk // Handle linking a measure to this risk
const handleLinkMeasure = useCallback( const handleLinkMeasure = useCallback(
@@ -718,38 +718,38 @@ function ShowRiskViewContent({
[risk.id, deleteRiskMeasureMapping, toast, environment, loadQuery] [risk.id, deleteRiskMeasureMapping, toast, environment, loadQuery]
); );
// Handle linking a policy to this risk // Handle linking a document to this risk
const handleLinkPolicy = useCallback( const handleLinkDocument = useCallback(
( (
policy: NonNullable< document: NonNullable<
NonNullable< NonNullable<
ShowRiskViewOrganizationPoliciesQuery$data["organization"] ShowRiskViewOrganizationDocumentsQuery$data["organization"]
>["policies"] >["documents"]
>["edges"][0]["node"] >["edges"][0]["node"]
) => { ) => {
if (!risk.id) return; if (!risk.id) return;
// Track this specific policy as linking // Track this specific document as linking
setLinkingPolicies((prev) => ({ ...prev, [policy.id]: true })); setLinkingDocuments((prev) => ({ ...prev, [document.id]: true }));
createRiskPolicyMapping({ createRiskDocumentMapping({
variables: { variables: {
input: { input: {
riskId: risk.id, riskId: risk.id,
policyId: policy.id, documentId: document.id,
}, },
}, },
onCompleted: (_, errors) => { onCompleted: (_, errors) => {
setLinkingPolicies((prev) => ({ setLinkingDocuments((prev) => ({
...prev, ...prev,
[policy.id]: false, [document.id]: false,
})); }));
if (errors && errors.length > 0) { if (errors && errors.length > 0) {
console.error("Error linking policy:", errors); console.error("Error linking document:", errors);
toast({ toast({
title: "Error", title: "Error",
description: "Failed to link policy. Please try again.", description: "Failed to link document. Please try again.",
variant: "destructive", variant: "destructive",
}); });
return; return;
@@ -770,58 +770,58 @@ function ShowRiskViewContent({
toast({ toast({
title: "Success", title: "Success",
description: `Linked policy "${policy.title}" to this risk.`, description: `Linked document "${document.title}" to this risk.`,
}); });
}, },
onError: (error) => { onError: (error) => {
setLinkingPolicies((prev) => ({ setLinkingDocuments((prev) => ({
...prev, ...prev,
[policy.id]: false, [document.id]: false,
})); }));
console.error("Error linking policy:", error); console.error("Error linking document:", error);
toast({ toast({
title: "Error", title: "Error",
description: "Failed to link policy. Please try again.", description: "Failed to link document. Please try again.",
variant: "destructive", variant: "destructive",
}); });
}, },
}); });
}, },
[risk.id, createRiskPolicyMapping, toast, environment, loadQuery] [risk.id, createRiskDocumentMapping, toast, environment, loadQuery]
); );
// Handle unlinking a policy from this risk // Handle unlinking a document from this risk
const handleUnlinkPolicy = useCallback( const handleUnlinkDocument = useCallback(
( (
policy: NonNullable< document: NonNullable<
NonNullable< NonNullable<
ShowRiskViewOrganizationPoliciesQuery$data["organization"] ShowRiskViewOrganizationDocumentsQuery$data["organization"]
>["policies"] >["documents"]
>["edges"][0]["node"] >["edges"][0]["node"]
) => { ) => {
if (!risk.id) return; if (!risk.id) return;
// Track this specific policy as unlinking // Track this specific document as unlinking
setUnlinkingPolicies((prev) => ({ ...prev, [policy.id]: true })); setUnlinkingDocuments((prev) => ({ ...prev, [document.id]: true }));
deleteRiskPolicyMapping({ deleteRiskDocumentMapping({
variables: { variables: {
input: { input: {
riskId: risk.id, riskId: risk.id,
policyId: policy.id, documentId: document.id,
}, },
}, },
onCompleted: (_, errors) => { onCompleted: (_, errors) => {
setUnlinkingPolicies((prev) => ({ setUnlinkingDocuments((prev) => ({
...prev, ...prev,
[policy.id]: false, [document.id]: false,
})); }));
if (errors && errors.length > 0) { if (errors && errors.length > 0) {
console.error("Error unlinking policy:", errors); console.error("Error unlinking document:", errors);
toast({ toast({
title: "Error", title: "Error",
description: "Failed to unlink policy. Please try again.", description: "Failed to unlink document. Please try again.",
variant: "destructive", variant: "destructive",
}); });
return; return;
@@ -842,24 +842,24 @@ function ShowRiskViewContent({
toast({ toast({
title: "Success", title: "Success",
description: `Unlinked policy "${policy.title}" from this risk.`, description: `Unlinked document "${document.title}" from this risk.`,
}); });
}, },
onError: (error) => { onError: (error) => {
setUnlinkingPolicies((prev) => ({ setUnlinkingDocuments((prev) => ({
...prev, ...prev,
[policy.id]: false, [document.id]: false,
})); }));
console.error("Error unlinking policy:", error); console.error("Error unlinking document:", error);
toast({ toast({
title: "Error", title: "Error",
description: "Failed to unlink policy. Please try again.", description: "Failed to unlink document. Please try again.",
variant: "destructive", variant: "destructive",
}); });
}, },
}); });
}, },
[risk.id, deleteRiskPolicyMapping, toast, environment, loadQuery] [risk.id, deleteRiskDocumentMapping, toast, environment, loadQuery]
); );
return ( return (
@@ -1073,7 +1073,7 @@ function ShowRiskViewContent({
<Tabs defaultValue="measures" className="w-full"> <Tabs defaultValue="measures" className="w-full">
<TabsList> <TabsList>
<TabsTrigger value="measures">Measures</TabsTrigger> <TabsTrigger value="measures">Measures</TabsTrigger>
<TabsTrigger value="policies">Policies</TabsTrigger> <TabsTrigger value="documents">Documents</TabsTrigger>
<TabsTrigger value="controls">Controls</TabsTrigger> <TabsTrigger value="controls">Controls</TabsTrigger>
</TabsList> </TabsList>
@@ -1133,48 +1133,48 @@ function ShowRiskViewContent({
)} )}
</TabsContent> </TabsContent>
<TabsContent value="policies" className="space-y-4"> <TabsContent value="documents" className="space-y-4">
<div className="flex justify-between items-center mb-4"> <div className="flex justify-between items-center mb-4">
<h2 className="text-xl font-semibold">Risk Policies</h2> <h2 className="text-xl font-semibold">Risk Documents</h2>
<div className="flex space-x-2"> <div className="flex space-x-2">
<Button <Button
onClick={() => { onClick={() => {
setIsPolicyDialogOpen(true); setIsDocumentDialogOpen(true);
loadPoliciesData(); loadDocumentsData();
}} }}
> >
<Plus className="mr-2 h-4 w-4" /> <Plus className="mr-2 h-4 w-4" />
Link Policy Link Document
</Button> </Button>
</div> </div>
</div> </div>
{policies.length > 0 ? ( {documents.length > 0 ? (
<div className="rounded-md border"> <div className="rounded-md border">
<Table> <Table>
<TableHeader> <TableHeader>
<TableRow> <TableRow>
<TableHead className="w-full">Policy</TableHead> <TableHead className="w-full">Document</TableHead>
<TableHead className="w-20">Actions</TableHead> <TableHead className="w-20">Actions</TableHead>
</TableRow> </TableRow>
</TableHeader> </TableHeader>
<TableBody> <TableBody>
{policies.map((policy) => ( {documents.map((document) => (
<TableRow key={policy.id}> <TableRow key={document.id}>
<TableCell> <TableCell>
<Link <Link
to={`/organizations/${organizationId}/policies/${policy.id}`} to={`/organizations/${organizationId}/documents/${document.id}`}
className="font-medium text-blue-600 hover:underline" className="font-medium text-blue-600 hover:underline"
> >
{policy.title} {document.title}
</Link> </Link>
</TableCell> </TableCell>
<TableCell> <TableCell>
<Button <Button
variant="ghost" variant="ghost"
size="icon" size="icon"
onClick={() => handleUnlinkPolicy(policy)} onClick={() => handleUnlinkDocument(document)}
disabled={unlinkingPolicies[policy.id] || false} disabled={unlinkingDocuments[document.id] || false}
title="Unlink policy" title="Unlink document"
> >
<Trash2 className="h-4 w-4 text-danger" /> <Trash2 className="h-4 w-4 text-danger" />
</Button> </Button>
@@ -1186,7 +1186,7 @@ function ShowRiskViewContent({
</div> </div>
) : ( ) : (
<div className="text-center py-10 text-secondary"> <div className="text-center py-10 text-secondary">
<p>No policies associated with this risk.</p> <p>No documents associated with this risk.</p>
</div> </div>
)} )}
</TabsContent> </TabsContent>
@@ -1351,15 +1351,15 @@ function ShowRiskViewContent({
</DialogContent> </DialogContent>
</Dialog> </Dialog>
{/* Dialog for linking policies */} {/* Dialog for linking documents */}
<Dialog open={isPolicyDialogOpen} onOpenChange={setIsPolicyDialogOpen}> <Dialog open={isDocumentDialogOpen} onOpenChange={setIsDocumentDialogOpen}>
<DialogContent className="max-w-3xl"> <DialogContent className="max-w-3xl">
<DialogHeader> <DialogHeader>
<div className="flex justify-between items-center"> <div className="flex justify-between items-center">
<div> <div>
<DialogTitle>Manage Risk Policies</DialogTitle> <DialogTitle>Manage Risk Documents</DialogTitle>
<DialogDescription> <DialogDescription>
Link or unlink policies to manage this risk. Link or unlink documents to manage this risk.
</DialogDescription> </DialogDescription>
</div> </div>
</div> </div>
@@ -1371,45 +1371,45 @@ function ShowRiskViewContent({
<div className="relative"> <div className="relative">
<Search className="absolute left-2 top-2.5 h-4 w-4 text-tertiary" /> <Search className="absolute left-2 top-2.5 h-4 w-4 text-tertiary" />
<Input <Input
placeholder="Search policies..." placeholder="Search documents..."
className="pl-8" className="pl-8"
value={policySearchQuery} value={documentSearchQuery}
onChange={(e) => setPolicySearchQuery(e.target.value)} onChange={(e) => setDocumentSearchQuery(e.target.value)}
/> />
</div> </div>
</div> </div>
</div> </div>
<div className="border rounded-md max-h-96 overflow-y-auto"> <div className="border rounded-md max-h-96 overflow-y-auto">
{isLoadingPolicies ? ( {isLoadingDocuments ? (
<div className="p-4 text-center">Loading policies...</div> <div className="p-4 text-center">Loading documents...</div>
) : filteredPolicies().length === 0 ? ( ) : filteredDocuments().length === 0 ? (
<div className="p-4 text-center">No policies found.</div> <div className="p-4 text-center">No documents found.</div>
) : ( ) : (
<div className="divide-y"> <div className="divide-y">
{filteredPolicies().map((policy) => { {filteredDocuments().map((document) => {
// For each render, recalculate linked status directly against the current risk data // For each render, recalculate linked status directly against the current risk data
const isLinked = policies.some( const isLinked = documents.some(
(riskPolicy) => riskPolicy.id === policy.id (riskDocument) => riskDocument.id === document.id
); );
const isLinking = linkingPolicies[policy.id] || false; const isLinking = linkingDocuments[document.id] || false;
const isUnlinking = unlinkingPolicies[policy.id] || false; const isUnlinking = unlinkingDocuments[document.id] || false;
return ( return (
<div <div
key={policy.id} key={document.id}
className="relative p-4 hover:bg-blue-50 transition-colors duration-150" className="relative p-4 hover:bg-blue-50 transition-colors duration-150"
> >
<div className="flex justify-between items-center"> <div className="flex justify-between items-center">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<h3 className="font-medium">{policy.title}</h3> <h3 className="font-medium">{document.title}</h3>
</div> </div>
{isLinked ? ( {isLinked ? (
<Button <Button
size="sm" size="sm"
variant="outline" variant="outline"
disabled={isUnlinking} disabled={isUnlinking}
onClick={() => handleUnlinkPolicy(policy)} onClick={() => handleUnlinkDocument(document)}
className="text-red-600 border-red-200 hover:bg-red-50" className="text-red-600 border-red-200 hover:bg-red-50"
> >
{isUnlinking ? "Unlinking..." : "Unlink"} {isUnlinking ? "Unlinking..." : "Unlink"}
@@ -1418,7 +1418,7 @@ function ShowRiskViewContent({
<Button <Button
size="sm" size="sm"
disabled={isLinking} disabled={isLinking}
onClick={() => handleLinkPolicy(policy)} onClick={() => handleLinkDocument(document)}
> >
{isLinking ? "Linking..." : "Link"} {isLinking ? "Linking..." : "Link"}
</Button> </Button>
@@ -1435,7 +1435,7 @@ function ShowRiskViewContent({
<DialogFooter> <DialogFooter>
<Button <Button
variant="outline" variant="outline"
onClick={() => setIsPolicyDialogOpen(false)} onClick={() => setIsDocumentDialogOpen(false)}
> >
Close Close
</Button> </Button>

View File

@@ -1,5 +1,5 @@
/** /**
* @generated SignedSource<<0a4cb496e3dd17d135eaa689ebba360a>> * @generated SignedSource<<ef56acc9abd55ffea9aee1093be375bf>>
* @lightSyntaxTransform * @lightSyntaxTransform
* @nogrep * @nogrep
*/ */
@@ -9,15 +9,15 @@
// @ts-nocheck // @ts-nocheck
import { ConcreteRequest } from 'relay-runtime'; import { ConcreteRequest } from 'relay-runtime';
export type CreateRiskPolicyMappingInput = { export type CreateRiskDocumentMappingInput = {
policyId: string; documentId: string;
riskId: string; riskId: string;
}; };
export type ShowRiskViewCreateRiskPolicyMappingMutation$variables = { export type ShowRiskViewCreateRiskDocumentMappingMutation$variables = {
input: CreateRiskPolicyMappingInput; input: CreateRiskDocumentMappingInput;
}; };
export type ShowRiskViewCreateRiskPolicyMappingMutation$data = { export type ShowRiskViewCreateRiskDocumentMappingMutation$data = {
readonly createRiskPolicyMapping: { readonly createRiskDocumentMapping: {
readonly riskEdge: { readonly riskEdge: {
readonly node: { readonly node: {
readonly id: string; readonly id: string;
@@ -25,9 +25,9 @@ export type ShowRiskViewCreateRiskPolicyMappingMutation$data = {
}; };
}; };
}; };
export type ShowRiskViewCreateRiskPolicyMappingMutation = { export type ShowRiskViewCreateRiskDocumentMappingMutation = {
response: ShowRiskViewCreateRiskPolicyMappingMutation$data; response: ShowRiskViewCreateRiskDocumentMappingMutation$data;
variables: ShowRiskViewCreateRiskPolicyMappingMutation$variables; variables: ShowRiskViewCreateRiskDocumentMappingMutation$variables;
}; };
const node: ConcreteRequest = (function(){ const node: ConcreteRequest = (function(){
@@ -48,9 +48,9 @@ v1 = [
"variableName": "input" "variableName": "input"
} }
], ],
"concreteType": "CreateRiskPolicyMappingPayload", "concreteType": "CreateRiskDocumentMappingPayload",
"kind": "LinkedField", "kind": "LinkedField",
"name": "createRiskPolicyMapping", "name": "createRiskDocumentMapping",
"plural": false, "plural": false,
"selections": [ "selections": [
{ {
@@ -91,7 +91,7 @@ return {
"argumentDefinitions": (v0/*: any*/), "argumentDefinitions": (v0/*: any*/),
"kind": "Fragment", "kind": "Fragment",
"metadata": null, "metadata": null,
"name": "ShowRiskViewCreateRiskPolicyMappingMutation", "name": "ShowRiskViewCreateRiskDocumentMappingMutation",
"selections": (v1/*: any*/), "selections": (v1/*: any*/),
"type": "Mutation", "type": "Mutation",
"abstractKey": null "abstractKey": null
@@ -100,20 +100,20 @@ return {
"operation": { "operation": {
"argumentDefinitions": (v0/*: any*/), "argumentDefinitions": (v0/*: any*/),
"kind": "Operation", "kind": "Operation",
"name": "ShowRiskViewCreateRiskPolicyMappingMutation", "name": "ShowRiskViewCreateRiskDocumentMappingMutation",
"selections": (v1/*: any*/) "selections": (v1/*: any*/)
}, },
"params": { "params": {
"cacheID": "57ab115614eb72c930a05a4496827702", "cacheID": "d48140a960f31c5ee40799780ad852c0",
"id": null, "id": null,
"metadata": {}, "metadata": {},
"name": "ShowRiskViewCreateRiskPolicyMappingMutation", "name": "ShowRiskViewCreateRiskDocumentMappingMutation",
"operationKind": "mutation", "operationKind": "mutation",
"text": "mutation ShowRiskViewCreateRiskPolicyMappingMutation(\n $input: CreateRiskPolicyMappingInput!\n) {\n createRiskPolicyMapping(input: $input) {\n riskEdge {\n node {\n id\n }\n }\n }\n}\n" "text": "mutation ShowRiskViewCreateRiskDocumentMappingMutation(\n $input: CreateRiskDocumentMappingInput!\n) {\n createRiskDocumentMapping(input: $input) {\n riskEdge {\n node {\n id\n }\n }\n }\n}\n"
} }
}; };
})(); })();
(node as any).hash = "ca3e1eee912cd4b7ac2702e4192dd544"; (node as any).hash = "cfd17c609ec34647f8ecafc1b07037ec";
export default node; export default node;

View File

@@ -0,0 +1,93 @@
/**
* @generated SignedSource<<77d14d5c3a949757604407daf7ba2600>>
* @lightSyntaxTransform
* @nogrep
*/
/* tslint:disable */
/* eslint-disable */
// @ts-nocheck
import { ConcreteRequest } from 'relay-runtime';
export type DeleteRiskDocumentMappingInput = {
documentId: string;
riskId: string;
};
export type ShowRiskViewDeleteRiskDocumentMappingMutation$variables = {
input: DeleteRiskDocumentMappingInput;
};
export type ShowRiskViewDeleteRiskDocumentMappingMutation$data = {
readonly deleteRiskDocumentMapping: {
readonly deletedDocumentId: string;
};
};
export type ShowRiskViewDeleteRiskDocumentMappingMutation = {
response: ShowRiskViewDeleteRiskDocumentMappingMutation$data;
variables: ShowRiskViewDeleteRiskDocumentMappingMutation$variables;
};
const node: ConcreteRequest = (function(){
var v0 = [
{
"defaultValue": null,
"kind": "LocalArgument",
"name": "input"
}
],
v1 = [
{
"alias": null,
"args": [
{
"kind": "Variable",
"name": "input",
"variableName": "input"
}
],
"concreteType": "DeleteRiskDocumentMappingPayload",
"kind": "LinkedField",
"name": "deleteRiskDocumentMapping",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "deletedDocumentId",
"storageKey": null
}
],
"storageKey": null
}
];
return {
"fragment": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Fragment",
"metadata": null,
"name": "ShowRiskViewDeleteRiskDocumentMappingMutation",
"selections": (v1/*: any*/),
"type": "Mutation",
"abstractKey": null
},
"kind": "Request",
"operation": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Operation",
"name": "ShowRiskViewDeleteRiskDocumentMappingMutation",
"selections": (v1/*: any*/)
},
"params": {
"cacheID": "1cd0845f63cf338aed2c2e565e239306",
"id": null,
"metadata": {},
"name": "ShowRiskViewDeleteRiskDocumentMappingMutation",
"operationKind": "mutation",
"text": "mutation ShowRiskViewDeleteRiskDocumentMappingMutation(\n $input: DeleteRiskDocumentMappingInput!\n) {\n deleteRiskDocumentMapping(input: $input) {\n deletedDocumentId\n }\n}\n"
}
};
})();
(node as any).hash = "b7b61daef6f0544c6b78f69094ad2d82";
export default node;

View File

@@ -1,93 +0,0 @@
/**
* @generated SignedSource<<8f8d550cd2bbc73744ba0b7a97720a49>>
* @lightSyntaxTransform
* @nogrep
*/
/* tslint:disable */
/* eslint-disable */
// @ts-nocheck
import { ConcreteRequest } from 'relay-runtime';
export type DeleteRiskPolicyMappingInput = {
policyId: string;
riskId: string;
};
export type ShowRiskViewDeleteRiskPolicyMappingMutation$variables = {
input: DeleteRiskPolicyMappingInput;
};
export type ShowRiskViewDeleteRiskPolicyMappingMutation$data = {
readonly deleteRiskPolicyMapping: {
readonly deletedPolicyId: string;
};
};
export type ShowRiskViewDeleteRiskPolicyMappingMutation = {
response: ShowRiskViewDeleteRiskPolicyMappingMutation$data;
variables: ShowRiskViewDeleteRiskPolicyMappingMutation$variables;
};
const node: ConcreteRequest = (function(){
var v0 = [
{
"defaultValue": null,
"kind": "LocalArgument",
"name": "input"
}
],
v1 = [
{
"alias": null,
"args": [
{
"kind": "Variable",
"name": "input",
"variableName": "input"
}
],
"concreteType": "DeleteRiskPolicyMappingPayload",
"kind": "LinkedField",
"name": "deleteRiskPolicyMapping",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "deletedPolicyId",
"storageKey": null
}
],
"storageKey": null
}
];
return {
"fragment": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Fragment",
"metadata": null,
"name": "ShowRiskViewDeleteRiskPolicyMappingMutation",
"selections": (v1/*: any*/),
"type": "Mutation",
"abstractKey": null
},
"kind": "Request",
"operation": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Operation",
"name": "ShowRiskViewDeleteRiskPolicyMappingMutation",
"selections": (v1/*: any*/)
},
"params": {
"cacheID": "d10c9ccbc01259fb7fea2bf463d6ecc6",
"id": null,
"metadata": {},
"name": "ShowRiskViewDeleteRiskPolicyMappingMutation",
"operationKind": "mutation",
"text": "mutation ShowRiskViewDeleteRiskPolicyMappingMutation(\n $input: DeleteRiskPolicyMappingInput!\n) {\n deleteRiskPolicyMapping(input: $input) {\n deletedPolicyId\n }\n}\n"
}
};
})();
(node as any).hash = "26177c99b1c35723f913637a1d6ac54b";
export default node;

View File

@@ -0,0 +1,246 @@
/**
* @generated SignedSource<<dfa237a2ce4b8cc6254ff791cb28f9f3>>
* @lightSyntaxTransform
* @nogrep
*/
/* tslint:disable */
/* eslint-disable */
// @ts-nocheck
import { ConcreteRequest } from 'relay-runtime';
export type ShowRiskViewOrganizationDocumentsQuery$variables = {
organizationId: string;
};
export type ShowRiskViewOrganizationDocumentsQuery$data = {
readonly organization: {
readonly documents?: {
readonly edges: ReadonlyArray<{
readonly node: {
readonly id: string;
readonly title: string;
};
}>;
};
readonly id: string;
};
};
export type ShowRiskViewOrganizationDocumentsQuery = {
response: ShowRiskViewOrganizationDocumentsQuery$data;
variables: ShowRiskViewOrganizationDocumentsQuery$variables;
};
const node: ConcreteRequest = (function(){
var v0 = [
{
"defaultValue": null,
"kind": "LocalArgument",
"name": "organizationId"
}
],
v1 = [
{
"kind": "Variable",
"name": "id",
"variableName": "organizationId"
}
],
v2 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "id",
"storageKey": null
},
v3 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "__typename",
"storageKey": null
},
v4 = [
{
"alias": null,
"args": null,
"concreteType": "DocumentEdge",
"kind": "LinkedField",
"name": "edges",
"plural": true,
"selections": [
{
"alias": null,
"args": null,
"concreteType": "Document",
"kind": "LinkedField",
"name": "node",
"plural": false,
"selections": [
(v2/*: any*/),
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "title",
"storageKey": null
},
(v3/*: any*/)
],
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "cursor",
"storageKey": null
}
],
"storageKey": null
},
{
"alias": null,
"args": null,
"concreteType": "PageInfo",
"kind": "LinkedField",
"name": "pageInfo",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "endCursor",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "hasNextPage",
"storageKey": null
}
],
"storageKey": null
}
],
v5 = [
{
"kind": "Literal",
"name": "first",
"value": 100
}
];
return {
"fragment": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Fragment",
"metadata": null,
"name": "ShowRiskViewOrganizationDocumentsQuery",
"selections": [
{
"alias": "organization",
"args": (v1/*: any*/),
"concreteType": null,
"kind": "LinkedField",
"name": "node",
"plural": false,
"selections": [
(v2/*: any*/),
{
"kind": "InlineFragment",
"selections": [
{
"alias": "documents",
"args": null,
"concreteType": "DocumentConnection",
"kind": "LinkedField",
"name": "__Organization__documents_connection",
"plural": false,
"selections": (v4/*: any*/),
"storageKey": null
}
],
"type": "Organization",
"abstractKey": null
}
],
"storageKey": null
}
],
"type": "Query",
"abstractKey": null
},
"kind": "Request",
"operation": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Operation",
"name": "ShowRiskViewOrganizationDocumentsQuery",
"selections": [
{
"alias": "organization",
"args": (v1/*: any*/),
"concreteType": null,
"kind": "LinkedField",
"name": "node",
"plural": false,
"selections": [
(v3/*: any*/),
(v2/*: any*/),
{
"kind": "InlineFragment",
"selections": [
{
"alias": null,
"args": (v5/*: any*/),
"concreteType": "DocumentConnection",
"kind": "LinkedField",
"name": "documents",
"plural": false,
"selections": (v4/*: any*/),
"storageKey": "documents(first:100)"
},
{
"alias": null,
"args": (v5/*: any*/),
"filters": null,
"handle": "connection",
"key": "Organization__documents",
"kind": "LinkedHandle",
"name": "documents"
}
],
"type": "Organization",
"abstractKey": null
}
],
"storageKey": null
}
]
},
"params": {
"cacheID": "7006d02b892a141f835e095002b234b1",
"id": null,
"metadata": {
"connection": [
{
"count": null,
"cursor": null,
"direction": "forward",
"path": [
"organization",
"documents"
]
}
]
},
"name": "ShowRiskViewOrganizationDocumentsQuery",
"operationKind": "query",
"text": "query ShowRiskViewOrganizationDocumentsQuery(\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n id\n ... on Organization {\n documents(first: 100) {\n edges {\n node {\n id\n title\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n }\n}\n"
}
};
})();
(node as any).hash = "dc0a2a6d494838560e76ac1ff916ecd5";
export default node;

View File

@@ -9,13 +9,13 @@
// @ts-nocheck // @ts-nocheck
import { ConcreteRequest } from 'relay-runtime'; import { ConcreteRequest } from 'relay-runtime';
export type ShowRiskViewOrganizationPoliciesQuery$variables = { export type ShowRiskViewOrganizationDocumentsQuery$variables = {
organizationId: string; organizationId: string;
}; };
export type ShowRiskViewOrganizationPoliciesQuery$data = { export type ShowRiskViewOrganizationDocumentsQuery$data = {
readonly organization: { readonly organization: {
readonly id: string; readonly id: string;
readonly policies?: { readonly documents?: {
readonly edges: ReadonlyArray<{ readonly edges: ReadonlyArray<{
readonly node: { readonly node: {
readonly id: string; readonly id: string;
@@ -25,9 +25,9 @@ export type ShowRiskViewOrganizationPoliciesQuery$data = {
}; };
}; };
}; };
export type ShowRiskViewOrganizationPoliciesQuery = { export type ShowRiskViewOrganizationDocumentsQuery = {
response: ShowRiskViewOrganizationPoliciesQuery$data; response: ShowRiskViewOrganizationDocumentsQuery$data;
variables: ShowRiskViewOrganizationPoliciesQuery$variables; variables: ShowRiskViewOrganizationDocumentsQuery$variables;
}; };
const node: ConcreteRequest = (function(){ const node: ConcreteRequest = (function(){
@@ -63,7 +63,7 @@ v4 = [
{ {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "PolicyEdge", "concreteType": "DocumentEdge",
"kind": "LinkedField", "kind": "LinkedField",
"name": "edges", "name": "edges",
"plural": true, "plural": true,
@@ -71,7 +71,7 @@ v4 = [
{ {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "Policy", "concreteType": "Document",
"kind": "LinkedField", "kind": "LinkedField",
"name": "node", "name": "node",
"plural": false, "plural": false,
@@ -136,7 +136,7 @@ return {
"argumentDefinitions": (v0/*: any*/), "argumentDefinitions": (v0/*: any*/),
"kind": "Fragment", "kind": "Fragment",
"metadata": null, "metadata": null,
"name": "ShowRiskViewOrganizationPoliciesQuery", "name": "ShowRiskViewOrganizationDocumentsQuery",
"selections": [ "selections": [
{ {
"alias": "organization", "alias": "organization",
@@ -151,11 +151,11 @@ return {
"kind": "InlineFragment", "kind": "InlineFragment",
"selections": [ "selections": [
{ {
"alias": "policies", "alias": "documents",
"args": null, "args": null,
"concreteType": "PolicyConnection", "concreteType": "DocumentConnection",
"kind": "LinkedField", "kind": "LinkedField",
"name": "__Organization__policies_connection", "name": "__Organization__documents_connection",
"plural": false, "plural": false,
"selections": (v4/*: any*/), "selections": (v4/*: any*/),
"storageKey": null "storageKey": null
@@ -175,7 +175,7 @@ return {
"operation": { "operation": {
"argumentDefinitions": (v0/*: any*/), "argumentDefinitions": (v0/*: any*/),
"kind": "Operation", "kind": "Operation",
"name": "ShowRiskViewOrganizationPoliciesQuery", "name": "ShowRiskViewOrganizationDocumentsQuery",
"selections": [ "selections": [
{ {
"alias": "organization", "alias": "organization",
@@ -193,21 +193,21 @@ return {
{ {
"alias": null, "alias": null,
"args": (v5/*: any*/), "args": (v5/*: any*/),
"concreteType": "PolicyConnection", "concreteType": "DocumentConnection",
"kind": "LinkedField", "kind": "LinkedField",
"name": "policies", "name": "documents",
"plural": false, "plural": false,
"selections": (v4/*: any*/), "selections": (v4/*: any*/),
"storageKey": "policies(first:100)" "storageKey": "documents(first:100)"
}, },
{ {
"alias": null, "alias": null,
"args": (v5/*: any*/), "args": (v5/*: any*/),
"filters": null, "filters": null,
"handle": "connection", "handle": "connection",
"key": "Organization__policies", "key": "Organization__documents",
"kind": "LinkedHandle", "kind": "LinkedHandle",
"name": "policies" "name": "documents"
} }
], ],
"type": "Organization", "type": "Organization",
@@ -229,14 +229,14 @@ return {
"direction": "forward", "direction": "forward",
"path": [ "path": [
"organization", "organization",
"policies" "documents"
] ]
} }
] ]
}, },
"name": "ShowRiskViewOrganizationPoliciesQuery", "name": "ShowRiskViewOrganizationDocumentsQuery",
"operationKind": "query", "operationKind": "query",
"text": "query ShowRiskViewOrganizationPoliciesQuery(\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n id\n ... on Organization {\n policies(first: 100) {\n edges {\n node {\n id\n title\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n }\n}\n" "text": "query ShowRiskViewOrganizationDocumentsQuery(\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n id\n ... on Organization {\n documents(first: 100) {\n edges {\n node {\n id\n title\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n }\n}\n"
} }
}; };
})(); })();

View File

@@ -1,5 +1,5 @@
/** /**
* @generated SignedSource<<48d940f6040fa9375ac915ce8851c658>> * @generated SignedSource<<d43ef1981a6db6f7813e6587e3eaf192>>
* @lightSyntaxTransform * @lightSyntaxTransform
* @nogrep * @nogrep
*/ */
@@ -29,6 +29,15 @@ export type ShowRiskViewQuery$data = {
}; };
readonly createdAt?: string; readonly createdAt?: string;
readonly description?: string; readonly description?: string;
readonly documents?: {
readonly edges: ReadonlyArray<{
readonly node: {
readonly createdAt: string;
readonly id: string;
readonly title: string;
};
}>;
};
readonly id: string; readonly id: string;
readonly inherentImpact?: number; readonly inherentImpact?: number;
readonly inherentLikelihood?: number; readonly inherentLikelihood?: number;
@@ -50,15 +59,6 @@ export type ShowRiskViewQuery$data = {
readonly fullName: string; readonly fullName: string;
readonly id: string; readonly id: string;
} | null | undefined; } | null | undefined;
readonly policies?: {
readonly edges: ReadonlyArray<{
readonly node: {
readonly createdAt: string;
readonly id: string;
readonly title: string;
};
}>;
};
readonly residualImpact?: number; readonly residualImpact?: number;
readonly residualLikelihood?: number; readonly residualLikelihood?: number;
readonly treatment?: RiskTreatment; readonly treatment?: RiskTreatment;
@@ -269,7 +269,7 @@ v18 = [
{ {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "PolicyEdge", "concreteType": "DocumentEdge",
"kind": "LinkedField", "kind": "LinkedField",
"name": "edges", "name": "edges",
"plural": true, "plural": true,
@@ -277,7 +277,7 @@ v18 = [
{ {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "Policy", "concreteType": "Document",
"kind": "LinkedField", "kind": "LinkedField",
"name": "node", "name": "node",
"plural": false, "plural": false,
@@ -387,11 +387,11 @@ return {
"storageKey": null "storageKey": null
}, },
{ {
"alias": "policies", "alias": "documents",
"args": null, "args": null,
"concreteType": "PolicyConnection", "concreteType": "DocumentConnection",
"kind": "LinkedField", "kind": "LinkedField",
"name": "__Risk__policies_connection", "name": "__Risk__documents_connection",
"plural": false, "plural": false,
"selections": (v18/*: any*/), "selections": (v18/*: any*/),
"storageKey": null "storageKey": null
@@ -469,21 +469,21 @@ return {
{ {
"alias": null, "alias": null,
"args": (v20/*: any*/), "args": (v20/*: any*/),
"concreteType": "PolicyConnection", "concreteType": "DocumentConnection",
"kind": "LinkedField", "kind": "LinkedField",
"name": "policies", "name": "documents",
"plural": false, "plural": false,
"selections": (v18/*: any*/), "selections": (v18/*: any*/),
"storageKey": "policies(first:100)" "storageKey": "documents(first:100)"
}, },
{ {
"alias": null, "alias": null,
"args": (v20/*: any*/), "args": (v20/*: any*/),
"filters": null, "filters": null,
"handle": "connection", "handle": "connection",
"key": "Risk__policies", "key": "Risk__documents",
"kind": "LinkedHandle", "kind": "LinkedHandle",
"name": "policies" "name": "documents"
}, },
{ {
"alias": null, "alias": null,
@@ -514,7 +514,7 @@ return {
] ]
}, },
"params": { "params": {
"cacheID": "487765d92cad8c0915ad4fee24d7e702", "cacheID": "9d1057cf6eac37c07ed841a80a4604b9",
"id": null, "id": null,
"metadata": { "metadata": {
"connection": [ "connection": [
@@ -533,7 +533,7 @@ return {
"direction": "forward", "direction": "forward",
"path": [ "path": [
"node", "node",
"policies" "documents"
] ]
}, },
{ {
@@ -549,11 +549,11 @@ return {
}, },
"name": "ShowRiskViewQuery", "name": "ShowRiskViewQuery",
"operationKind": "query", "operationKind": "query",
"text": "query ShowRiskViewQuery(\n $riskId: ID!\n) {\n node(id: $riskId) {\n __typename\n id\n ... on Risk {\n name\n description\n treatment\n owner {\n id\n fullName\n }\n inherentLikelihood\n inherentImpact\n residualLikelihood\n residualImpact\n note\n createdAt\n updatedAt\n measures(first: 100) {\n edges {\n node {\n id\n name\n description\n category\n createdAt\n state\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n policies(first: 100) {\n edges {\n node {\n id\n title\n createdAt\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n controls(first: 100) {\n edges {\n node {\n id\n referenceId\n name\n description\n createdAt\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n }\n}\n" "text": "query ShowRiskViewQuery(\n $riskId: ID!\n) {\n node(id: $riskId) {\n __typename\n id\n ... on Risk {\n name\n description\n treatment\n owner {\n id\n fullName\n }\n inherentLikelihood\n inherentImpact\n residualLikelihood\n residualImpact\n note\n createdAt\n updatedAt\n measures(first: 100) {\n edges {\n node {\n id\n name\n description\n category\n createdAt\n state\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n documents(first: 100) {\n edges {\n node {\n id\n title\n createdAt\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n controls(first: 100) {\n edges {\n node {\n id\n referenceId\n name\n description\n createdAt\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n }\n}\n"
} }
}; };
})(); })();
(node as any).hash = "b8506a3dd8980cd16b5344b990471533"; (node as any).hash = "96763bbbebd3aa29a02fcf1e6e782293";
export default node; export default node;

View File

@@ -1,9 +1,9 @@
/* Policy Content Styles */ /* Document Content Styles */
.policy-content { .document-content {
line-height: 1.6; line-height: 1.6;
} }
.policy-content h1 { .document-content h1 {
font-size: 2rem; font-size: 2rem;
font-weight: 700; font-weight: 700;
margin-top: 1.5rem; margin-top: 1.5rem;
@@ -11,7 +11,7 @@
color: hsl(var(--foreground)); color: hsl(var(--foreground));
} }
.policy-content h2 { .document-content h2 {
font-size: 1.5rem; font-size: 1.5rem;
font-weight: 600; font-weight: 600;
margin-top: 1.5rem; margin-top: 1.5rem;
@@ -19,7 +19,7 @@
color: hsl(var(--foreground)); color: hsl(var(--foreground));
} }
.policy-content h3 { .document-content h3 {
font-size: 1.25rem; font-size: 1.25rem;
font-weight: 600; font-weight: 600;
margin-top: 1.25rem; margin-top: 1.25rem;
@@ -27,7 +27,7 @@
color: hsl(var(--foreground)); color: hsl(var(--foreground));
} }
.policy-content h4 { .document-content h4 {
font-size: 1.125rem; font-size: 1.125rem;
font-weight: 600; font-weight: 600;
margin-top: 1rem; margin-top: 1rem;
@@ -35,38 +35,38 @@
color: hsl(var(--foreground)); color: hsl(var(--foreground));
} }
.policy-content p { .document-content p {
margin-bottom: 1rem; margin-bottom: 1rem;
} }
.policy-content ul, .document-content ul,
.policy-content ol { .document-content ol {
margin-left: 1.5rem; margin-left: 1.5rem;
margin-bottom: 1rem; margin-bottom: 1rem;
} }
.policy-content ul { .document-content ul {
list-style-type: disc; list-style-type: disc;
} }
.policy-content ol { .document-content ol {
list-style-type: decimal; list-style-type: decimal;
} }
.policy-content li { .document-content li {
margin-bottom: 0.5rem; margin-bottom: 0.5rem;
} }
.policy-content a { .document-content a {
color: hsl(var(--primary)); color: hsl(var(--primary));
text-decoration: underline; text-decoration: underline;
} }
.policy-content a:hover { .document-content a:hover {
text-decoration: none; text-decoration: none;
} }
.policy-content blockquote { .document-content blockquote {
border-left: 4px solid hsl(var(--solid-b)); border-left: 4px solid hsl(var(--solid-b));
padding-left: 1rem; padding-left: 1rem;
margin-left: 0; margin-left: 0;
@@ -75,7 +75,7 @@
color: hsl(var(--tertiary)); color: hsl(var(--tertiary));
} }
.policy-content code { .document-content code {
font-family: monospace; font-family: monospace;
background-color: hsl(var(--invert-bg)); background-color: hsl(var(--invert-bg));
padding: 0.2rem 0.4rem; padding: 0.2rem 0.4rem;
@@ -83,7 +83,7 @@
font-size: 0.875em; font-size: 0.875em;
} }
.policy-content pre { .document-content pre {
background-color: hsl(var(--invert-bg)); background-color: hsl(var(--invert-bg));
padding: 1rem; padding: 1rem;
border-radius: 0.5rem; border-radius: 0.5rem;
@@ -91,36 +91,36 @@
margin-bottom: 1rem; margin-bottom: 1rem;
} }
.policy-content pre code { .document-content pre code {
background-color: transparent; background-color: transparent;
padding: 0; padding: 0;
border-radius: 0; border-radius: 0;
} }
.policy-content table { .document-content table {
width: 100%; width: 100%;
border-collapse: collapse; border-collapse: collapse;
margin-bottom: 1rem; margin-bottom: 1rem;
} }
.policy-content th, .document-content th,
.policy-content td { .document-content td {
border: 1px solid hsl(var(--solid-b)); border: 1px solid hsl(var(--solid-b));
padding: 0.5rem; padding: 0.5rem;
} }
.policy-content th { .document-content th {
background-color: hsl(var(--invert-bg)); background-color: hsl(var(--invert-bg));
font-weight: 600; font-weight: 600;
} }
.policy-content img { .document-content img {
max-width: 100%; max-width: 100%;
height: auto; height: auto;
border-radius: 0.5rem; border-radius: 0.5rem;
} }
.policy-content hr { .document-content hr {
border: 0; border: 0;
border-top: 1px solid hsl(var(--solid-b)); border-top: 1px solid hsl(var(--solid-b));
margin: 1.5rem 0; margin: 1.5rem 0;

View File

@@ -56,11 +56,11 @@ func (c Control) CursorKey(orderBy ControlOrderField) page.CursorKey {
panic(fmt.Sprintf("unsupported order by: %s", orderBy)) panic(fmt.Sprintf("unsupported order by: %s", orderBy))
} }
func (c *Controls) LoadByPolicyID( func (c *Controls) LoadByDocumentID(
ctx context.Context, ctx context.Context,
conn pg.Conn, conn pg.Conn,
scope Scoper, scope Scoper,
policyID gid.GID, documentID gid.GID,
cursor *page.Cursor[ControlOrderField], cursor *page.Cursor[ControlOrderField],
) error { ) error {
q := ` q := `
@@ -77,9 +77,9 @@ WITH ctrl AS (
FROM FROM
controls c controls c
INNER JOIN INNER JOIN
controls_policies cp ON c.id = cp.control_id controls_documents cp ON c.id = cp.control_id
WHERE WHERE
cp.policy_id = @policy_id cp.document_id = @document_id
) )
SELECT SELECT
id, id,
@@ -97,7 +97,7 @@ WHERE %s
` `
q = fmt.Sprintf(q, scope.SQLFragment(), cursor.SQLFragment()) q = fmt.Sprintf(q, scope.SQLFragment(), cursor.SQLFragment())
args := pgx.NamedArgs{"policy_id": policyID} args := pgx.NamedArgs{"document_id": documentID}
maps.Copy(args, scope.SQLArguments()) maps.Copy(args, scope.SQLArguments())
maps.Copy(args, cursor.SQLArguments()) maps.Copy(args, cursor.SQLArguments())
@@ -196,9 +196,9 @@ WITH ctrl AS (
FROM FROM
controls c controls c
LEFT JOIN LEFT JOIN
controls_policies cp ON c.id = cp.control_id controls_documents cp ON c.id = cp.control_id
LEFT JOIN LEFT JOIN
risks_policies rp ON cp.policy_id = rp.policy_id risks_documents rp ON cp.document_id = rp.document_id
LEFT JOIN LEFT JOIN
controls_measures cm ON c.id = cm.control_id controls_measures cm ON c.id = cm.control_id
LEFT JOIN LEFT JOIN

View File

@@ -26,32 +26,32 @@ import (
) )
type ( type (
ControlPolicy struct { ControlDocument struct {
ControlID gid.GID `db:"control_id"` ControlID gid.GID `db:"control_id"`
PolicyID gid.GID `db:"policy_id"` DocumentID gid.GID `db:"document_id"`
TenantID gid.TenantID `db:"tenant_id"` TenantID gid.TenantID `db:"tenant_id"`
CreatedAt time.Time `db:"created_at"` CreatedAt time.Time `db:"created_at"`
} }
ControlPolicies []*ControlPolicy ControlDocuments []*ControlDocument
) )
func (cp ControlPolicy) Insert( func (cp ControlDocument) Insert(
ctx context.Context, ctx context.Context,
conn pg.Conn, conn pg.Conn,
scope Scoper, scope Scoper,
) error { ) error {
q := ` q := `
INSERT INTO INSERT INTO
controls_policies ( controls_documents (
control_id, control_id,
policy_id, document_id,
tenant_id, tenant_id,
created_at created_at
) )
VALUES ( VALUES (
@control_id, @control_id,
@policy_id, @document_id,
@tenant_id, @tenant_id,
@created_at @created_at
); );
@@ -59,7 +59,7 @@ VALUES (
args := pgx.StrictNamedArgs{ args := pgx.StrictNamedArgs{
"control_id": cp.ControlID, "control_id": cp.ControlID,
"policy_id": cp.PolicyID, "document_id": cp.DocumentID,
"tenant_id": scope.GetTenantID(), "tenant_id": scope.GetTenantID(),
"created_at": cp.CreatedAt, "created_at": cp.CreatedAt,
} }
@@ -67,26 +67,26 @@ VALUES (
return err return err
} }
func (cp ControlPolicy) Delete( func (cp ControlDocument) Delete(
ctx context.Context, ctx context.Context,
conn pg.Conn, conn pg.Conn,
scope Scoper, scope Scoper,
controlID gid.GID, controlID gid.GID,
policyID gid.GID, documentID gid.GID,
) error { ) error {
q := ` q := `
DELETE DELETE
FROM FROM
controls_policies controls_documents
WHERE WHERE
%s %s
AND control_id = @control_id AND control_id = @control_id
AND policy_id = @policy_id; AND document_id = @document_id;
` `
args := pgx.StrictNamedArgs{ args := pgx.StrictNamedArgs{
"control_id": controlID, "control_id": controlID,
"policy_id": policyID, "document_id": documentID,
} }
maps.Copy(args, scope.SQLArguments()) maps.Copy(args, scope.SQLArguments())

View File

@@ -27,7 +27,7 @@ import (
) )
type ( type (
Policy struct { Document struct {
ID gid.GID `db:"id"` ID gid.GID `db:"id"`
OrganizationID gid.GID `db:"organization_id"` OrganizationID gid.GID `db:"organization_id"`
OwnerID gid.GID `db:"owner_id"` OwnerID gid.GID `db:"owner_id"`
@@ -37,25 +37,25 @@ type (
UpdatedAt time.Time `db:"updated_at"` UpdatedAt time.Time `db:"updated_at"`
} }
Policies []*Policy Documents []*Document
) )
func (p Policy) CursorKey(orderBy PolicyOrderField) page.CursorKey { func (p Document) CursorKey(orderBy DocumentOrderField) page.CursorKey {
switch orderBy { switch orderBy {
case PolicyOrderFieldCreatedAt: case DocumentOrderFieldCreatedAt:
return page.NewCursorKey(p.ID, p.CreatedAt) return page.NewCursorKey(p.ID, p.CreatedAt)
case PolicyOrderFieldTitle: case DocumentOrderFieldTitle:
return page.NewCursorKey(p.ID, p.Title) return page.NewCursorKey(p.ID, p.Title)
} }
panic(fmt.Sprintf("unsupported order by: %s", orderBy)) panic(fmt.Sprintf("unsupported order by: %s", orderBy))
} }
func (p *Policy) LoadByID( func (p *Document) LoadByID(
ctx context.Context, ctx context.Context,
conn pg.Conn, conn pg.Conn,
scope Scoper, scope Scoper,
policyID gid.GID, documentID gid.GID,
) error { ) error {
q := ` q := `
SELECT SELECT
@@ -67,39 +67,39 @@ SELECT
created_at, created_at,
updated_at updated_at
FROM FROM
policies documents
WHERE WHERE
%s %s
AND id = @policy_id AND id = @document_id
LIMIT 1; LIMIT 1;
` `
q = fmt.Sprintf(q, scope.SQLFragment()) q = fmt.Sprintf(q, scope.SQLFragment())
args := pgx.StrictNamedArgs{"policy_id": policyID} args := pgx.StrictNamedArgs{"document_id": documentID}
maps.Copy(args, scope.SQLArguments()) maps.Copy(args, scope.SQLArguments())
rows, err := conn.Query(ctx, q, args) rows, err := conn.Query(ctx, q, args)
if err != nil { if err != nil {
return fmt.Errorf("cannot query policies: %w", err) return fmt.Errorf("cannot query documents: %w", err)
} }
policy, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[Policy]) document, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[Document])
if err != nil { if err != nil {
return fmt.Errorf("cannot collect policy: %w", err) return fmt.Errorf("cannot collect document: %w", err)
} }
*p = policy *p = document
return nil return nil
} }
func (p *Policies) LoadByOrganizationID( func (p *Documents) LoadByOrganizationID(
ctx context.Context, ctx context.Context,
conn pg.Conn, conn pg.Conn,
scope Scoper, scope Scoper,
organizationID gid.GID, organizationID gid.GID,
cursor *page.Cursor[PolicyOrderField], cursor *page.Cursor[DocumentOrderField],
) error { ) error {
q := ` q := `
SELECT SELECT
@@ -111,7 +111,7 @@ SELECT
created_at, created_at,
updated_at updated_at
FROM FROM
policies documents
WHERE WHERE
%s %s
AND organization_id = @organization_id AND organization_id = @organization_id
@@ -126,27 +126,27 @@ WHERE
rows, err := conn.Query(ctx, q, args) rows, err := conn.Query(ctx, q, args)
if err != nil { if err != nil {
return fmt.Errorf("cannot query policies: %w", err) return fmt.Errorf("cannot query documents: %w", err)
} }
policies, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[Policy]) documents, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[Document])
if err != nil { if err != nil {
return fmt.Errorf("cannot collect policies: %w", err) return fmt.Errorf("cannot collect documents: %w", err)
} }
*p = policies *p = documents
return nil return nil
} }
func (p Policy) Insert( func (p Document) Insert(
ctx context.Context, ctx context.Context,
conn pg.Conn, conn pg.Conn,
scope Scoper, scope Scoper,
) error { ) error {
q := ` q := `
INSERT INTO INSERT INTO
policies ( documents (
tenant_id, tenant_id,
id, id,
organization_id, organization_id,
@@ -158,7 +158,7 @@ INSERT INTO
) )
VALUES ( VALUES (
@tenant_id, @tenant_id,
@policy_id, @document_id,
@organization_id, @organization_id,
@owner_id, @owner_id,
@title, @title,
@@ -170,7 +170,7 @@ VALUES (
args := pgx.StrictNamedArgs{ args := pgx.StrictNamedArgs{
"tenant_id": scope.GetTenantID(), "tenant_id": scope.GetTenantID(),
"policy_id": p.ID, "document_id": p.ID,
"organization_id": p.OrganizationID, "organization_id": p.OrganizationID,
"owner_id": p.OwnerID, "owner_id": p.OwnerID,
"title": p.Title, "title": p.Title,
@@ -182,44 +182,44 @@ VALUES (
return err return err
} }
func (p Policy) Delete( func (p Document) Delete(
ctx context.Context, ctx context.Context,
conn pg.Conn, conn pg.Conn,
scope Scoper, scope Scoper,
) error { ) error {
q := ` q := `
DELETE FROM policies WHERE %s AND id = @policy_id DELETE FROM documents WHERE %s AND id = @document_id
` `
q = fmt.Sprintf(q, scope.SQLFragment()) q = fmt.Sprintf(q, scope.SQLFragment())
args := pgx.StrictNamedArgs{"policy_id": p.ID} args := pgx.StrictNamedArgs{"document_id": p.ID}
maps.Copy(args, scope.SQLArguments()) maps.Copy(args, scope.SQLArguments())
_, err := conn.Exec(ctx, q, args) _, err := conn.Exec(ctx, q, args)
return err return err
} }
func (p *Policy) Update( func (p *Document) Update(
ctx context.Context, ctx context.Context,
conn pg.Conn, conn pg.Conn,
scope Scoper, scope Scoper,
) error { ) error {
q := ` q := `
UPDATE UPDATE
policies documents
SET SET
title = @title, title = @title,
current_published_version = @current_published_version, current_published_version = @current_published_version,
owner_id = @owner_id, owner_id = @owner_id,
updated_at = @updated_at updated_at = @updated_at
WHERE %s WHERE %s
AND id = @policy_id AND id = @document_id
` `
q = fmt.Sprintf(q, scope.SQLFragment()) q = fmt.Sprintf(q, scope.SQLFragment())
args := pgx.StrictNamedArgs{ args := pgx.StrictNamedArgs{
"policy_id": p.ID, "document_id": p.ID,
"updated_at": time.Now(), "updated_at": time.Now(),
"title": p.Title, "title": p.Title,
"current_published_version": p.CurrentPublishedVersion, "current_published_version": p.CurrentPublishedVersion,
@@ -229,18 +229,18 @@ WHERE %s
_, err := conn.Exec(ctx, q, args) _, err := conn.Exec(ctx, q, args)
if err != nil { if err != nil {
return fmt.Errorf("cannot update policy: %w", err) return fmt.Errorf("cannot update document: %w", err)
} }
return nil return nil
} }
func (p *Policies) LoadByControlID( func (p *Documents) LoadByControlID(
ctx context.Context, ctx context.Context,
conn pg.Conn, conn pg.Conn,
scope Scoper, scope Scoper,
controlID gid.GID, controlID gid.GID,
cursor *page.Cursor[PolicyOrderField], cursor *page.Cursor[DocumentOrderField],
) error { ) error {
q := ` q := `
WITH plcs AS ( WITH plcs AS (
@@ -254,9 +254,9 @@ WITH plcs AS (
p.created_at, p.created_at,
p.updated_at p.updated_at
FROM FROM
policies p documents p
INNER JOIN INNER JOIN
controls_policies cp ON p.id = cp.policy_id controls_documents cp ON p.id = cp.document_id
WHERE WHERE
cp.control_id = @control_id cp.control_id = @control_id
) )
@@ -281,25 +281,25 @@ WHERE %s
rows, err := conn.Query(ctx, q, args) rows, err := conn.Query(ctx, q, args)
if err != nil { if err != nil {
return fmt.Errorf("cannot query policies: %w", err) return fmt.Errorf("cannot query documents: %w", err)
} }
policies, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[Policy]) documents, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[Document])
if err != nil { if err != nil {
return fmt.Errorf("cannot collect policies: %w", err) return fmt.Errorf("cannot collect documents: %w", err)
} }
*p = policies *p = documents
return nil return nil
} }
func (p *Policies) LoadByRiskID( func (p *Documents) LoadByRiskID(
ctx context.Context, ctx context.Context,
conn pg.Conn, conn pg.Conn,
scope Scoper, scope Scoper,
riskID gid.GID, riskID gid.GID,
cursor *page.Cursor[PolicyOrderField], cursor *page.Cursor[DocumentOrderField],
) error { ) error {
q := ` q := `
WITH plcs AS ( WITH plcs AS (
@@ -313,9 +313,9 @@ WITH plcs AS (
p.created_at, p.created_at,
p.updated_at p.updated_at
FROM FROM
policies p documents p
INNER JOIN INNER JOIN
risks_policies rp ON p.id = rp.policy_id risks_documents rp ON p.id = rp.document_id
WHERE WHERE
rp.risk_id = @risk_id rp.risk_id = @risk_id
) )
@@ -340,15 +340,15 @@ WHERE %s
rows, err := conn.Query(ctx, q, args) rows, err := conn.Query(ctx, q, args)
if err != nil { if err != nil {
return fmt.Errorf("cannot query policies: %w", err) return fmt.Errorf("cannot query documents: %w", err)
} }
policies, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[Policy]) documents, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[Document])
if err != nil { if err != nil {
return fmt.Errorf("cannot collect policies: %w", err) return fmt.Errorf("cannot collect documents: %w", err)
} }
*p = policies *p = documents
return nil return nil
} }

View File

@@ -15,27 +15,27 @@
package coredata package coredata
type ( type (
PolicyOrderField string DocumentOrderField string
) )
const ( const (
PolicyOrderFieldCreatedAt PolicyOrderField = "CREATED_AT" DocumentOrderFieldCreatedAt DocumentOrderField = "CREATED_AT"
PolicyOrderFieldTitle PolicyOrderField = "TITLE" DocumentOrderFieldTitle DocumentOrderField = "TITLE"
) )
func (p PolicyOrderField) Column() string { func (p DocumentOrderField) Column() string {
return string(p) return string(p)
} }
func (p PolicyOrderField) String() string { func (p DocumentOrderField) String() string {
return string(p) return string(p)
} }
func (p PolicyOrderField) MarshalText() ([]byte, error) { func (p DocumentOrderField) MarshalText() ([]byte, error) {
return []byte(p.String()), nil return []byte(p.String()), nil
} }
func (p *PolicyOrderField) UnmarshalText(text []byte) error { func (p *DocumentOrderField) UnmarshalText(text []byte) error {
*p = PolicyOrderField(text) *p = DocumentOrderField(text)
return nil return nil
} }

View File

@@ -20,55 +20,55 @@ import (
) )
type ( type (
PolicyStatus uint8 DocumentStatus uint8
) )
const ( const (
PolicyStatusDraft PolicyStatus = iota DocumentStatusDraft DocumentStatus = iota
PolicyStatusPublished DocumentStatusPublished
) )
func (ps PolicyStatus) MarshalText() ([]byte, error) { func (ps DocumentStatus) MarshalText() ([]byte, error) {
return []byte(ps.String()), nil return []byte(ps.String()), nil
} }
func (ps *PolicyStatus) UnmarshalText(data []byte) error { func (ps *DocumentStatus) UnmarshalText(data []byte) error {
val := string(data) val := string(data)
switch val { switch val {
case PolicyStatusDraft.String(): case DocumentStatusDraft.String():
*ps = PolicyStatusDraft *ps = DocumentStatusDraft
case PolicyStatusPublished.String(): case DocumentStatusPublished.String():
*ps = PolicyStatusPublished *ps = DocumentStatusPublished
default: default:
return fmt.Errorf("invalid PolicyStatus value: %q", val) return fmt.Errorf("invalid DocumentStatus value: %q", val)
} }
return nil return nil
} }
func (ps PolicyStatus) String() string { func (ps DocumentStatus) String() string {
var val string var val string
switch ps { switch ps {
case PolicyStatusDraft: case DocumentStatusDraft:
val = "DRAFT" val = "DRAFT"
case PolicyStatusPublished: case DocumentStatusPublished:
val = "PUBLISHED" val = "PUBLISHED"
} }
return val return val
} }
func (ps *PolicyStatus) Scan(value any) error { func (ps *DocumentStatus) Scan(value any) error {
val, ok := value.(string) val, ok := value.(string)
if !ok { if !ok {
return fmt.Errorf("invalid scan source for PolicyStatus, expected string got %T", value) return fmt.Errorf("invalid scan source for DocumentStatus, expected string got %T", value)
} }
return ps.UnmarshalText([]byte(val)) return ps.UnmarshalText([]byte(val))
} }
func (ps PolicyStatus) Value() (driver.Value, error) { func (ps DocumentStatus) Value() (driver.Value, error) {
return ps.String(), nil return ps.String(), nil
} }

View File

@@ -27,34 +27,34 @@ import (
) )
type ( type (
PolicyVersion struct { DocumentVersion struct {
ID gid.GID `db:"id"` ID gid.GID `db:"id"`
PolicyID gid.GID `db:"policy_id"` DocumentID gid.GID `db:"document_id"`
VersionNumber int `db:"version_number"` VersionNumber int `db:"version_number"`
Content string `db:"content"` Content string `db:"content"`
Changelog string `db:"changelog"` Changelog string `db:"changelog"`
CreatedBy gid.GID `db:"created_by"` CreatedBy gid.GID `db:"created_by"`
Status PolicyStatus `db:"status"` Status DocumentStatus `db:"status"`
PublishedBy *gid.GID `db:"published_by"` PublishedBy *gid.GID `db:"published_by"`
PublishedAt *time.Time `db:"published_at"` PublishedAt *time.Time `db:"published_at"`
CreatedAt time.Time `db:"created_at"` CreatedAt time.Time `db:"created_at"`
UpdatedAt time.Time `db:"updated_at"` UpdatedAt time.Time `db:"updated_at"`
} }
PolicyVersions []*PolicyVersion DocumentVersions []*DocumentVersion
) )
func (p *PolicyVersions) LoadByPolicyID( func (p *DocumentVersions) LoadByDocumentID(
ctx context.Context, ctx context.Context,
conn pg.Conn, conn pg.Conn,
scope Scoper, scope Scoper,
policyID gid.GID, documentID gid.GID,
cursor *page.Cursor[PolicyVersionOrderField], cursor *page.Cursor[DocumentVersionOrderField],
) error { ) error {
q := ` q := `
SELECT SELECT
id, id,
policy_id, document_id,
version_number, version_number,
content, content,
changelog, changelog,
@@ -65,53 +65,53 @@ SELECT
created_at, created_at,
updated_at updated_at
FROM FROM
policy_versions document_versions
WHERE WHERE
%s %s
AND policy_id = @policy_id AND document_id = @document_id
AND %s AND %s
` `
q = fmt.Sprintf(q, scope.SQLFragment(), cursor.SQLFragment()) q = fmt.Sprintf(q, scope.SQLFragment(), cursor.SQLFragment())
args := pgx.StrictNamedArgs{"policy_id": policyID} args := pgx.StrictNamedArgs{"document_id": documentID}
maps.Copy(args, scope.SQLArguments()) maps.Copy(args, scope.SQLArguments())
maps.Copy(args, cursor.SQLArguments()) maps.Copy(args, cursor.SQLArguments())
rows, err := conn.Query(ctx, q, args) rows, err := conn.Query(ctx, q, args)
if err != nil { if err != nil {
return fmt.Errorf("cannot query policy versions: %w", err) return fmt.Errorf("cannot query document versions: %w", err)
} }
policyVersions, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[PolicyVersion]) documentVersions, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[DocumentVersion])
if err != nil { if err != nil {
return fmt.Errorf("cannot collect policy versions: %w", err) return fmt.Errorf("cannot collect document versions: %w", err)
} }
*p = policyVersions *p = documentVersions
return nil return nil
} }
func (p PolicyVersion) CursorKey(orderBy PolicyVersionOrderField) page.CursorKey { func (p DocumentVersion) CursorKey(orderBy DocumentVersionOrderField) page.CursorKey {
switch orderBy { switch orderBy {
case PolicyVersionOrderFieldCreatedAt: case DocumentVersionOrderFieldCreatedAt:
return page.NewCursorKey(p.ID, p.CreatedAt) return page.NewCursorKey(p.ID, p.CreatedAt)
} }
panic(fmt.Sprintf("unsupported order by: %s", orderBy)) panic(fmt.Sprintf("unsupported order by: %s", orderBy))
} }
func (p *PolicyVersion) LoadByID( func (p *DocumentVersion) LoadByID(
ctx context.Context, ctx context.Context,
conn pg.Conn, conn pg.Conn,
scope Scoper, scope Scoper,
policyVersionID gid.GID, documentVersionID gid.GID,
) error { ) error {
q := ` q := `
SELECT SELECT
id, id,
policy_id, document_id,
version_number, version_number,
content, content,
changelog, changelog,
@@ -122,43 +122,43 @@ SELECT
created_at, created_at,
updated_at updated_at
FROM FROM
policy_versions document_versions
WHERE WHERE
%s %s
AND id = @policy_version_id AND id = @document_version_id
LIMIT 1; LIMIT 1;
` `
q = fmt.Sprintf(q, scope.SQLFragment()) q = fmt.Sprintf(q, scope.SQLFragment())
args := pgx.StrictNamedArgs{"policy_version_id": policyVersionID} args := pgx.StrictNamedArgs{"document_version_id": documentVersionID}
maps.Copy(args, scope.SQLArguments()) maps.Copy(args, scope.SQLArguments())
rows, err := conn.Query(ctx, q, args) rows, err := conn.Query(ctx, q, args)
if err != nil { if err != nil {
return fmt.Errorf("cannot query policy versions: %w", err) return fmt.Errorf("cannot query document versions: %w", err)
} }
policyVersion, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[PolicyVersion]) documentVersion, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[DocumentVersion])
if err != nil { if err != nil {
return fmt.Errorf("cannot collect policy version: %w", err) return fmt.Errorf("cannot collect document version: %w", err)
} }
*p = policyVersion *p = documentVersion
return nil return nil
} }
func (p PolicyVersion) Insert( func (p DocumentVersion) Insert(
ctx context.Context, ctx context.Context,
conn pg.Conn, conn pg.Conn,
scope Scoper, scope Scoper,
) error { ) error {
q := ` q := `
INSERT INTO policy_versions ( INSERT INTO document_versions (
tenant_id, tenant_id,
id, id,
policy_id, document_id,
version_number, version_number,
content, content,
changelog, changelog,
@@ -169,7 +169,7 @@ INSERT INTO policy_versions (
) VALUES ( ) VALUES (
@tenant_id, @tenant_id,
@id, @id,
@policy_id, @document_id,
@version_number, @version_number,
@content, @content,
@changelog, @changelog,
@@ -184,7 +184,7 @@ INSERT INTO policy_versions (
args := pgx.StrictNamedArgs{ args := pgx.StrictNamedArgs{
"tenant_id": scope.GetTenantID(), "tenant_id": scope.GetTenantID(),
"id": p.ID, "id": p.ID,
"policy_id": p.PolicyID, "document_id": p.DocumentID,
"version_number": p.VersionNumber, "version_number": p.VersionNumber,
"content": p.Content, "content": p.Content,
"changelog": p.Changelog, "changelog": p.Changelog,
@@ -196,23 +196,23 @@ INSERT INTO policy_versions (
_, err := conn.Exec(ctx, q, args) _, err := conn.Exec(ctx, q, args)
if err != nil { if err != nil {
return fmt.Errorf("error creating/updating policy version: %w", err) return fmt.Errorf("error creating/updating document version: %w", err)
} }
return nil return nil
} }
func (p *PolicyVersion) LoadByPolicyIDAndVersionNumber( func (p *DocumentVersion) LoadByDocumentIDAndVersionNumber(
ctx context.Context, ctx context.Context,
conn pg.Conn, conn pg.Conn,
scope Scoper, scope Scoper,
policyID gid.GID, documentID gid.GID,
versionNumber int, versionNumber int,
) error { ) error {
q := ` q := `
SELECT SELECT
id, id,
policy_id, document_id,
version_number, version_number,
content, content,
changelog, changelog,
@@ -223,10 +223,10 @@ SELECT
created_at, created_at,
updated_at updated_at
FROM FROM
policy_versions document_versions
WHERE WHERE
%s %s
AND policy_id = @policy_id AND document_id = @document_id
AND version_number = @version_number AND version_number = @version_number
LIMIT 1; LIMIT 1;
` `
@@ -234,7 +234,7 @@ LIMIT 1;
q = fmt.Sprintf(q, scope.SQLFragment()) q = fmt.Sprintf(q, scope.SQLFragment())
args := pgx.StrictNamedArgs{ args := pgx.StrictNamedArgs{
"policy_id": policyID, "document_id": documentID,
"version_number": versionNumber, "version_number": versionNumber,
} }
@@ -242,29 +242,29 @@ LIMIT 1;
rows, err := conn.Query(ctx, q, args) rows, err := conn.Query(ctx, q, args)
if err != nil { if err != nil {
return fmt.Errorf("cannot query policy versions: %w", err) return fmt.Errorf("cannot query document versions: %w", err)
} }
policyVersion, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[PolicyVersion]) documentVersion, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[DocumentVersion])
if err != nil { if err != nil {
return fmt.Errorf("cannot collect policy version: %w", err) return fmt.Errorf("cannot collect document version: %w", err)
} }
*p = policyVersion *p = documentVersion
return nil return nil
} }
func (p *PolicyVersion) LoadLatestVersion( func (p *DocumentVersion) LoadLatestVersion(
ctx context.Context, ctx context.Context,
conn pg.Conn, conn pg.Conn,
scope Scoper, scope Scoper,
policyID gid.GID, documentID gid.GID,
) error { ) error {
q := ` q := `
SELECT SELECT
id, id,
policy_id, document_id,
version_number, version_number,
content, content,
changelog, changelog,
@@ -275,10 +275,10 @@ SELECT
created_at, created_at,
updated_at updated_at
FROM FROM
policy_versions document_versions
WHERE WHERE
%s %s
AND policy_id = @policy_id AND document_id = @document_id
ORDER BY created_at DESC ORDER BY created_at DESC
LIMIT 1; LIMIT 1;
` `
@@ -286,33 +286,33 @@ LIMIT 1;
q = fmt.Sprintf(q, scope.SQLFragment()) q = fmt.Sprintf(q, scope.SQLFragment())
args := pgx.StrictNamedArgs{ args := pgx.StrictNamedArgs{
"policy_id": policyID, "document_id": documentID,
} }
maps.Copy(args, scope.SQLArguments()) maps.Copy(args, scope.SQLArguments())
rows, err := conn.Query(ctx, q, args) rows, err := conn.Query(ctx, q, args)
if err != nil { if err != nil {
return fmt.Errorf("cannot query policy versions: %w", err) return fmt.Errorf("cannot query document versions: %w", err)
} }
policyVersion, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[PolicyVersion]) documentVersion, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[DocumentVersion])
if err != nil { if err != nil {
return fmt.Errorf("cannot collect policy version: %w", err) return fmt.Errorf("cannot collect document version: %w", err)
} }
*p = policyVersion *p = documentVersion
return nil return nil
} }
func (p PolicyVersion) Update( func (p DocumentVersion) Update(
ctx context.Context, ctx context.Context,
conn pg.Conn, conn pg.Conn,
scope Scoper, scope Scoper,
) error { ) error {
q := ` q := `
UPDATE policy_versions SET UPDATE document_versions SET
changelog = @changelog, changelog = @changelog,
status = @status, status = @status,
content = @content, content = @content,
@@ -320,12 +320,12 @@ UPDATE policy_versions SET
published_at = @published_at, published_at = @published_at,
updated_at = @updated_at updated_at = @updated_at
WHERE %s WHERE %s
AND id = @policy_version_id;` AND id = @document_version_id;`
q = fmt.Sprintf(q, scope.SQLFragment()) q = fmt.Sprintf(q, scope.SQLFragment())
args := pgx.StrictNamedArgs{ args := pgx.StrictNamedArgs{
"policy_version_id": p.ID, "document_version_id": p.ID,
"changelog": p.Changelog, "changelog": p.Changelog,
"status": p.Status, "status": p.Status,
"content": p.Content, "content": p.Content,
@@ -337,7 +337,7 @@ WHERE %s
_, err := conn.Exec(ctx, q, args) _, err := conn.Exec(ctx, q, args)
if err != nil { if err != nil {
return fmt.Errorf("cannot update policy version: %w", err) return fmt.Errorf("cannot update document version: %w", err)
} }
return nil return nil

View File

@@ -15,27 +15,27 @@
package coredata package coredata
type ( type (
PolicyVersionOrderField string DocumentVersionOrderField string
) )
const ( const (
PolicyVersionOrderFieldCreatedAt PolicyVersionOrderField = "CREATED_AT" DocumentVersionOrderFieldCreatedAt DocumentVersionOrderField = "CREATED_AT"
PolicyVersionOrderFieldVersion PolicyVersionOrderField = "VERSION" DocumentVersionOrderFieldVersion DocumentVersionOrderField = "VERSION"
) )
func (p PolicyVersionOrderField) Column() string { func (p DocumentVersionOrderField) Column() string {
return string(p) return string(p)
} }
func (p PolicyVersionOrderField) String() string { func (p DocumentVersionOrderField) String() string {
return string(p) return string(p)
} }
func (p PolicyVersionOrderField) MarshalText() ([]byte, error) { func (p DocumentVersionOrderField) MarshalText() ([]byte, error) {
return []byte(p.String()), nil return []byte(p.String()), nil
} }
func (p *PolicyVersionOrderField) UnmarshalText(text []byte) error { func (p *DocumentVersionOrderField) UnmarshalText(text []byte) error {
*p = PolicyVersionOrderField(text) *p = DocumentVersionOrderField(text)
return nil return nil
} }

View File

@@ -0,0 +1,281 @@
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
package coredata
import (
"context"
"fmt"
"maps"
"time"
"github.com/getprobo/probo/pkg/gid"
"github.com/getprobo/probo/pkg/page"
"github.com/jackc/pgx/v5"
"go.gearno.de/kit/pg"
)
type (
DocumentVersionSignature struct {
ID gid.GID `json:"id"`
DocumentVersionID gid.GID `json:"document_version_id"`
State DocumentVersionSignatureState `json:"state"`
SignedBy gid.GID `json:"signed_by"`
SignedAt *time.Time `json:"signed_at"`
RequestedAt time.Time `json:"requested_at"`
RequestedBy gid.GID `json:"requested_by"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
DocumentVersionSignatures []*DocumentVersionSignature
)
func (pvs DocumentVersionSignature) CursorKey(orderBy DocumentVersionSignatureOrderField) page.CursorKey {
switch orderBy {
case DocumentVersionSignatureOrderFieldCreatedAt:
return page.NewCursorKey(pvs.ID, pvs.CreatedAt)
case DocumentVersionSignatureOrderFieldSignedAt:
return page.NewCursorKey(pvs.ID, pvs.SignedAt)
}
panic(fmt.Sprintf("unsupported order by: %s", orderBy))
}
func (pvs *DocumentVersionSignature) LoadByDocumentVersionIDAndSignatory(
ctx context.Context,
conn pg.Conn,
scope Scoper,
documentVersionID gid.GID,
signatory gid.GID,
) error {
q := `
SELECT
id,
document_version_id,
state,
signed_by,
signed_at,
requested_at,
requested_by,
created_at,
updated_at
FROM
document_version_signatures
WHERE
%s
AND document_version_id = @document_version_id
AND signed_by = @signatory
LIMIT 1
`
q = fmt.Sprintf(q, scope.SQLFragment())
args := pgx.StrictNamedArgs{"document_version_id": documentVersionID, "signatory": signatory}
maps.Copy(args, scope.SQLArguments())
rows, err := conn.Query(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot query document version signature: %w", err)
}
documentVersionSignature, err := pgx.CollectOneRow(rows, pgx.RowToStructByName[DocumentVersionSignature])
if err != nil {
return fmt.Errorf("cannot collect document version signature: %w", err)
}
*pvs = documentVersionSignature
return nil
}
func (pvs *DocumentVersionSignature) LoadByID(
ctx context.Context,
conn pg.Conn,
scope Scoper,
signatureID gid.GID,
) error {
q := `
SELECT
id,
document_version_id,
state,
signed_by,
signed_at,
requested_at,
requested_by,
created_at,
updated_at
FROM
document_version_signatures
WHERE
id = @document_version_signature_id
AND %s
`
q = fmt.Sprintf(q, scope.SQLFragment())
args := pgx.StrictNamedArgs{"document_version_signature_id": signatureID}
maps.Copy(args, scope.SQLArguments())
rows, err := conn.Query(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot query document version signature: %w", err)
}
documentVersionSignature, err := pgx.CollectOneRow(rows, pgx.RowToStructByName[DocumentVersionSignature])
if err != nil {
return fmt.Errorf("cannot collect document version signature: %w", err)
}
*pvs = documentVersionSignature
return nil
}
func (pvs DocumentVersionSignature) Insert(
ctx context.Context,
conn pg.Conn,
scope Scoper,
) error {
q := `
INSERT INTO document_version_signatures (
id,
tenant_id,
document_version_id,
state,
signed_by,
signed_at,
requested_at,
requested_by,
created_at,
updated_at
) VALUES (
@id,
@tenant_id,
@document_version_id,
@state,
@signed_by,
@signed_at,
@requested_at,
@requested_by,
@created_at,
@updated_at
)
`
args := pgx.StrictNamedArgs{
"id": pvs.ID,
"tenant_id": scope.GetTenantID(),
"document_version_id": pvs.DocumentVersionID,
"state": pvs.State,
"signed_by": pvs.SignedBy,
"signed_at": pvs.SignedAt,
"requested_at": pvs.RequestedAt,
"requested_by": pvs.RequestedBy,
"created_at": pvs.CreatedAt,
"updated_at": pvs.UpdatedAt,
}
_, err := conn.Exec(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot insert document version signature: %w", err)
}
return nil
}
func (pvss *DocumentVersionSignatures) LoadByDocumentVersionID(
ctx context.Context,
conn pg.Conn,
scope Scoper,
documentVersionID gid.GID,
cursor *page.Cursor[DocumentVersionSignatureOrderField],
) error {
q := `
SELECT
id,
document_version_id,
state,
signed_by,
signed_at,
requested_at,
requested_by,
created_at,
updated_at
FROM
document_version_signatures
WHERE
%s
AND document_version_id = @document_version_id
AND %s
`
q = fmt.Sprintf(q, scope.SQLFragment(), cursor.SQLFragment())
args := pgx.StrictNamedArgs{"document_version_id": documentVersionID}
maps.Copy(args, scope.SQLArguments())
maps.Copy(args, cursor.SQLArguments())
rows, err := conn.Query(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot query document version signatures: %w", err)
}
documentVersionSignatures, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[DocumentVersionSignature])
if err != nil {
return fmt.Errorf("cannot collect document version signatures: %w", err)
}
*pvss = documentVersionSignatures
return nil
}
func (pvs *DocumentVersionSignature) Update(
ctx context.Context,
conn pg.Conn,
scope Scoper,
) error {
q := `
UPDATE document_version_signatures
SET
state = @state,
signed_by = @signed_by,
signed_at = @signed_at,
updated_at = @updated_at
WHERE
%s
AND id = @id
`
q = fmt.Sprintf(q, scope.SQLFragment())
args := pgx.StrictNamedArgs{
"id": pvs.ID,
"state": pvs.State,
"signed_by": pvs.SignedBy,
"signed_at": pvs.SignedAt,
"updated_at": pvs.UpdatedAt,
}
maps.Copy(args, scope.SQLArguments())
_, err := conn.Exec(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot update document version signature: %w", err)
}
return nil
}

View File

@@ -15,27 +15,27 @@
package coredata package coredata
type ( type (
PolicyVersionSignatureOrderField string DocumentVersionSignatureOrderField string
) )
const ( const (
PolicyVersionSignatureOrderFieldCreatedAt PolicyVersionSignatureOrderField = "CREATED_AT" DocumentVersionSignatureOrderFieldCreatedAt DocumentVersionSignatureOrderField = "CREATED_AT"
PolicyVersionSignatureOrderFieldSignedAt PolicyVersionSignatureOrderField = "SIGNED_AT" DocumentVersionSignatureOrderFieldSignedAt DocumentVersionSignatureOrderField = "SIGNED_AT"
) )
func (p PolicyVersionSignatureOrderField) Column() string { func (p DocumentVersionSignatureOrderField) Column() string {
return string(p) return string(p)
} }
func (p PolicyVersionSignatureOrderField) String() string { func (p DocumentVersionSignatureOrderField) String() string {
return string(p) return string(p)
} }
func (p PolicyVersionSignatureOrderField) MarshalText() ([]byte, error) { func (p DocumentVersionSignatureOrderField) MarshalText() ([]byte, error) {
return []byte(p.String()), nil return []byte(p.String()), nil
} }
func (p *PolicyVersionSignatureOrderField) UnmarshalText(text []byte) error { func (p *DocumentVersionSignatureOrderField) UnmarshalText(text []byte) error {
*p = PolicyVersionSignatureOrderField(text) *p = DocumentVersionSignatureOrderField(text)
return nil return nil
} }

View File

@@ -20,57 +20,57 @@ import (
) )
type ( type (
PolicyVersionSignatureState string DocumentVersionSignatureState string
) )
const ( const (
PolicyVersionSignatureStateRequested PolicyVersionSignatureState = "REQUESTED" DocumentVersionSignatureStateRequested DocumentVersionSignatureState = "REQUESTED"
PolicyVersionSignatureStateSigned PolicyVersionSignatureState = "SIGNED" DocumentVersionSignatureStateSigned DocumentVersionSignatureState = "SIGNED"
) )
func (pvs PolicyVersionSignatureState) MarshalText() ([]byte, error) { func (pvs DocumentVersionSignatureState) MarshalText() ([]byte, error) {
return []byte(pvs.String()), nil return []byte(pvs.String()), nil
} }
func (pvs *PolicyVersionSignatureState) UnmarshalText(data []byte) error { func (pvs *DocumentVersionSignatureState) UnmarshalText(data []byte) error {
val := string(data) val := string(data)
switch val { switch val {
case PolicyVersionSignatureStateRequested.String(): case DocumentVersionSignatureStateRequested.String():
*pvs = PolicyVersionSignatureStateRequested *pvs = DocumentVersionSignatureStateRequested
case PolicyVersionSignatureStateSigned.String(): case DocumentVersionSignatureStateSigned.String():
*pvs = PolicyVersionSignatureStateSigned *pvs = DocumentVersionSignatureStateSigned
default: default:
return fmt.Errorf("invalid PolicyVersionSignatureState value: %q", val) return fmt.Errorf("invalid DocumentVersionSignatureState value: %q", val)
} }
return nil return nil
} }
func (pvs PolicyVersionSignatureState) String() string { func (pvs DocumentVersionSignatureState) String() string {
var val string var val string
switch pvs { switch pvs {
case PolicyVersionSignatureStateRequested: case DocumentVersionSignatureStateRequested:
val = "REQUESTED" val = "REQUESTED"
case PolicyVersionSignatureStateSigned: case DocumentVersionSignatureStateSigned:
val = "SIGNED" val = "SIGNED"
default: default:
panic(fmt.Errorf("invalid PolicyVersionSignatureState value: %q", string(pvs))) panic(fmt.Errorf("invalid DocumentVersionSignatureState value: %q", string(pvs)))
} }
return val return val
} }
func (pvs *PolicyVersionSignatureState) Scan(value any) error { func (pvs *DocumentVersionSignatureState) Scan(value any) error {
val, ok := value.(string) val, ok := value.(string)
if !ok { if !ok {
return fmt.Errorf("invalid scan source for PolicyVersionSignatureState, expected string got %T", value) return fmt.Errorf("invalid scan source for DocumentVersionSignatureState, expected string got %T", value)
} }
return pvs.UnmarshalText([]byte(val)) return pvs.UnmarshalText([]byte(val))
} }
func (pvs PolicyVersionSignatureState) Value() (driver.Value, error) { func (pvs DocumentVersionSignatureState) Value() (driver.Value, error) {
return pvs.String(), nil return pvs.String(), nil
} }

View File

@@ -25,12 +25,12 @@ const (
VendorEntityType VendorEntityType
PeopleEntityType PeopleEntityType
VendorComplianceReportEntityType VendorComplianceReportEntityType
PolicyEntityType DocumentEntityType
UserEntityType UserEntityType
SessionEntityType SessionEntityType
EmailEntityType EmailEntityType
ControlEntityType ControlEntityType
RiskEntityType RiskEntityType
PolicyVersionEntityType DocumentVersionEntityType
PolicyVersionSignatureEntityType DocumentVersionSignatureEntityType
) )

View File

@@ -0,0 +1,36 @@
-- Rename policies table to documents
ALTER TABLE policies RENAME TO documents;
-- Rename risks_policies table to risks_documents
ALTER TABLE risks_policies RENAME TO risks_documents;
-- Update the foreign key reference in risks_documents
ALTER TABLE risks_documents RENAME CONSTRAINT risks_policies_policy_id_fkey TO risks_documents_document_id_fkey;
-- Rename the policy_id column in risks_documents to document_id
ALTER TABLE risks_documents RENAME COLUMN policy_id TO document_id;
-- Rename controls_policies table to controls_documents
ALTER TABLE controls_policies RENAME TO controls_documents;
-- Update controls_documents foreign key and column
ALTER TABLE controls_documents RENAME COLUMN policy_id TO document_id;
ALTER TABLE controls_documents RENAME CONSTRAINT controls_policies_policy_id_fkey TO controls_documents_document_id_fkey;
-- Rename policy_versions table to document_versions
ALTER TABLE policy_versions RENAME TO document_versions;
-- Update document_versions foreign key and column
ALTER TABLE document_versions RENAME COLUMN policy_id TO document_id;
ALTER TABLE document_versions RENAME CONSTRAINT policy_versions_policy_id_fkey TO document_versions_document_id_fkey;
-- Rename policy_version_signatures table to document_version_signatures
ALTER TABLE policy_version_signatures RENAME TO document_version_signatures;
-- Update document_version_signatures foreign key and column
ALTER TABLE document_version_signatures RENAME COLUMN policy_version_id TO document_version_id;
ALTER TABLE document_version_signatures RENAME CONSTRAINT policy_version_signatures_policy_version_id_fkey TO document_version_signatures_document_version_id_fkey;
-- Rename the unique index, preserving the WHERE clause
DROP INDEX policy_one_draft_version_idx;
CREATE UNIQUE INDEX document_one_draft_version_idx ON document_versions (document_id, status) WHERE status = 'DRAFT';

View File

@@ -1,281 +0,0 @@
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
package coredata
import (
"context"
"fmt"
"maps"
"time"
"github.com/getprobo/probo/pkg/gid"
"github.com/getprobo/probo/pkg/page"
"github.com/jackc/pgx/v5"
"go.gearno.de/kit/pg"
)
type (
PolicyVersionSignature struct {
ID gid.GID `json:"id"`
PolicyVersionID gid.GID `json:"policy_version_id"`
State PolicyVersionSignatureState `json:"state"`
SignedBy gid.GID `json:"signed_by"`
SignedAt *time.Time `json:"signed_at"`
RequestedAt time.Time `json:"requested_at"`
RequestedBy gid.GID `json:"requested_by"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
PolicyVersionSignatures []*PolicyVersionSignature
)
func (pvs PolicyVersionSignature) CursorKey(orderBy PolicyVersionSignatureOrderField) page.CursorKey {
switch orderBy {
case PolicyVersionSignatureOrderFieldCreatedAt:
return page.NewCursorKey(pvs.ID, pvs.CreatedAt)
case PolicyVersionSignatureOrderFieldSignedAt:
return page.NewCursorKey(pvs.ID, pvs.SignedAt)
}
panic(fmt.Sprintf("unsupported order by: %s", orderBy))
}
func (pvs *PolicyVersionSignature) LoadByPolicyVersionIDAndSignatory(
ctx context.Context,
conn pg.Conn,
scope Scoper,
policyVersionID gid.GID,
signatory gid.GID,
) error {
q := `
SELECT
id,
policy_version_id,
state,
signed_by,
signed_at,
requested_at,
requested_by,
created_at,
updated_at
FROM
policy_version_signatures
WHERE
%s
AND policy_version_id = @policy_version_id
AND signed_by = @signatory
LIMIT 1
`
q = fmt.Sprintf(q, scope.SQLFragment())
args := pgx.StrictNamedArgs{"policy_version_id": policyVersionID, "signatory": signatory}
maps.Copy(args, scope.SQLArguments())
rows, err := conn.Query(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot query policy version signature: %w", err)
}
policyVersionSignature, err := pgx.CollectOneRow(rows, pgx.RowToStructByName[PolicyVersionSignature])
if err != nil {
return fmt.Errorf("cannot collect policy version signature: %w", err)
}
*pvs = policyVersionSignature
return nil
}
func (pvs *PolicyVersionSignature) LoadByID(
ctx context.Context,
conn pg.Conn,
scope Scoper,
signatureID gid.GID,
) error {
q := `
SELECT
id,
policy_version_id,
state,
signed_by,
signed_at,
requested_at,
requested_by,
created_at,
updated_at
FROM
policy_version_signatures
WHERE
id = @policy_version_signature_id
AND %s
`
q = fmt.Sprintf(q, scope.SQLFragment())
args := pgx.StrictNamedArgs{"policy_version_signature_id": signatureID}
maps.Copy(args, scope.SQLArguments())
rows, err := conn.Query(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot query policy version signature: %w", err)
}
policyVersionSignature, err := pgx.CollectOneRow(rows, pgx.RowToStructByName[PolicyVersionSignature])
if err != nil {
return fmt.Errorf("cannot collect policy version signature: %w", err)
}
*pvs = policyVersionSignature
return nil
}
func (pvs PolicyVersionSignature) Insert(
ctx context.Context,
conn pg.Conn,
scope Scoper,
) error {
q := `
INSERT INTO policy_version_signatures (
id,
tenant_id,
policy_version_id,
state,
signed_by,
signed_at,
requested_at,
requested_by,
created_at,
updated_at
) VALUES (
@id,
@tenant_id,
@policy_version_id,
@state,
@signed_by,
@signed_at,
@requested_at,
@requested_by,
@created_at,
@updated_at
)
`
args := pgx.StrictNamedArgs{
"id": pvs.ID,
"tenant_id": scope.GetTenantID(),
"policy_version_id": pvs.PolicyVersionID,
"state": pvs.State,
"signed_by": pvs.SignedBy,
"signed_at": pvs.SignedAt,
"requested_at": pvs.RequestedAt,
"requested_by": pvs.RequestedBy,
"created_at": pvs.CreatedAt,
"updated_at": pvs.UpdatedAt,
}
_, err := conn.Exec(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot insert policy version signature: %w", err)
}
return nil
}
func (pvss *PolicyVersionSignatures) LoadByPolicyVersionID(
ctx context.Context,
conn pg.Conn,
scope Scoper,
policyVersionID gid.GID,
cursor *page.Cursor[PolicyVersionSignatureOrderField],
) error {
q := `
SELECT
id,
policy_version_id,
state,
signed_by,
signed_at,
requested_at,
requested_by,
created_at,
updated_at
FROM
policy_version_signatures
WHERE
%s
AND policy_version_id = @policy_version_id
AND %s
`
q = fmt.Sprintf(q, scope.SQLFragment(), cursor.SQLFragment())
args := pgx.StrictNamedArgs{"policy_version_id": policyVersionID}
maps.Copy(args, scope.SQLArguments())
maps.Copy(args, cursor.SQLArguments())
rows, err := conn.Query(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot query policy version signatures: %w", err)
}
policyVersionSignatures, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[PolicyVersionSignature])
if err != nil {
return fmt.Errorf("cannot collect policy version signatures: %w", err)
}
*pvss = policyVersionSignatures
return nil
}
func (pvs *PolicyVersionSignature) Update(
ctx context.Context,
conn pg.Conn,
scope Scoper,
) error {
q := `
UPDATE policy_version_signatures
SET
state = @state,
signed_by = @signed_by,
signed_at = @signed_at,
updated_at = @updated_at
WHERE
%s
AND id = @id
`
q = fmt.Sprintf(q, scope.SQLFragment())
args := pgx.StrictNamedArgs{
"id": pvs.ID,
"state": pvs.State,
"signed_by": pvs.SignedBy,
"signed_at": pvs.SignedAt,
"updated_at": pvs.UpdatedAt,
}
maps.Copy(args, scope.SQLArguments())
_, err := conn.Exec(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot update policy version signature: %w", err)
}
return nil
}

View File

@@ -26,32 +26,32 @@ import (
) )
type ( type (
RiskPolicy struct { RiskDocument struct {
RiskID gid.GID `db:"risk_id"` RiskID gid.GID `db:"risk_id"`
PolicyID gid.GID `db:"policy_id"` DocumentID gid.GID `db:"document_id"`
TenantID gid.TenantID `db:"tenant_id"` TenantID gid.TenantID `db:"tenant_id"`
CreatedAt time.Time `db:"created_at"` CreatedAt time.Time `db:"created_at"`
} }
RiskPolicies []*RiskPolicy RiskDocuments []*RiskDocument
) )
func (rp RiskPolicy) Insert( func (rp RiskDocument) Insert(
ctx context.Context, ctx context.Context,
conn pg.Conn, conn pg.Conn,
scope Scoper, scope Scoper,
) error { ) error {
q := ` q := `
INSERT INTO INSERT INTO
risks_policies ( risks_documents (
risk_id, risk_id,
policy_id, document_id,
tenant_id, tenant_id,
created_at created_at
) )
VALUES ( VALUES (
@risk_id, @risk_id,
@policy_id, @document_id,
@tenant_id, @tenant_id,
@created_at @created_at
); );
@@ -59,7 +59,7 @@ VALUES (
args := pgx.StrictNamedArgs{ args := pgx.StrictNamedArgs{
"risk_id": rp.RiskID, "risk_id": rp.RiskID,
"policy_id": rp.PolicyID, "document_id": rp.DocumentID,
"tenant_id": scope.GetTenantID(), "tenant_id": scope.GetTenantID(),
"created_at": rp.CreatedAt, "created_at": rp.CreatedAt,
} }
@@ -67,28 +67,28 @@ VALUES (
return err return err
} }
func (rp RiskPolicy) Delete( func (rp RiskDocument) Delete(
ctx context.Context, ctx context.Context,
conn pg.Conn, conn pg.Conn,
scope Scoper, scope Scoper,
riskID gid.GID, riskID gid.GID,
policyID gid.GID, documentID gid.GID,
) error { ) error {
q := ` q := `
DELETE DELETE
FROM FROM
risks_policies risks_documents
WHERE WHERE
%s %s
AND risk_id = @risk_id AND risk_id = @risk_id
AND policy_id = @policy_id; AND document_id = @document_id;
` `
q = fmt.Sprintf(q, scope.SQLFragment()) q = fmt.Sprintf(q, scope.SQLFragment())
args := pgx.StrictNamedArgs{ args := pgx.StrictNamedArgs{
"risk_id": riskID, "risk_id": riskID,
"policy_id": policyID, "document_id": documentID,
} }
maps.Copy(args, scope.SQLArguments()) maps.Copy(args, scope.SQLArguments())

View File

@@ -55,22 +55,22 @@ type (
} }
) )
func (s ControlService) ListForPolicyID( func (s ControlService) ListForDocumentID(
ctx context.Context, ctx context.Context,
policyID gid.GID, documentID gid.GID,
cursor *page.Cursor[coredata.ControlOrderField], cursor *page.Cursor[coredata.ControlOrderField],
) (*page.Page[*coredata.Control, coredata.ControlOrderField], error) { ) (*page.Page[*coredata.Control, coredata.ControlOrderField], error) {
var controls coredata.Controls var controls coredata.Controls
policy := &coredata.Policy{} document := &coredata.Document{}
err := s.svc.pg.WithConn( err := s.svc.pg.WithConn(
ctx, ctx,
func(conn pg.Conn) error { func(conn pg.Conn) error {
if err := policy.LoadByID(ctx, conn, s.svc.scope, policyID); err != nil { if err := document.LoadByID(ctx, conn, s.svc.scope, documentID); err != nil {
return fmt.Errorf("cannot load policy: %w", err) return fmt.Errorf("cannot load document: %w", err)
} }
return controls.LoadByPolicyID(ctx, conn, s.svc.scope, policyID, cursor) return controls.LoadByDocumentID(ctx, conn, s.svc.scope, documentID, cursor)
}, },
) )
@@ -179,13 +179,13 @@ func (s ControlService) DeleteMeasureMapping(
return control, measure, nil return control, measure, nil
} }
func (s ControlService) CreatePolicyMapping( func (s ControlService) CreateDocumentMapping(
ctx context.Context, ctx context.Context,
controlID gid.GID, controlID gid.GID,
policyID gid.GID, documentID gid.GID,
) (*coredata.Control, *coredata.Policy, error) { ) (*coredata.Control, *coredata.Document, error) {
control := &coredata.Control{} control := &coredata.Control{}
policy := &coredata.Policy{} document := &coredata.Document{}
err := s.svc.pg.WithConn( err := s.svc.pg.WithConn(
ctx, ctx,
@@ -194,19 +194,19 @@ func (s ControlService) CreatePolicyMapping(
return fmt.Errorf("cannot load control: %w", err) return fmt.Errorf("cannot load control: %w", err)
} }
if err := policy.LoadByID(ctx, conn, s.svc.scope, policyID); err != nil { if err := document.LoadByID(ctx, conn, s.svc.scope, documentID); err != nil {
return fmt.Errorf("cannot load policy: %w", err) return fmt.Errorf("cannot load document: %w", err)
} }
controlPolicy := &coredata.ControlPolicy{ controlDocument := &coredata.ControlDocument{
ControlID: control.ID, ControlID: control.ID,
PolicyID: policy.ID, DocumentID: document.ID,
TenantID: s.svc.scope.GetTenantID(), TenantID: s.svc.scope.GetTenantID(),
CreatedAt: time.Now(), CreatedAt: time.Now(),
} }
if err := controlPolicy.Insert(ctx, conn, s.svc.scope); err != nil { if err := controlDocument.Insert(ctx, conn, s.svc.scope); err != nil {
return fmt.Errorf("cannot insert control policy: %w", err) return fmt.Errorf("cannot insert control document: %w", err)
} }
return nil return nil
@@ -214,19 +214,19 @@ func (s ControlService) CreatePolicyMapping(
) )
if err != nil { if err != nil {
return nil, nil, fmt.Errorf("cannot create control policy mapping: %w", err) return nil, nil, fmt.Errorf("cannot create control document mapping: %w", err)
} }
return control, policy, nil return control, document, nil
} }
func (s ControlService) DeletePolicyMapping( func (s ControlService) DeleteDocumentMapping(
ctx context.Context, ctx context.Context,
controlID gid.GID, controlID gid.GID,
policyID gid.GID, documentID gid.GID,
) (*coredata.Control, *coredata.Policy, error) { ) (*coredata.Control, *coredata.Document, error) {
control := &coredata.Control{} control := &coredata.Control{}
policy := &coredata.Policy{} document := &coredata.Document{}
err := s.svc.pg.WithConn( err := s.svc.pg.WithConn(
ctx, ctx,
@@ -235,13 +235,13 @@ func (s ControlService) DeletePolicyMapping(
return fmt.Errorf("cannot load control: %w", err) return fmt.Errorf("cannot load control: %w", err)
} }
if err := policy.LoadByID(ctx, conn, s.svc.scope, policyID); err != nil { if err := document.LoadByID(ctx, conn, s.svc.scope, documentID); err != nil {
return fmt.Errorf("cannot load policy: %w", err) return fmt.Errorf("cannot load document: %w", err)
} }
controlPolicy := &coredata.ControlPolicy{} controlDocument := &coredata.ControlDocument{}
if err := controlPolicy.Delete(ctx, conn, s.svc.scope, control.ID, policy.ID); err != nil { if err := controlDocument.Delete(ctx, conn, s.svc.scope, control.ID, document.ID); err != nil {
return fmt.Errorf("cannot delete control policy mapping: %w", err) return fmt.Errorf("cannot delete control document mapping: %w", err)
} }
return nil return nil
@@ -249,10 +249,10 @@ func (s ControlService) DeletePolicyMapping(
) )
if err != nil { if err != nil {
return nil, nil, fmt.Errorf("cannot delete control policy mapping: %w", err) return nil, nil, fmt.Errorf("cannot delete control document mapping: %w", err)
} }
return control, policy, nil return control, document, nil
} }
func (s ControlService) Create( func (s ControlService) Create(

View File

@@ -0,0 +1,634 @@
package probo
import (
"context"
"fmt"
"net/url"
"time"
"github.com/getprobo/probo/pkg/coredata"
"github.com/getprobo/probo/pkg/gid"
"github.com/getprobo/probo/pkg/page"
"github.com/getprobo/probo/pkg/statelesstoken"
"github.com/jackc/pgx/v5"
"go.gearno.de/kit/pg"
)
type (
DocumentService struct {
svc *TenantService
}
CreateDocumentRequest struct {
OrganizationID gid.GID
Title string
Content string
OwnerID gid.GID
CreatedBy gid.GID
}
UpdateDocumentVersionRequest struct {
ID gid.GID
Content string
}
RequestSignatureRequest struct {
DocumentVersionID gid.GID
RequestedBy gid.GID
Signatory gid.GID
}
SigningRequestData struct {
OrganizationID gid.GID `json:"organization_id"`
PeopleID gid.GID `json:"people_id"`
}
)
const (
TokenTypeSigningRequest = "signing_request"
)
func (s *DocumentService) Get(
ctx context.Context,
documentID gid.GID,
) (*coredata.Document, error) {
document := &coredata.Document{}
err := s.svc.pg.WithConn(
ctx,
func(conn pg.Conn) error {
return document.LoadByID(ctx, conn, s.svc.scope, documentID)
},
)
if err != nil {
return nil, err
}
return document, nil
}
func (s *DocumentService) PublishVersion(
ctx context.Context,
documentID gid.GID,
publishedBy gid.GID,
) (*coredata.Document, *coredata.DocumentVersion, error) {
document := &coredata.Document{}
documentVersion := &coredata.DocumentVersion{}
now := time.Now()
err := s.svc.pg.WithTx(
ctx,
func(tx pg.Conn) error {
if err := document.LoadByID(ctx, tx, s.svc.scope, documentID); err != nil {
return fmt.Errorf("cannot load document %q: %w", documentID, err)
}
if err := documentVersion.LoadLatestVersion(ctx, tx, s.svc.scope, documentID); err != nil {
return fmt.Errorf("cannot load current draft: %w", err)
}
if documentVersion.Status != coredata.DocumentStatusDraft {
return fmt.Errorf("cannot publish version")
}
document.CurrentPublishedVersion = &documentVersion.VersionNumber
document.UpdatedAt = now
documentVersion.Status = coredata.DocumentStatusPublished
documentVersion.PublishedAt = &now
documentVersion.PublishedBy = &publishedBy
documentVersion.UpdatedAt = now
if err := document.Update(ctx, tx, s.svc.scope); err != nil {
return fmt.Errorf("cannot update document: %w", err)
}
if err := documentVersion.Update(ctx, tx, s.svc.scope); err != nil {
return fmt.Errorf("cannot update document version: %w", err)
}
return nil
},
)
if err != nil {
return nil, nil, err
}
return document, documentVersion, nil
}
func (s *DocumentService) Create(
ctx context.Context,
req CreateDocumentRequest,
) (*coredata.Document, *coredata.DocumentVersion, error) {
now := time.Now()
documentID := gid.New(s.svc.scope.GetTenantID(), coredata.DocumentEntityType)
documentVersionID := gid.New(s.svc.scope.GetTenantID(), coredata.DocumentVersionEntityType)
organization := &coredata.Organization{}
people := &coredata.People{}
document := &coredata.Document{
ID: documentID,
Title: req.Title,
CreatedAt: now,
UpdatedAt: now,
}
documentVersion := &coredata.DocumentVersion{
ID: documentVersionID,
DocumentID: documentID,
VersionNumber: 1,
Content: req.Content,
Status: coredata.DocumentStatusDraft,
CreatedBy: req.CreatedBy,
CreatedAt: now,
UpdatedAt: now,
}
err := s.svc.pg.WithTx(
ctx,
func(conn pg.Conn) error {
if err := organization.LoadByID(ctx, conn, s.svc.scope, req.OrganizationID); err != nil {
return fmt.Errorf("cannot load organization: %w", err)
}
if err := people.LoadByID(ctx, conn, s.svc.scope, req.OwnerID); err != nil {
return fmt.Errorf("cannot load people: %w", err)
}
document.OrganizationID = organization.ID
document.OwnerID = people.ID
if err := document.Insert(ctx, conn, s.svc.scope); err != nil {
return fmt.Errorf("cannot insert document: %w", err)
}
if err := documentVersion.Insert(ctx, conn, s.svc.scope); err != nil {
return fmt.Errorf("cannot create document version: %w", err)
}
return nil
},
)
if err != nil {
return nil, nil, err
}
return document, documentVersion, nil
}
func (s *DocumentService) ListSigningRequests(
ctx context.Context,
organizationID gid.GID,
peopleID gid.GID,
) ([]map[string]any, error) {
q := `
SELECT
p.title,
pv.content,
pv.id AS document_version_id
FROM
documents p
INNER JOIN document_versions pv ON pv.document_id = p.id
INNER JOIN document_version_signatures pvs ON pvs.document_version_id = pv.id
WHERE
p.tenant_id = $1
AND pvs.signed_by = $2
AND pvs.signed_at IS NULL
`
var results []map[string]any
err := s.svc.pg.WithConn(
ctx,
func(conn pg.Conn) error {
rows, err := conn.Query(ctx, q, s.svc.scope.GetTenantID(), peopleID)
if err != nil {
return fmt.Errorf("cannot query documents: %w", err)
}
results, err = pgx.CollectRows(rows, pgx.RowToMap)
if err != nil {
return err
}
return nil
},
)
if err != nil {
return nil, err
}
return results, nil
}
func (s *DocumentService) SendSigningNotifications(
ctx context.Context,
organizationID gid.GID,
) error {
err := s.svc.pg.WithTx(
ctx,
func(tx pg.Conn) error {
var peoples coredata.Peoples
if err := peoples.LoadAwaitingSigning(ctx, tx, s.svc.scope); err != nil {
return fmt.Errorf("cannot load people: %w", err)
}
for _, people := range peoples {
now := time.Now()
emailID := gid.New(s.svc.scope.GetTenantID(), coredata.EmailEntityType)
token, err := statelesstoken.NewToken(
s.svc.tokenSecret,
TokenTypeSigningRequest,
time.Hour*24*7,
SigningRequestData{
OrganizationID: organizationID,
PeopleID: people.ID,
},
)
if err != nil {
return fmt.Errorf("cannot create signing request token: %w", err)
}
signRequestURL := url.URL{
Scheme: "https",
Host: s.svc.hostname,
Path: "/documents/signing-requests",
RawQuery: url.Values{
"token": []string{token},
}.Encode(),
}
email := &coredata.Email{
ID: emailID,
RecipientEmail: people.PrimaryEmailAddress,
RecipientName: people.FullName,
Subject: "Probo - Documents Signing Request",
TextBody: fmt.Sprintf("Hi,\nYou have documents awaiting your signature. Please follow this link to sign them: %s", signRequestURL.String()),
CreatedAt: now,
UpdatedAt: now,
}
if err := email.Insert(ctx, tx); err != nil {
return fmt.Errorf("cannot insert email: %w", err)
}
}
return nil
},
)
if err != nil {
return fmt.Errorf("cannot send signing notifications: %w", err)
}
return nil
}
func (s *DocumentService) SignDocumentVersion(
ctx context.Context,
documentVersionID gid.GID,
signatory gid.GID,
) error {
documentVersion := &coredata.DocumentVersion{}
documentVersionSignature := &coredata.DocumentVersionSignature{}
now := time.Now()
err := s.svc.pg.WithTx(
ctx,
func(conn pg.Conn) error {
if err := documentVersion.LoadByID(ctx, conn, s.svc.scope, documentVersionID); err != nil {
return fmt.Errorf("cannot load document version %q: %w", documentVersionID, err)
}
if documentVersion.Status != coredata.DocumentStatusPublished {
return fmt.Errorf("cannot sign unpublished version")
}
if err := documentVersionSignature.LoadByDocumentVersionIDAndSignatory(ctx, conn, s.svc.scope, documentVersionID, signatory); err != nil {
return fmt.Errorf("cannot load document version signature: %w", err)
}
if documentVersionSignature.State == coredata.DocumentVersionSignatureStateSigned {
return fmt.Errorf("document version already signed")
}
documentVersionSignature.State = coredata.DocumentVersionSignatureStateSigned
documentVersionSignature.SignedAt = &now
documentVersionSignature.UpdatedAt = now
if err := documentVersion.Update(ctx, conn, s.svc.scope); err != nil {
return fmt.Errorf("cannot update document version: %w", err)
}
if err := documentVersionSignature.Update(ctx, conn, s.svc.scope); err != nil {
return fmt.Errorf("cannot update document version signature: %w", err)
}
return nil
},
)
if err != nil {
return fmt.Errorf("cannot sign document version: %w", err)
}
return nil
}
func (s *DocumentService) UpdateVersion(
ctx context.Context,
req UpdateDocumentVersionRequest,
) (*coredata.DocumentVersion, error) {
documentVersion := &coredata.DocumentVersion{}
err := s.svc.pg.WithTx(
ctx,
func(conn pg.Conn) error {
if err := documentVersion.LoadByID(ctx, conn, s.svc.scope, req.ID); err != nil {
return fmt.Errorf("cannot load document version %q: %w", req.ID, err)
}
if documentVersion.Status != coredata.DocumentStatusDraft {
return fmt.Errorf("cannot update published version")
}
documentVersion.Content = req.Content
documentVersion.UpdatedAt = time.Now()
if err := documentVersion.Update(ctx, conn, s.svc.scope); err != nil {
return fmt.Errorf("cannot update document version: %w", err)
}
return nil
},
)
if err != nil {
return nil, err
}
return documentVersion, nil
}
func (s *DocumentService) GetVersionSignature(
ctx context.Context,
signatureID gid.GID,
) (*coredata.DocumentVersionSignature, error) {
documentVersionSignature := &coredata.DocumentVersionSignature{}
err := s.svc.pg.WithConn(
ctx,
func(conn pg.Conn) error {
return documentVersionSignature.LoadByID(ctx, conn, s.svc.scope, signatureID)
},
)
if err != nil {
return nil, err
}
return documentVersionSignature, nil
}
func (s *DocumentService) RequestSignature(
ctx context.Context,
req RequestSignatureRequest,
) (*coredata.DocumentVersionSignature, error) {
documentVersionSignatureID := gid.New(s.svc.scope.GetTenantID(), coredata.DocumentVersionSignatureEntityType)
documentVersion, err := s.GetVersion(ctx, req.DocumentVersionID)
if err != nil {
return nil, fmt.Errorf("cannot get document version: %w", err)
}
if documentVersion.Status != coredata.DocumentStatusPublished {
return nil, fmt.Errorf("cannot request signature for unpublished version")
}
now := time.Now()
documentVersionSignature := &coredata.DocumentVersionSignature{
ID: documentVersionSignatureID,
DocumentVersionID: req.DocumentVersionID,
State: coredata.DocumentVersionSignatureStateRequested,
RequestedBy: req.RequestedBy,
RequestedAt: now,
SignedBy: req.Signatory,
SignedAt: nil,
CreatedAt: now,
UpdatedAt: now,
}
err = s.svc.pg.WithTx(
ctx,
func(conn pg.Conn) error {
if err := documentVersionSignature.Insert(ctx, conn, s.svc.scope); err != nil {
return fmt.Errorf("cannot insert document version signature: %w", err)
}
return nil
},
)
if err != nil {
return nil, err
}
return documentVersionSignature, nil
}
func (s *DocumentService) ListSignatures(
ctx context.Context,
documentVersionID gid.GID,
cursor *page.Cursor[coredata.DocumentVersionSignatureOrderField],
) (*page.Page[*coredata.DocumentVersionSignature, coredata.DocumentVersionSignatureOrderField], error) {
var documentVersionSignatures coredata.DocumentVersionSignatures
err := s.svc.pg.WithConn(
ctx,
func(conn pg.Conn) error {
return documentVersionSignatures.LoadByDocumentVersionID(ctx, conn, s.svc.scope, documentVersionID, cursor)
},
)
if err != nil {
return nil, err
}
return page.NewPage(documentVersionSignatures, cursor), nil
}
func (s *DocumentService) CreateDraft(
ctx context.Context,
documentID gid.GID,
createdBy gid.GID,
) (*coredata.DocumentVersion, error) {
draftVersionID := gid.New(s.svc.scope.GetTenantID(), coredata.DocumentVersionEntityType)
latestVersion := &coredata.DocumentVersion{}
draftVersion := &coredata.DocumentVersion{}
now := time.Now()
err := s.svc.pg.WithTx(
ctx,
func(conn pg.Conn) error {
if err := latestVersion.LoadLatestVersion(ctx, conn, s.svc.scope, documentID); err != nil {
return fmt.Errorf("cannot load latest version: %w", err)
}
if latestVersion.Status != coredata.DocumentStatusPublished {
return fmt.Errorf("cannot create draft from unpublished version")
}
draftVersion.ID = draftVersionID
draftVersion.DocumentID = documentID
draftVersion.VersionNumber = latestVersion.VersionNumber + 1
draftVersion.Content = latestVersion.Content
draftVersion.Status = coredata.DocumentStatusDraft
draftVersion.CreatedBy = createdBy
draftVersion.CreatedAt = now
draftVersion.UpdatedAt = now
if err := draftVersion.Insert(ctx, conn, s.svc.scope); err != nil {
return fmt.Errorf("cannot create draft: %w", err)
}
return nil
},
)
if err != nil {
return nil, err
}
return draftVersion, nil
}
func (s *DocumentService) Delete(
ctx context.Context,
documentID gid.GID,
) error {
document := coredata.Document{ID: documentID}
return s.svc.pg.WithConn(
ctx,
func(conn pg.Conn) error {
return document.Delete(ctx, conn, s.svc.scope)
},
)
}
func (s *DocumentService) ListVersions(
ctx context.Context,
documentID gid.GID,
cursor *page.Cursor[coredata.DocumentVersionOrderField],
) (*page.Page[*coredata.DocumentVersion, coredata.DocumentVersionOrderField], error) {
var documentVersions coredata.DocumentVersions
err := s.svc.pg.WithConn(
ctx,
func(conn pg.Conn) error {
return documentVersions.LoadByDocumentID(ctx, conn, s.svc.scope, documentID, cursor)
},
)
if err != nil {
return nil, err
}
return page.NewPage(documentVersions, cursor), nil
}
func (s *DocumentService) GetVersion(
ctx context.Context,
documentVersionID gid.GID,
) (*coredata.DocumentVersion, error) {
documentVersion := &coredata.DocumentVersion{}
err := s.svc.pg.WithConn(
ctx,
func(conn pg.Conn) error {
return documentVersion.LoadByID(ctx, conn, s.svc.scope, documentVersionID)
},
)
if err != nil {
return nil, err
}
return documentVersion, nil
}
func (s *DocumentService) ListByOrganizationID(
ctx context.Context,
organizationID gid.GID,
cursor *page.Cursor[coredata.DocumentOrderField],
) (*page.Page[*coredata.Document, coredata.DocumentOrderField], error) {
var documents coredata.Documents
err := s.svc.pg.WithConn(
ctx,
func(conn pg.Conn) error {
return documents.LoadByOrganizationID(
ctx,
conn,
s.svc.scope,
organizationID,
cursor,
)
},
)
if err != nil {
return nil, err
}
return page.NewPage(documents, cursor), nil
}
func (s *DocumentService) ListForControlID(
ctx context.Context,
controlID gid.GID,
cursor *page.Cursor[coredata.DocumentOrderField],
) (*page.Page[*coredata.Document, coredata.DocumentOrderField], error) {
var documents coredata.Documents
err := s.svc.pg.WithConn(
ctx,
func(conn pg.Conn) error {
return documents.LoadByControlID(ctx, conn, s.svc.scope, controlID, cursor)
},
)
if err != nil {
return nil, err
}
return page.NewPage(documents, cursor), nil
}
func (s *DocumentService) ListForRiskID(
ctx context.Context,
riskID gid.GID,
cursor *page.Cursor[coredata.DocumentOrderField],
) (*page.Page[*coredata.Document, coredata.DocumentOrderField], error) {
var documents coredata.Documents
err := s.svc.pg.WithConn(
ctx,
func(conn pg.Conn) error {
return documents.LoadByRiskID(ctx, conn, s.svc.scope, riskID, cursor)
},
)
if err != nil {
return nil, err
}
return page.NewPage(documents, cursor), nil
}

View File

@@ -327,36 +327,36 @@ func (s FrameworkService) ExportAudit(
return fmt.Errorf("cannot load measures: %w", err) return fmt.Errorf("cannot load measures: %w", err)
} }
policies := coredata.Policies{} documents := coredata.Documents{}
cursor2 := page.NewCursor( cursor2 := page.NewCursor(
0, 0,
nil, nil,
page.Head, page.Head,
page.OrderBy[coredata.PolicyOrderField]{ page.OrderBy[coredata.DocumentOrderField]{
Field: coredata.PolicyOrderFieldCreatedAt, Field: coredata.DocumentOrderFieldCreatedAt,
Direction: page.OrderDirectionAsc, Direction: page.OrderDirectionAsc,
}, },
) )
if err := policies.LoadByControlID(ctx, conn, s.svc.scope, control.ID, cursor2); err != nil { if err := documents.LoadByControlID(ctx, conn, s.svc.scope, control.ID, cursor2); err != nil {
return fmt.Errorf("cannot load policies: %w", err) return fmt.Errorf("cannot load documents: %w", err)
} }
for _, policy := range policies { for _, document := range documents {
policyDir := filepath.Join(controlDir, policy.Title) documentDir := filepath.Join(controlDir, document.Title)
if err := os.MkdirAll(policyDir, 0755); err != nil { if err := os.MkdirAll(documentDir, 0755); err != nil {
return fmt.Errorf("cannot create policy directory: %w", err) return fmt.Errorf("cannot create document directory: %w", err)
} }
version := coredata.PolicyVersion{} version := coredata.DocumentVersion{}
if err := version.LoadLatestVersion(ctx, conn, s.svc.scope, policy.ID); err != nil { if err := version.LoadLatestVersion(ctx, conn, s.svc.scope, document.ID); err != nil {
return fmt.Errorf("cannot load policy version: %w", err) return fmt.Errorf("cannot load document version: %w", err)
} }
policyFile := filepath.Join(policyDir, "policy.md") documentFile := filepath.Join(documentDir, "document.md")
if err := os.WriteFile(policyFile, []byte(version.Content), 0644); err != nil { if err := os.WriteFile(documentFile, []byte(version.Content), 0644); err != nil {
return fmt.Errorf("cannot write policy file: %w", err) return fmt.Errorf("cannot write document file: %w", err)
} }
} }

View File

@@ -1,634 +0,0 @@
package probo
import (
"context"
"fmt"
"net/url"
"time"
"github.com/getprobo/probo/pkg/coredata"
"github.com/getprobo/probo/pkg/gid"
"github.com/getprobo/probo/pkg/page"
"github.com/getprobo/probo/pkg/statelesstoken"
"github.com/jackc/pgx/v5"
"go.gearno.de/kit/pg"
)
type (
PolicyService struct {
svc *TenantService
}
CreatePolicyRequest struct {
OrganizationID gid.GID
Title string
Content string
OwnerID gid.GID
CreatedBy gid.GID
}
UpdatePolicyVersionRequest struct {
ID gid.GID
Content string
}
RequestSignatureRequest struct {
PolicyVersionID gid.GID
RequestedBy gid.GID
Signatory gid.GID
}
SigningRequestData struct {
OrganizationID gid.GID `json:"organization_id"`
PeopleID gid.GID `json:"people_id"`
}
)
const (
TokenTypeSigningRequest = "signing_request"
)
func (s *PolicyService) Get(
ctx context.Context,
policyID gid.GID,
) (*coredata.Policy, error) {
policy := &coredata.Policy{}
err := s.svc.pg.WithConn(
ctx,
func(conn pg.Conn) error {
return policy.LoadByID(ctx, conn, s.svc.scope, policyID)
},
)
if err != nil {
return nil, err
}
return policy, nil
}
func (s *PolicyService) PublishVersion(
ctx context.Context,
policyID gid.GID,
publishedBy gid.GID,
) (*coredata.Policy, *coredata.PolicyVersion, error) {
policy := &coredata.Policy{}
policyVersion := &coredata.PolicyVersion{}
now := time.Now()
err := s.svc.pg.WithTx(
ctx,
func(tx pg.Conn) error {
if err := policy.LoadByID(ctx, tx, s.svc.scope, policyID); err != nil {
return fmt.Errorf("cannot load policy %q: %w", policyID, err)
}
if err := policyVersion.LoadLatestVersion(ctx, tx, s.svc.scope, policyID); err != nil {
return fmt.Errorf("cannot load current draft: %w", err)
}
if policyVersion.Status != coredata.PolicyStatusDraft {
return fmt.Errorf("cannot publish version")
}
policy.CurrentPublishedVersion = &policyVersion.VersionNumber
policy.UpdatedAt = now
policyVersion.Status = coredata.PolicyStatusPublished
policyVersion.PublishedAt = &now
policyVersion.PublishedBy = &publishedBy
policyVersion.UpdatedAt = now
if err := policy.Update(ctx, tx, s.svc.scope); err != nil {
return fmt.Errorf("cannot update policy: %w", err)
}
if err := policyVersion.Update(ctx, tx, s.svc.scope); err != nil {
return fmt.Errorf("cannot update policy version: %w", err)
}
return nil
},
)
if err != nil {
return nil, nil, err
}
return policy, policyVersion, nil
}
func (s *PolicyService) Create(
ctx context.Context,
req CreatePolicyRequest,
) (*coredata.Policy, *coredata.PolicyVersion, error) {
now := time.Now()
policyID := gid.New(s.svc.scope.GetTenantID(), coredata.PolicyEntityType)
policyVersionID := gid.New(s.svc.scope.GetTenantID(), coredata.PolicyVersionEntityType)
organization := &coredata.Organization{}
people := &coredata.People{}
policy := &coredata.Policy{
ID: policyID,
Title: req.Title,
CreatedAt: now,
UpdatedAt: now,
}
policyVersion := &coredata.PolicyVersion{
ID: policyVersionID,
PolicyID: policyID,
VersionNumber: 1,
Content: req.Content,
Status: coredata.PolicyStatusDraft,
CreatedBy: req.CreatedBy,
CreatedAt: now,
UpdatedAt: now,
}
err := s.svc.pg.WithTx(
ctx,
func(conn pg.Conn) error {
if err := organization.LoadByID(ctx, conn, s.svc.scope, req.OrganizationID); err != nil {
return fmt.Errorf("cannot load organization: %w", err)
}
if err := people.LoadByID(ctx, conn, s.svc.scope, req.OwnerID); err != nil {
return fmt.Errorf("cannot load people: %w", err)
}
policy.OrganizationID = organization.ID
policy.OwnerID = people.ID
if err := policy.Insert(ctx, conn, s.svc.scope); err != nil {
return fmt.Errorf("cannot insert policy: %w", err)
}
if err := policyVersion.Insert(ctx, conn, s.svc.scope); err != nil {
return fmt.Errorf("cannot create policy version: %w", err)
}
return nil
},
)
if err != nil {
return nil, nil, err
}
return policy, policyVersion, nil
}
func (s *PolicyService) ListSigningRequests(
ctx context.Context,
organizationID gid.GID,
peopleID gid.GID,
) ([]map[string]any, error) {
q := `
SELECT
p.title,
pv.content,
pv.id AS policy_version_id
FROM
policies p
INNER JOIN policy_versions pv ON pv.policy_id = p.id
INNER JOIN policy_version_signatures pvs ON pvs.policy_version_id = pv.id
WHERE
p.tenant_id = $1
AND pvs.signed_by = $2
AND pvs.signed_at IS NULL
`
var results []map[string]any
err := s.svc.pg.WithConn(
ctx,
func(conn pg.Conn) error {
rows, err := conn.Query(ctx, q, s.svc.scope.GetTenantID(), peopleID)
if err != nil {
return fmt.Errorf("cannot query policies: %w", err)
}
results, err = pgx.CollectRows(rows, pgx.RowToMap)
if err != nil {
return err
}
return nil
},
)
if err != nil {
return nil, err
}
return results, nil
}
func (s *PolicyService) SendSigningNotifications(
ctx context.Context,
organizationID gid.GID,
) error {
err := s.svc.pg.WithTx(
ctx,
func(tx pg.Conn) error {
var peoples coredata.Peoples
if err := peoples.LoadAwaitingSigning(ctx, tx, s.svc.scope); err != nil {
return fmt.Errorf("cannot load people: %w", err)
}
for _, people := range peoples {
now := time.Now()
emailID := gid.New(s.svc.scope.GetTenantID(), coredata.EmailEntityType)
token, err := statelesstoken.NewToken(
s.svc.tokenSecret,
TokenTypeSigningRequest,
time.Hour*24*7,
SigningRequestData{
OrganizationID: organizationID,
PeopleID: people.ID,
},
)
if err != nil {
return fmt.Errorf("cannot create signing request token: %w", err)
}
signRequestURL := url.URL{
Scheme: "https",
Host: s.svc.hostname,
Path: "/policies/signing-requests",
RawQuery: url.Values{
"token": []string{token},
}.Encode(),
}
email := &coredata.Email{
ID: emailID,
RecipientEmail: people.PrimaryEmailAddress,
RecipientName: people.FullName,
Subject: "Probo - Policies Signing Request",
TextBody: fmt.Sprintf("Hi,\nYou have documents awaiting your signature. Please follow this link to sign them: %s", signRequestURL.String()),
CreatedAt: now,
UpdatedAt: now,
}
if err := email.Insert(ctx, tx); err != nil {
return fmt.Errorf("cannot insert email: %w", err)
}
}
return nil
},
)
if err != nil {
return fmt.Errorf("cannot send signing notifications: %w", err)
}
return nil
}
func (s *PolicyService) SignPolicyVersion(
ctx context.Context,
policyVersionID gid.GID,
signatory gid.GID,
) error {
policyVersion := &coredata.PolicyVersion{}
policyVersionSignature := &coredata.PolicyVersionSignature{}
now := time.Now()
err := s.svc.pg.WithTx(
ctx,
func(conn pg.Conn) error {
if err := policyVersion.LoadByID(ctx, conn, s.svc.scope, policyVersionID); err != nil {
return fmt.Errorf("cannot load policy version %q: %w", policyVersionID, err)
}
if policyVersion.Status != coredata.PolicyStatusPublished {
return fmt.Errorf("cannot sign unpublished version")
}
if err := policyVersionSignature.LoadByPolicyVersionIDAndSignatory(ctx, conn, s.svc.scope, policyVersionID, signatory); err != nil {
return fmt.Errorf("cannot load policy version signature: %w", err)
}
if policyVersionSignature.State == coredata.PolicyVersionSignatureStateSigned {
return fmt.Errorf("policy version already signed")
}
policyVersionSignature.State = coredata.PolicyVersionSignatureStateSigned
policyVersionSignature.SignedAt = &now
policyVersionSignature.UpdatedAt = now
if err := policyVersion.Update(ctx, conn, s.svc.scope); err != nil {
return fmt.Errorf("cannot update policy version: %w", err)
}
if err := policyVersionSignature.Update(ctx, conn, s.svc.scope); err != nil {
return fmt.Errorf("cannot update policy version signature: %w", err)
}
return nil
},
)
if err != nil {
return fmt.Errorf("cannot sign policy version: %w", err)
}
return nil
}
func (s *PolicyService) UpdateVersion(
ctx context.Context,
req UpdatePolicyVersionRequest,
) (*coredata.PolicyVersion, error) {
policyVersion := &coredata.PolicyVersion{}
err := s.svc.pg.WithTx(
ctx,
func(conn pg.Conn) error {
if err := policyVersion.LoadByID(ctx, conn, s.svc.scope, req.ID); err != nil {
return fmt.Errorf("cannot load policy version %q: %w", req.ID, err)
}
if policyVersion.Status != coredata.PolicyStatusDraft {
return fmt.Errorf("cannot update published version")
}
policyVersion.Content = req.Content
policyVersion.UpdatedAt = time.Now()
if err := policyVersion.Update(ctx, conn, s.svc.scope); err != nil {
return fmt.Errorf("cannot update policy version: %w", err)
}
return nil
},
)
if err != nil {
return nil, err
}
return policyVersion, nil
}
func (s *PolicyService) GetVersionSignature(
ctx context.Context,
signatureID gid.GID,
) (*coredata.PolicyVersionSignature, error) {
policyVersionSignature := &coredata.PolicyVersionSignature{}
err := s.svc.pg.WithConn(
ctx,
func(conn pg.Conn) error {
return policyVersionSignature.LoadByID(ctx, conn, s.svc.scope, signatureID)
},
)
if err != nil {
return nil, err
}
return policyVersionSignature, nil
}
func (s *PolicyService) RequestSignature(
ctx context.Context,
req RequestSignatureRequest,
) (*coredata.PolicyVersionSignature, error) {
policyVersionSignatureID := gid.New(s.svc.scope.GetTenantID(), coredata.PolicyVersionSignatureEntityType)
policyVersion, err := s.GetVersion(ctx, req.PolicyVersionID)
if err != nil {
return nil, fmt.Errorf("cannot get policy version: %w", err)
}
if policyVersion.Status != coredata.PolicyStatusPublished {
return nil, fmt.Errorf("cannot request signature for unpublished version")
}
now := time.Now()
policyVersionSignature := &coredata.PolicyVersionSignature{
ID: policyVersionSignatureID,
PolicyVersionID: req.PolicyVersionID,
State: coredata.PolicyVersionSignatureStateRequested,
RequestedBy: req.RequestedBy,
RequestedAt: now,
SignedBy: req.Signatory,
SignedAt: nil,
CreatedAt: now,
UpdatedAt: now,
}
err = s.svc.pg.WithTx(
ctx,
func(conn pg.Conn) error {
if err := policyVersionSignature.Insert(ctx, conn, s.svc.scope); err != nil {
return fmt.Errorf("cannot insert policy version signature: %w", err)
}
return nil
},
)
if err != nil {
return nil, err
}
return policyVersionSignature, nil
}
func (s *PolicyService) ListSignatures(
ctx context.Context,
policyVersionID gid.GID,
cursor *page.Cursor[coredata.PolicyVersionSignatureOrderField],
) (*page.Page[*coredata.PolicyVersionSignature, coredata.PolicyVersionSignatureOrderField], error) {
var policyVersionSignatures coredata.PolicyVersionSignatures
err := s.svc.pg.WithConn(
ctx,
func(conn pg.Conn) error {
return policyVersionSignatures.LoadByPolicyVersionID(ctx, conn, s.svc.scope, policyVersionID, cursor)
},
)
if err != nil {
return nil, err
}
return page.NewPage(policyVersionSignatures, cursor), nil
}
func (s *PolicyService) CreateDraft(
ctx context.Context,
policyID gid.GID,
createdBy gid.GID,
) (*coredata.PolicyVersion, error) {
draftVersionID := gid.New(s.svc.scope.GetTenantID(), coredata.PolicyVersionEntityType)
latestVersion := &coredata.PolicyVersion{}
draftVersion := &coredata.PolicyVersion{}
now := time.Now()
err := s.svc.pg.WithTx(
ctx,
func(conn pg.Conn) error {
if err := latestVersion.LoadLatestVersion(ctx, conn, s.svc.scope, policyID); err != nil {
return fmt.Errorf("cannot load latest version: %w", err)
}
if latestVersion.Status != coredata.PolicyStatusPublished {
return fmt.Errorf("cannot create draft from unpublished version")
}
draftVersion.ID = draftVersionID
draftVersion.PolicyID = policyID
draftVersion.VersionNumber = latestVersion.VersionNumber + 1
draftVersion.Content = latestVersion.Content
draftVersion.Status = coredata.PolicyStatusDraft
draftVersion.CreatedBy = createdBy
draftVersion.CreatedAt = now
draftVersion.UpdatedAt = now
if err := draftVersion.Insert(ctx, conn, s.svc.scope); err != nil {
return fmt.Errorf("cannot create draft: %w", err)
}
return nil
},
)
if err != nil {
return nil, err
}
return draftVersion, nil
}
func (s *PolicyService) Delete(
ctx context.Context,
policyID gid.GID,
) error {
policy := coredata.Policy{ID: policyID}
return s.svc.pg.WithConn(
ctx,
func(conn pg.Conn) error {
return policy.Delete(ctx, conn, s.svc.scope)
},
)
}
func (s *PolicyService) ListVersions(
ctx context.Context,
policyID gid.GID,
cursor *page.Cursor[coredata.PolicyVersionOrderField],
) (*page.Page[*coredata.PolicyVersion, coredata.PolicyVersionOrderField], error) {
var policyVersions coredata.PolicyVersions
err := s.svc.pg.WithConn(
ctx,
func(conn pg.Conn) error {
return policyVersions.LoadByPolicyID(ctx, conn, s.svc.scope, policyID, cursor)
},
)
if err != nil {
return nil, err
}
return page.NewPage(policyVersions, cursor), nil
}
func (s *PolicyService) GetVersion(
ctx context.Context,
policyVersionID gid.GID,
) (*coredata.PolicyVersion, error) {
policyVersion := &coredata.PolicyVersion{}
err := s.svc.pg.WithConn(
ctx,
func(conn pg.Conn) error {
return policyVersion.LoadByID(ctx, conn, s.svc.scope, policyVersionID)
},
)
if err != nil {
return nil, err
}
return policyVersion, nil
}
func (s *PolicyService) ListByOrganizationID(
ctx context.Context,
organizationID gid.GID,
cursor *page.Cursor[coredata.PolicyOrderField],
) (*page.Page[*coredata.Policy, coredata.PolicyOrderField], error) {
var policies coredata.Policies
err := s.svc.pg.WithConn(
ctx,
func(conn pg.Conn) error {
return policies.LoadByOrganizationID(
ctx,
conn,
s.svc.scope,
organizationID,
cursor,
)
},
)
if err != nil {
return nil, err
}
return page.NewPage(policies, cursor), nil
}
func (s *PolicyService) ListForControlID(
ctx context.Context,
controlID gid.GID,
cursor *page.Cursor[coredata.PolicyOrderField],
) (*page.Page[*coredata.Policy, coredata.PolicyOrderField], error) {
var policies coredata.Policies
err := s.svc.pg.WithConn(
ctx,
func(conn pg.Conn) error {
return policies.LoadByControlID(ctx, conn, s.svc.scope, controlID, cursor)
},
)
if err != nil {
return nil, err
}
return page.NewPage(policies, cursor), nil
}
func (s *PolicyService) ListForRiskID(
ctx context.Context,
riskID gid.GID,
cursor *page.Cursor[coredata.PolicyOrderField],
) (*page.Page[*coredata.Policy, coredata.PolicyOrderField], error) {
var policies coredata.Policies
err := s.svc.pg.WithConn(
ctx,
func(conn pg.Conn) error {
return policies.LoadByRiskID(ctx, conn, s.svc.scope, riskID, cursor)
},
)
if err != nil {
return nil, err
}
return page.NewPage(policies, cursor), nil
}

View File

@@ -80,13 +80,13 @@ func (s RiskService) ListForMeasureID(
return page.NewPage(risks, cursor), nil return page.NewPage(risks, cursor), nil
} }
func (s RiskService) CreatePolicyMapping( func (s RiskService) CreateDocumentMapping(
ctx context.Context, ctx context.Context,
riskID gid.GID, riskID gid.GID,
policyID gid.GID, documentID gid.GID,
) (*coredata.Risk, *coredata.Policy, error) { ) (*coredata.Risk, *coredata.Document, error) {
risk := &coredata.Risk{} risk := &coredata.Risk{}
policy := &coredata.Policy{} document := &coredata.Document{}
err := s.svc.pg.WithConn( err := s.svc.pg.WithConn(
ctx, ctx,
@@ -95,36 +95,36 @@ func (s RiskService) CreatePolicyMapping(
return fmt.Errorf("cannot load risk: %w", err) return fmt.Errorf("cannot load risk: %w", err)
} }
if err := policy.LoadByID(ctx, conn, s.svc.scope, policyID); err != nil { if err := document.LoadByID(ctx, conn, s.svc.scope, documentID); err != nil {
return fmt.Errorf("cannot load policy: %w", err) return fmt.Errorf("cannot load document: %w", err)
} }
riskPolicy := &coredata.RiskPolicy{ riskDocument := &coredata.RiskDocument{
RiskID: risk.ID, RiskID: risk.ID,
PolicyID: policy.ID, DocumentID: document.ID,
TenantID: s.svc.scope.GetTenantID(), TenantID: s.svc.scope.GetTenantID(),
CreatedAt: time.Now(), CreatedAt: time.Now(),
} }
return riskPolicy.Insert(ctx, conn, s.svc.scope) return riskDocument.Insert(ctx, conn, s.svc.scope)
}, },
) )
if err != nil { if err != nil {
return nil, nil, fmt.Errorf("cannot create risk policy mapping: %w", err) return nil, nil, fmt.Errorf("cannot create risk document mapping: %w", err)
} }
return risk, policy, nil return risk, document, nil
} }
func (s RiskService) DeletePolicyMapping( func (s RiskService) DeleteDocumentMapping(
ctx context.Context, ctx context.Context,
riskID gid.GID, riskID gid.GID,
policyID gid.GID, documentID gid.GID,
) (*coredata.Risk, *coredata.Policy, error) { ) (*coredata.Risk, *coredata.Document, error) {
riskPolicy := &coredata.RiskPolicy{} riskDocument := &coredata.RiskDocument{}
risk := &coredata.Risk{} risk := &coredata.Risk{}
policy := &coredata.Policy{} document := &coredata.Document{}
err := s.svc.pg.WithConn( err := s.svc.pg.WithConn(
ctx, ctx,
@@ -133,19 +133,19 @@ func (s RiskService) DeletePolicyMapping(
return fmt.Errorf("cannot load risk: %w", err) return fmt.Errorf("cannot load risk: %w", err)
} }
if err := policy.LoadByID(ctx, conn, s.svc.scope, policyID); err != nil { if err := document.LoadByID(ctx, conn, s.svc.scope, documentID); err != nil {
return fmt.Errorf("cannot load policy: %w", err) return fmt.Errorf("cannot load document: %w", err)
} }
return riskPolicy.Delete(ctx, conn, s.svc.scope, risk.ID, policy.ID) return riskDocument.Delete(ctx, conn, s.svc.scope, risk.ID, document.ID)
}, },
) )
if err != nil { if err != nil {
return nil, nil, fmt.Errorf("cannot delete risk policy mapping: %w", err) return nil, nil, fmt.Errorf("cannot delete risk document mapping: %w", err)
} }
return risk, policy, nil return risk, document, nil
} }
func (s RiskService) CreateMeasureMapping( func (s RiskService) CreateMeasureMapping(

View File

@@ -54,7 +54,7 @@ type (
Organizations *OrganizationService Organizations *OrganizationService
Vendors *VendorService Vendors *VendorService
Peoples *PeopleService Peoples *PeopleService
Policies *PolicyService Documents *DocumentService
Controls *ControlService Controls *ControlService
Risks *RiskService Risks *RiskService
VendorComplianceReports *VendorComplianceReportService VendorComplianceReports *VendorComplianceReportService
@@ -118,7 +118,7 @@ func (s *Service) WithTenant(tenantID gid.TenantID) *TenantService {
} }
tenantService.Peoples = &PeopleService{svc: tenantService} tenantService.Peoples = &PeopleService{svc: tenantService}
tenantService.Vendors = &VendorService{svc: tenantService} tenantService.Vendors = &VendorService{svc: tenantService}
tenantService.Policies = &PolicyService{svc: tenantService} tenantService.Documents = &DocumentService{svc: tenantService}
tenantService.Organizations = &OrganizationService{ tenantService.Organizations = &OrganizationService{
svc: tenantService, svc: tenantService,
fileValidator: filevalidation.NewValidator( fileValidator: filevalidation.NewValidator(

View File

@@ -89,7 +89,7 @@ func NewMux(
r := chi.NewMux() r := chi.NewMux()
r.Get( r.Get(
"/policies/signing-requests", "/documents/signing-requests",
func(w http.ResponseWriter, r *http.Request) { func(w http.ResponseWriter, r *http.Request) {
token := r.Header.Get("Authorization") token := r.Header.Get("Authorization")
if token == "" { if token == "" {
@@ -106,7 +106,7 @@ func NewMux(
svc := proboSvc.WithTenant(data.Data.OrganizationID.TenantID()) svc := proboSvc.WithTenant(data.Data.OrganizationID.TenantID())
requests, err := svc.Policies.ListSigningRequests(r.Context(), data.Data.OrganizationID, data.Data.PeopleID) requests, err := svc.Documents.ListSigningRequests(r.Context(), data.Data.OrganizationID, data.Data.PeopleID)
if err != nil { if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
@@ -118,7 +118,7 @@ func NewMux(
) )
r.Post( r.Post(
"/policies/signing-requests/{policy_version_id}/sign", "/documents/signing-requests/{document_version_id}/sign",
func(w http.ResponseWriter, r *http.Request) { func(w http.ResponseWriter, r *http.Request) {
token := r.Header.Get("Authorization") token := r.Header.Get("Authorization")
if token == "" { if token == "" {
@@ -133,15 +133,15 @@ func NewMux(
return return
} }
policyVersionID, err := gid.ParseGID(chi.URLParam(r, "policy_version_id")) documentVersionID, err := gid.ParseGID(chi.URLParam(r, "document_version_id"))
if err != nil { if err != nil {
http.Error(w, "invalid policy version id", http.StatusBadRequest) http.Error(w, "invalid document version id", http.StatusBadRequest)
return return
} }
svc := proboSvc.WithTenant(data.Data.OrganizationID.TenantID()) svc := proboSvc.WithTenant(data.Data.OrganizationID.TenantID())
if err := svc.Policies.SignPolicyVersion(r.Context(), policyVersionID, data.Data.PeopleID); err != nil { if err := svc.Documents.SignDocumentVersion(r.Context(), documentVersionID, data.Data.PeopleID); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
} }

View File

@@ -91,13 +91,13 @@ enum PeopleKind
) )
} }
enum PolicyStatus enum DocumentStatus
@goModel(model: "github.com/getprobo/probo/pkg/coredata.PolicyStatus") { @goModel(model: "github.com/getprobo/probo/pkg/coredata.DocumentStatus") {
DRAFT DRAFT
@goEnum(value: "github.com/getprobo/probo/pkg/coredata.PolicyStatusDraft") @goEnum(value: "github.com/getprobo/probo/pkg/coredata.DocumentStatusDraft")
PUBLISHED PUBLISHED
@goEnum( @goEnum(
value: "github.com/getprobo/probo/pkg/coredata.PolicyStatusPublished" value: "github.com/getprobo/probo/pkg/coredata.DocumentStatusPublished"
) )
} }
@@ -184,15 +184,15 @@ enum TaskOrderField
CREATED_AT CREATED_AT
} }
enum PolicyOrderField enum DocumentOrderField
@goModel(model: "github.com/getprobo/probo/pkg/coredata.PolicyOrderField") { @goModel(model: "github.com/getprobo/probo/pkg/coredata.DocumentOrderField") {
TITLE TITLE
@goEnum( @goEnum(
value: "github.com/getprobo/probo/pkg/coredata.PolicyOrderFieldTitle" value: "github.com/getprobo/probo/pkg/coredata.DocumentOrderFieldTitle"
) )
CREATED_AT CREATED_AT
@goEnum( @goEnum(
value: "github.com/getprobo/probo/pkg/coredata.PolicyOrderFieldCreatedAt" value: "github.com/getprobo/probo/pkg/coredata.DocumentOrderFieldCreatedAt"
) )
} }
@@ -298,17 +298,17 @@ enum BusinessImpact
) )
} }
enum PolicyVersionOrderField enum DocumentVersionOrderField
@goModel( @goModel(
model: "github.com/getprobo/probo/pkg/coredata.PolicyVersionOrderField" model: "github.com/getprobo/probo/pkg/coredata.DocumentVersionOrderField"
) { ) {
VERSION VERSION
@goEnum( @goEnum(
value: "github.com/getprobo/probo/pkg/coredata.PolicyVersionOrderFieldVersion" value: "github.com/getprobo/probo/pkg/coredata.DocumentVersionOrderFieldVersion"
) )
CREATED_AT CREATED_AT
@goEnum( @goEnum(
value: "github.com/getprobo/probo/pkg/coredata.PolicyVersionOrderFieldCreatedAt" value: "github.com/getprobo/probo/pkg/coredata.DocumentVersionOrderFieldCreatedAt"
) )
} }
@@ -394,12 +394,12 @@ input TaskOrder
field: TaskOrderField! field: TaskOrderField!
} }
input PolicyOrder input DocumentOrder
@goModel( @goModel(
model: "github.com/getprobo/probo/pkg/server/api/console/v1/types.PolicyOrderBy" model: "github.com/getprobo/probo/pkg/server/api/console/v1/types.DocumentOrderBy"
) { ) {
direction: OrderDirection! direction: OrderDirection!
field: PolicyOrderField! field: DocumentOrderField!
} }
input RiskOrder input RiskOrder
@@ -436,16 +436,16 @@ input ConnectorOrder {
direction: OrderDirection! direction: OrderDirection!
} }
input PolicyVersionOrder input DocumentVersionOrder
@goModel( @goModel(
model: "github.com/getprobo/probo/pkg/server/api/console/v1/types.PolicyVersionOrderBy" model: "github.com/getprobo/probo/pkg/server/api/console/v1/types.DocumentVersionOrderBy"
) { ) {
direction: OrderDirection! direction: OrderDirection!
field: PolicyVersionOrderField! field: DocumentVersionOrderField!
} }
input PolicyVersionFilter { input DocumentVersionFilter {
status: PolicyStatus status: DocumentStatus
} }
# Core Types # Core Types
@@ -494,13 +494,13 @@ type Organization implements Node {
orderBy: PeopleOrder orderBy: PeopleOrder
): PeopleConnection! @goField(forceResolver: true) ): PeopleConnection! @goField(forceResolver: true)
policies( documents(
first: Int first: Int
after: CursorKey after: CursorKey
last: Int last: Int
before: CursorKey before: CursorKey
orderBy: PolicyOrder orderBy: DocumentOrder
): PolicyConnection! @goField(forceResolver: true) ): DocumentConnection! @goField(forceResolver: true)
measures( measures(
first: Int first: Int
@@ -652,13 +652,13 @@ type Control implements Node {
orderBy: MeasureOrder orderBy: MeasureOrder
): MeasureConnection! @goField(forceResolver: true) ): MeasureConnection! @goField(forceResolver: true)
policies( documents(
first: Int first: Int
after: CursorKey after: CursorKey
last: Int last: Int
before: CursorKey before: CursorKey
orderBy: PolicyOrder orderBy: DocumentOrder
): PolicyConnection! @goField(forceResolver: true) ): DocumentConnection! @goField(forceResolver: true)
createdAt: Datetime! createdAt: Datetime!
updatedAt: Datetime! updatedAt: Datetime!
@@ -748,7 +748,7 @@ type Evidence implements Node {
updatedAt: Datetime! updatedAt: Datetime!
} }
type Policy implements Node { type Document implements Node {
id: ID! id: ID!
title: String! title: String!
description: String! description: String!
@@ -761,9 +761,9 @@ type Policy implements Node {
after: CursorKey after: CursorKey
last: Int last: Int
before: CursorKey before: CursorKey
orderBy: PolicyVersionOrder orderBy: DocumentVersionOrder
filter: PolicyVersionFilter filter: DocumentVersionFilter
): PolicyVersionConnection! @goField(forceResolver: true) ): DocumentVersionConnection! @goField(forceResolver: true)
controls( controls(
first: Int first: Int
@@ -802,13 +802,13 @@ type Risk implements Node {
orderBy: MeasureOrder orderBy: MeasureOrder
): MeasureConnection! @goField(forceResolver: true) ): MeasureConnection! @goField(forceResolver: true)
policies( documents(
first: Int first: Int
after: CursorKey after: CursorKey
last: Int last: Int
before: CursorKey before: CursorKey
orderBy: PolicyOrder orderBy: DocumentOrder
): PolicyConnection! @goField(forceResolver: true) ): DocumentConnection! @goField(forceResolver: true)
controls( controls(
first: Int first: Int
@@ -931,14 +931,14 @@ type EvidenceEdge {
node: Evidence! node: Evidence!
} }
type PolicyConnection { type DocumentConnection {
edges: [PolicyEdge!]! edges: [DocumentEdge!]!
pageInfo: PageInfo! pageInfo: PageInfo!
} }
type PolicyEdge { type DocumentEdge {
cursor: CursorKey! cursor: CursorKey!
node: Policy! node: Document!
} }
type RiskConnection { type RiskConnection {
@@ -981,14 +981,14 @@ type VendorRiskAssessmentEdge {
node: VendorRiskAssessment! node: VendorRiskAssessment!
} }
type PolicyVersionConnection { type DocumentVersionConnection {
edges: [PolicyVersionEdge!]! edges: [DocumentVersionEdge!]!
pageInfo: PageInfo! pageInfo: PageInfo!
} }
type PolicyVersionEdge { type DocumentVersionEdge {
cursor: CursorKey! cursor: CursorKey!
node: PolicyVersion! node: DocumentVersion!
} }
# Root Types # Root Types
@@ -1040,15 +1040,15 @@ type Mutation {
createControlMeasureMapping( createControlMeasureMapping(
input: CreateControlMeasureMappingInput! input: CreateControlMeasureMappingInput!
): CreateControlMeasureMappingPayload! ): CreateControlMeasureMappingPayload!
createControlPolicyMapping( createControlDocumentMapping(
input: CreateControlPolicyMappingInput! input: CreateControlDocumentMappingInput!
): CreateControlPolicyMappingPayload! ): CreateControlDocumentMappingPayload!
deleteControlMeasureMapping( deleteControlMeasureMapping(
input: DeleteControlMeasureMappingInput! input: DeleteControlMeasureMappingInput!
): DeleteControlMeasureMappingPayload! ): DeleteControlMeasureMappingPayload!
deleteControlPolicyMapping( deleteControlDocumentMapping(
input: DeleteControlPolicyMappingInput! input: DeleteControlDocumentMappingInput!
): DeleteControlPolicyMappingPayload! ): DeleteControlDocumentMappingPayload!
# Task mutations # Task mutations
createTask(input: CreateTaskInput!): CreateTaskPayload! createTask(input: CreateTaskInput!): CreateTaskPayload!
@@ -1068,12 +1068,12 @@ type Mutation {
input: DeleteRiskMeasureMappingInput! input: DeleteRiskMeasureMappingInput!
): DeleteRiskMeasureMappingPayload! ): DeleteRiskMeasureMappingPayload!
createRiskPolicyMapping( createRiskDocumentMapping(
input: CreateRiskPolicyMappingInput! input: CreateRiskDocumentMappingInput!
): CreateRiskPolicyMappingPayload! ): CreateRiskDocumentMappingPayload!
deleteRiskPolicyMapping( deleteRiskDocumentMapping(
input: DeleteRiskPolicyMappingInput! input: DeleteRiskDocumentMappingInput!
): DeleteRiskPolicyMappingPayload! ): DeleteRiskDocumentMappingPayload!
# Evidence mutations # Evidence mutations
requestEvidence(input: RequestEvidenceInput!): RequestEvidencePayload! requestEvidence(input: RequestEvidenceInput!): RequestEvidencePayload!
@@ -1094,18 +1094,18 @@ type Mutation {
input: DeleteVendorComplianceReportInput! input: DeleteVendorComplianceReportInput!
): DeleteVendorComplianceReportPayload! ): DeleteVendorComplianceReportPayload!
# Policy mutations # Document mutations
createPolicy(input: CreatePolicyInput!): CreatePolicyPayload! createDocument(input: CreateDocumentInput!): CreateDocumentPayload!
deletePolicy(input: DeletePolicyInput!): DeletePolicyPayload! deleteDocument(input: DeleteDocumentInput!): DeleteDocumentPayload!
publishPolicyVersion( publishDocumentVersion(
input: PublishPolicyVersionInput! input: PublishDocumentVersionInput!
): PublishPolicyVersionPayload! ): PublishDocumentVersionPayload!
createDraftPolicyVersion( createDraftDocumentVersion(
input: CreateDraftPolicyVersionInput! input: CreateDraftDocumentVersionInput!
): CreateDraftPolicyVersionPayload! ): CreateDraftDocumentVersionPayload!
updatePolicyVersion( updateDocumentVersion(
input: UpdatePolicyVersionInput! input: UpdateDocumentVersionInput!
): UpdatePolicyVersionPayload! ): UpdateDocumentVersionPayload!
requestSignature(input: RequestSignatureInput!): RequestSignaturePayload! requestSignature(input: RequestSignatureInput!): RequestSignaturePayload!
sendSigningNotifications( sendSigningNotifications(
input: SendSigningNotificationsInput! input: SendSigningNotificationsInput!
@@ -1285,9 +1285,9 @@ input CreateControlMeasureMappingInput {
measureId: ID! measureId: ID!
} }
input CreateControlPolicyMappingInput { input CreateControlDocumentMappingInput {
controlId: ID! controlId: ID!
policyId: ID! documentId: ID!
} }
input DeleteControlMeasureMappingInput { input DeleteControlMeasureMappingInput {
@@ -1295,9 +1295,9 @@ input DeleteControlMeasureMappingInput {
measureId: ID! measureId: ID!
} }
input DeleteControlPolicyMappingInput { input DeleteControlDocumentMappingInput {
controlId: ID! controlId: ID!
policyId: ID! documentId: ID!
} }
input CreateRiskInput { input CreateRiskInput {
@@ -1342,14 +1342,14 @@ input DeleteRiskMeasureMappingInput {
measureId: ID! measureId: ID!
} }
input CreateRiskPolicyMappingInput { input CreateRiskDocumentMappingInput {
riskId: ID! riskId: ID!
policyId: ID! documentId: ID!
} }
input DeleteRiskPolicyMappingInput { input DeleteRiskDocumentMappingInput {
riskId: ID! riskId: ID!
policyId: ID! documentId: ID!
} }
input RequestEvidenceInput { input RequestEvidenceInput {
@@ -1391,14 +1391,14 @@ input DeleteVendorComplianceReportInput {
reportId: ID! reportId: ID!
} }
input CreatePolicyInput { input CreateDocumentInput {
organizationId: ID! organizationId: ID!
title: String! title: String!
content: String! content: String!
ownerId: ID! ownerId: ID!
} }
input UpdatePolicyInput { input UpdateDocumentInput {
id: ID! id: ID!
title: String title: String
content: String content: String
@@ -1406,8 +1406,8 @@ input UpdatePolicyInput {
createdBy: ID createdBy: ID
} }
input DeletePolicyInput { input DeleteDocumentInput {
policyId: ID! documentId: ID!
} }
input ConfirmEmailInput { input ConfirmEmailInput {
@@ -1515,9 +1515,9 @@ type CreateControlMeasureMappingPayload {
measureEdge: MeasureEdge! measureEdge: MeasureEdge!
} }
type CreateControlPolicyMappingPayload { type CreateControlDocumentMappingPayload {
controlEdge: ControlEdge! controlEdge: ControlEdge!
policyEdge: PolicyEdge! documentEdge: DocumentEdge!
} }
type DeleteControlMeasureMappingPayload { type DeleteControlMeasureMappingPayload {
@@ -1525,9 +1525,9 @@ type DeleteControlMeasureMappingPayload {
deletedMeasureId: ID! deletedMeasureId: ID!
} }
type DeleteControlPolicyMappingPayload { type DeleteControlDocumentMappingPayload {
deletedControlId: ID! deletedControlId: ID!
deletedPolicyId: ID! deletedDocumentId: ID!
} }
type CreateRiskPayload { type CreateRiskPayload {
@@ -1552,14 +1552,14 @@ type DeleteRiskMeasureMappingPayload {
deletedRiskId: ID! deletedRiskId: ID!
} }
type CreateRiskPolicyMappingPayload { type CreateRiskDocumentMappingPayload {
riskEdge: RiskEdge! riskEdge: RiskEdge!
policyEdge: PolicyEdge! documentEdge: DocumentEdge!
} }
type DeleteRiskPolicyMappingPayload { type DeleteRiskDocumentMappingPayload {
deletedRiskId: ID! deletedRiskId: ID!
deletedPolicyId: ID! deletedDocumentId: ID!
} }
type RequestEvidencePayload { type RequestEvidencePayload {
@@ -1586,17 +1586,17 @@ type DeleteVendorComplianceReportPayload {
deletedVendorComplianceReportId: ID! deletedVendorComplianceReportId: ID!
} }
type CreatePolicyPayload { type CreateDocumentPayload {
policyEdge: PolicyEdge! documentEdge: DocumentEdge!
policyVersionEdge: PolicyVersionEdge! documentVersionEdge: DocumentVersionEdge!
} }
type UpdatePolicyPayload { type UpdateDocumentPayload {
policy: Policy! document: Document!
} }
type DeletePolicyPayload { type DeleteDocumentPayload {
deletedPolicyId: ID! deletedDocumentId: ID!
} }
type ConfirmEmailPayload { type ConfirmEmailPayload {
@@ -1668,10 +1668,10 @@ type DeleteMeasurePayload {
deletedMeasureId: ID! deletedMeasureId: ID!
} }
type PolicyVersion implements Node { type DocumentVersion implements Node {
id: ID! id: ID!
policy: Policy! @goField(forceResolver: true) document: Document! @goField(forceResolver: true)
status: PolicyStatus! status: DocumentStatus!
version: Int! version: Int!
content: String! content: String!
changelog: String! changelog: String!
@@ -1681,8 +1681,8 @@ type PolicyVersion implements Node {
after: CursorKey after: CursorKey
last: Int last: Int
before: CursorKey before: CursorKey
orderBy: PolicyVersionSignatureOrder orderBy: DocumentVersionSignatureOrder
): PolicyVersionSignatureConnection! @goField(forceResolver: true) ): DocumentVersionSignatureConnection! @goField(forceResolver: true)
publishedBy: People @goField(forceResolver: true) publishedBy: People @goField(forceResolver: true)
publishedAt: Datetime publishedAt: Datetime
@@ -1690,53 +1690,53 @@ type PolicyVersion implements Node {
updatedAt: Datetime! updatedAt: Datetime!
} }
type PolicyVersionSignatureConnection { type DocumentVersionSignatureConnection {
edges: [PolicyVersionSignatureEdge!]! edges: [DocumentVersionSignatureEdge!]!
pageInfo: PageInfo! pageInfo: PageInfo!
} }
type PolicyVersionSignatureEdge { type DocumentVersionSignatureEdge {
cursor: CursorKey! cursor: CursorKey!
node: PolicyVersionSignature! node: DocumentVersionSignature!
} }
input PolicyVersionSignatureOrder { input DocumentVersionSignatureOrder {
field: PolicyVersionSignatureOrderField! field: DocumentVersionSignatureOrderField!
direction: OrderDirection! direction: OrderDirection!
} }
enum PolicyVersionSignatureState enum DocumentVersionSignatureState
@goModel( @goModel(
model: "github.com/getprobo/probo/pkg/coredata.PolicyVersionSignatureState" model: "github.com/getprobo/probo/pkg/coredata.DocumentVersionSignatureState"
) { ) {
REQUESTED REQUESTED
@goEnum( @goEnum(
value: "github.com/getprobo/probo/pkg/coredata.PolicyVersionSignatureStateRequested" value: "github.com/getprobo/probo/pkg/coredata.DocumentVersionSignatureStateRequested"
) )
SIGNED SIGNED
@goEnum( @goEnum(
value: "github.com/getprobo/probo/pkg/coredata.PolicyVersionSignatureStateSigned" value: "github.com/getprobo/probo/pkg/coredata.DocumentVersionSignatureStateSigned"
) )
} }
enum PolicyVersionSignatureOrderField enum DocumentVersionSignatureOrderField
@goModel( @goModel(
model: "github.com/getprobo/probo/pkg/coredata.PolicyVersionSignatureOrderField" model: "github.com/getprobo/probo/pkg/coredata.DocumentVersionSignatureOrderField"
) { ) {
CREATED_AT CREATED_AT
@goEnum( @goEnum(
value: "github.com/getprobo/probo/pkg/coredata.PolicyVersionSignatureOrderFieldCreatedAt" value: "github.com/getprobo/probo/pkg/coredata.DocumentVersionSignatureOrderFieldCreatedAt"
) )
SIGNED_AT SIGNED_AT
@goEnum( @goEnum(
value: "github.com/getprobo/probo/pkg/coredata.PolicyVersionSignatureOrderFieldSignedAt" value: "github.com/getprobo/probo/pkg/coredata.DocumentVersionSignatureOrderFieldSignedAt"
) )
} }
type PolicyVersionSignature implements Node { type DocumentVersionSignature implements Node {
id: ID! id: ID!
policyVersion: PolicyVersion! @goField(forceResolver: true) documentVersion: DocumentVersion! @goField(forceResolver: true)
state: PolicyVersionSignatureState! state: DocumentVersionSignatureState!
signedBy: People! @goField(forceResolver: true) signedBy: People! @goField(forceResolver: true)
signedAt: Datetime signedAt: Datetime
requestedAt: Datetime! requestedAt: Datetime!
@@ -1746,38 +1746,38 @@ type PolicyVersionSignature implements Node {
} }
input RequestSignatureInput { input RequestSignatureInput {
policyVersionId: ID! documentVersionId: ID!
signatoryId: ID! signatoryId: ID!
} }
type RequestSignaturePayload { type RequestSignaturePayload {
policyVersionSignatureEdge: PolicyVersionSignatureEdge! documentVersionSignatureEdge: DocumentVersionSignatureEdge!
} }
input PublishPolicyVersionInput { input PublishDocumentVersionInput {
policyId: ID! documentId: ID!
} }
type PublishPolicyVersionPayload { type PublishDocumentVersionPayload {
policyVersion: PolicyVersion! documentVersion: DocumentVersion!
policy: Policy! document: Document!
} }
type CreateDraftPolicyVersionPayload { type CreateDraftDocumentVersionPayload {
policyVersionEdge: PolicyVersionEdge! documentVersionEdge: DocumentVersionEdge!
} }
input CreateDraftPolicyVersionInput { input CreateDraftDocumentVersionInput {
policyID: ID! documentID: ID!
} }
input UpdatePolicyVersionInput { input UpdateDocumentVersionInput {
policyVersionId: ID! documentVersionId: ID!
content: String! content: String!
} }
type UpdatePolicyVersionPayload { type UpdateDocumentVersionPayload {
policyVersion: PolicyVersion! documentVersion: DocumentVersion!
} }
input SendSigningNotificationsInput { input SendSigningNotificationsInput {

File diff suppressed because it is too large Load Diff

View File

@@ -20,34 +20,34 @@ import (
) )
type ( type (
PolicyOrderBy OrderBy[coredata.PolicyOrderField] DocumentOrderBy OrderBy[coredata.DocumentOrderField]
) )
func NewPolicyConnection(page *page.Page[*coredata.Policy, coredata.PolicyOrderField]) *PolicyConnection { func NewDocumentConnection(page *page.Page[*coredata.Document, coredata.DocumentOrderField]) *DocumentConnection {
edges := make([]*PolicyEdge, len(page.Data)) edges := make([]*DocumentEdge, len(page.Data))
for i, policy := range page.Data { for i, document := range page.Data {
edges[i] = NewPolicyEdge(policy, page.Cursor.OrderBy.Field) edges[i] = NewDocumentEdge(document, page.Cursor.OrderBy.Field)
} }
return &PolicyConnection{ return &DocumentConnection{
Edges: edges, Edges: edges,
PageInfo: NewPageInfo(page), PageInfo: NewPageInfo(page),
} }
} }
func NewPolicyEdge(policy *coredata.Policy, orderBy coredata.PolicyOrderField) *PolicyEdge { func NewDocumentEdge(document *coredata.Document, orderBy coredata.DocumentOrderField) *DocumentEdge {
return &PolicyEdge{ return &DocumentEdge{
Cursor: policy.CursorKey(orderBy), Cursor: document.CursorKey(orderBy),
Node: NewPolicy(policy), Node: NewDocument(document),
} }
} }
func NewPolicy(policy *coredata.Policy) *Policy { func NewDocument(document *coredata.Document) *Document {
return &Policy{ return &Document{
ID: policy.ID, ID: document.ID,
Title: policy.Title, Title: document.Title,
CurrentPublishedVersion: policy.CurrentPublishedVersion, CurrentPublishedVersion: document.CurrentPublishedVersion,
CreatedAt: policy.CreatedAt, CreatedAt: document.CreatedAt,
UpdatedAt: policy.UpdatedAt, UpdatedAt: document.UpdatedAt,
} }
} }

View File

@@ -0,0 +1,56 @@
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
package types
import (
"github.com/getprobo/probo/pkg/coredata"
"github.com/getprobo/probo/pkg/page"
)
type (
DocumentVersionOrderBy OrderBy[coredata.DocumentVersionOrderField]
)
func NewDocumentVersionConnection(page *page.Page[*coredata.DocumentVersion, coredata.DocumentVersionOrderField]) *DocumentVersionConnection {
edges := make([]*DocumentVersionEdge, len(page.Data))
for i, documentVersion := range page.Data {
edges[i] = NewDocumentVersionEdge(documentVersion, page.Cursor.OrderBy.Field)
}
return &DocumentVersionConnection{
Edges: edges,
PageInfo: NewPageInfo(page),
}
}
func NewDocumentVersionEdge(documentVersion *coredata.DocumentVersion, orderBy coredata.DocumentVersionOrderField) *DocumentVersionEdge {
return &DocumentVersionEdge{
Cursor: documentVersion.CursorKey(orderBy),
Node: NewDocumentVersion(documentVersion),
}
}
func NewDocumentVersion(documentVersion *coredata.DocumentVersion) *DocumentVersion {
return &DocumentVersion{
ID: documentVersion.ID,
Version: documentVersion.VersionNumber,
Content: documentVersion.Content,
Status: documentVersion.Status,
PublishedAt: documentVersion.PublishedAt,
Changelog: documentVersion.Changelog,
CreatedAt: documentVersion.CreatedAt,
UpdatedAt: documentVersion.UpdatedAt,
}
}

View File

@@ -0,0 +1,54 @@
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
package types
import (
"github.com/getprobo/probo/pkg/coredata"
"github.com/getprobo/probo/pkg/page"
)
type (
DocumentVersionSignatureOrderBy OrderBy[coredata.DocumentVersionSignatureOrderField]
)
func NewDocumentVersionSignatureConnection(page *page.Page[*coredata.DocumentVersionSignature, coredata.DocumentVersionSignatureOrderField]) *DocumentVersionSignatureConnection {
edges := make([]*DocumentVersionSignatureEdge, len(page.Data))
for i, documentVersionSignature := range page.Data {
edges[i] = NewDocumentVersionSignatureEdge(documentVersionSignature, page.Cursor.OrderBy.Field)
}
return &DocumentVersionSignatureConnection{
Edges: edges,
PageInfo: NewPageInfo(page),
}
}
func NewDocumentVersionSignatureEdge(documentVersionSignature *coredata.DocumentVersionSignature, orderBy coredata.DocumentVersionSignatureOrderField) *DocumentVersionSignatureEdge {
return &DocumentVersionSignatureEdge{
Cursor: documentVersionSignature.CursorKey(orderBy),
Node: NewDocumentVersionSignature(documentVersionSignature),
}
}
func NewDocumentVersionSignature(documentVersionSignature *coredata.DocumentVersionSignature) *DocumentVersionSignature {
return &DocumentVersionSignature{
ID: documentVersionSignature.ID,
State: documentVersionSignature.State,
SignedAt: documentVersionSignature.SignedAt,
RequestedAt: documentVersionSignature.RequestedAt,
CreatedAt: documentVersionSignature.CreatedAt,
UpdatedAt: documentVersionSignature.UpdatedAt,
}
}

View File

@@ -1,56 +0,0 @@
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
package types
import (
"github.com/getprobo/probo/pkg/coredata"
"github.com/getprobo/probo/pkg/page"
)
type (
PolicyVersionOrderBy OrderBy[coredata.PolicyVersionOrderField]
)
func NewPolicyVersionConnection(page *page.Page[*coredata.PolicyVersion, coredata.PolicyVersionOrderField]) *PolicyVersionConnection {
edges := make([]*PolicyVersionEdge, len(page.Data))
for i, policyVersion := range page.Data {
edges[i] = NewPolicyVersionEdge(policyVersion, page.Cursor.OrderBy.Field)
}
return &PolicyVersionConnection{
Edges: edges,
PageInfo: NewPageInfo(page),
}
}
func NewPolicyVersionEdge(policyVersion *coredata.PolicyVersion, orderBy coredata.PolicyVersionOrderField) *PolicyVersionEdge {
return &PolicyVersionEdge{
Cursor: policyVersion.CursorKey(orderBy),
Node: NewPolicyVersion(policyVersion),
}
}
func NewPolicyVersion(policyVersion *coredata.PolicyVersion) *PolicyVersion {
return &PolicyVersion{
ID: policyVersion.ID,
Version: policyVersion.VersionNumber,
Content: policyVersion.Content,
Status: policyVersion.Status,
PublishedAt: policyVersion.PublishedAt,
Changelog: policyVersion.Changelog,
CreatedAt: policyVersion.CreatedAt,
UpdatedAt: policyVersion.UpdatedAt,
}
}

View File

@@ -1,54 +0,0 @@
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
package types
import (
"github.com/getprobo/probo/pkg/coredata"
"github.com/getprobo/probo/pkg/page"
)
type (
PolicyVersionSignatureOrderBy OrderBy[coredata.PolicyVersionSignatureOrderField]
)
func NewPolicyVersionSignatureConnection(page *page.Page[*coredata.PolicyVersionSignature, coredata.PolicyVersionSignatureOrderField]) *PolicyVersionSignatureConnection {
edges := make([]*PolicyVersionSignatureEdge, len(page.Data))
for i, policyVersionSignature := range page.Data {
edges[i] = NewPolicyVersionSignatureEdge(policyVersionSignature, page.Cursor.OrderBy.Field)
}
return &PolicyVersionSignatureConnection{
Edges: edges,
PageInfo: NewPageInfo(page),
}
}
func NewPolicyVersionSignatureEdge(policyVersionSignature *coredata.PolicyVersionSignature, orderBy coredata.PolicyVersionSignatureOrderField) *PolicyVersionSignatureEdge {
return &PolicyVersionSignatureEdge{
Cursor: policyVersionSignature.CursorKey(orderBy),
Node: NewPolicyVersionSignature(policyVersionSignature),
}
}
func NewPolicyVersionSignature(policyVersionSignature *coredata.PolicyVersionSignature) *PolicyVersionSignature {
return &PolicyVersionSignature{
ID: policyVersionSignature.ID,
State: policyVersionSignature.State,
SignedAt: policyVersionSignature.SignedAt,
RequestedAt: policyVersionSignature.RequestedAt,
CreatedAt: policyVersionSignature.CreatedAt,
UpdatedAt: policyVersionSignature.UpdatedAt,
}
}

View File

@@ -79,7 +79,7 @@ type Control struct {
Description string `json:"description"` Description string `json:"description"`
Framework *Framework `json:"framework"` Framework *Framework `json:"framework"`
Measures *MeasureConnection `json:"measures"` Measures *MeasureConnection `json:"measures"`
Policies *PolicyConnection `json:"policies"` Documents *DocumentConnection `json:"documents"`
CreatedAt time.Time `json:"createdAt"` CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"` UpdatedAt time.Time `json:"updatedAt"`
} }
@@ -107,22 +107,22 @@ type CreateControlMeasureMappingPayload struct {
MeasureEdge *MeasureEdge `json:"measureEdge"` MeasureEdge *MeasureEdge `json:"measureEdge"`
} }
type CreateControlPolicyMappingInput struct { type CreateControlDocumentMappingInput struct {
ControlID gid.GID `json:"controlId"` ControlID gid.GID `json:"controlId"`
PolicyID gid.GID `json:"policyId"` DocumentID gid.GID `json:"documentId"`
} }
type CreateControlPolicyMappingPayload struct { type CreateControlDocumentMappingPayload struct {
ControlEdge *ControlEdge `json:"controlEdge"` ControlEdge *ControlEdge `json:"controlEdge"`
PolicyEdge *PolicyEdge `json:"policyEdge"` DocumentEdge *DocumentEdge `json:"documentEdge"`
} }
type CreateDraftPolicyVersionInput struct { type CreateDraftDocumentVersionInput struct {
PolicyID gid.GID `json:"policyID"` DocumentID gid.GID `json:"documentID"`
} }
type CreateDraftPolicyVersionPayload struct { type CreateDraftDocumentVersionPayload struct {
PolicyVersionEdge *PolicyVersionEdge `json:"policyVersionEdge"` DocumentVersionEdge *DocumentVersionEdge `json:"documentVersionEdge"`
} }
type CreateEvidenceInput struct { type CreateEvidenceInput struct {
@@ -182,16 +182,16 @@ type CreatePeoplePayload struct {
PeopleEdge *PeopleEdge `json:"peopleEdge"` PeopleEdge *PeopleEdge `json:"peopleEdge"`
} }
type CreatePolicyInput struct { type CreateDocumentInput struct {
OrganizationID gid.GID `json:"organizationId"` OrganizationID gid.GID `json:"organizationId"`
Title string `json:"title"` Title string `json:"title"`
Content string `json:"content"` Content string `json:"content"`
OwnerID gid.GID `json:"ownerId"` OwnerID gid.GID `json:"ownerId"`
} }
type CreatePolicyPayload struct { type CreateDocumentPayload struct {
PolicyEdge *PolicyEdge `json:"policyEdge"` DocumentEdge *DocumentEdge `json:"documentEdge"`
PolicyVersionEdge *PolicyVersionEdge `json:"policyVersionEdge"` DocumentVersionEdge *DocumentVersionEdge `json:"documentVersionEdge"`
} }
type CreateRiskInput struct { type CreateRiskInput struct {
@@ -222,14 +222,14 @@ type CreateRiskPayload struct {
RiskEdge *RiskEdge `json:"riskEdge"` RiskEdge *RiskEdge `json:"riskEdge"`
} }
type CreateRiskPolicyMappingInput struct { type CreateRiskDocumentMappingInput struct {
RiskID gid.GID `json:"riskId"` RiskID gid.GID `json:"riskId"`
PolicyID gid.GID `json:"policyId"` DocumentID gid.GID `json:"documentId"`
} }
type CreateRiskPolicyMappingPayload struct { type CreateRiskDocumentMappingPayload struct {
RiskEdge *RiskEdge `json:"riskEdge"` RiskEdge *RiskEdge `json:"riskEdge"`
PolicyEdge *PolicyEdge `json:"policyEdge"` DocumentEdge *DocumentEdge `json:"documentEdge"`
} }
type CreateTaskInput struct { type CreateTaskInput struct {
@@ -294,14 +294,14 @@ type DeleteControlMeasureMappingPayload struct {
DeletedMeasureID gid.GID `json:"deletedMeasureId"` DeletedMeasureID gid.GID `json:"deletedMeasureId"`
} }
type DeleteControlPolicyMappingInput struct { type DeleteControlDocumentMappingInput struct {
ControlID gid.GID `json:"controlId"` ControlID gid.GID `json:"controlId"`
PolicyID gid.GID `json:"policyId"` DocumentID gid.GID `json:"documentId"`
} }
type DeleteControlPolicyMappingPayload struct { type DeleteControlDocumentMappingPayload struct {
DeletedControlID gid.GID `json:"deletedControlId"` DeletedControlID gid.GID `json:"deletedControlId"`
DeletedPolicyID gid.GID `json:"deletedPolicyId"` DeletedDocumentID gid.GID `json:"deletedDocumentId"`
} }
type DeleteEvidenceInput struct { type DeleteEvidenceInput struct {
@@ -344,12 +344,12 @@ type DeletePeoplePayload struct {
DeletedPeopleID gid.GID `json:"deletedPeopleId"` DeletedPeopleID gid.GID `json:"deletedPeopleId"`
} }
type DeletePolicyInput struct { type DeleteDocumentInput struct {
PolicyID gid.GID `json:"policyId"` DocumentID gid.GID `json:"documentId"`
} }
type DeletePolicyPayload struct { type DeleteDocumentPayload struct {
DeletedPolicyID gid.GID `json:"deletedPolicyId"` DeletedDocumentID gid.GID `json:"deletedDocumentId"`
} }
type DeleteRiskInput struct { type DeleteRiskInput struct {
@@ -370,14 +370,14 @@ type DeleteRiskPayload struct {
DeletedRiskID gid.GID `json:"deletedRiskId"` DeletedRiskID gid.GID `json:"deletedRiskId"`
} }
type DeleteRiskPolicyMappingInput struct { type DeleteRiskDocumentMappingInput struct {
RiskID gid.GID `json:"riskId"` RiskID gid.GID `json:"riskId"`
PolicyID gid.GID `json:"policyId"` DocumentID gid.GID `json:"documentId"`
} }
type DeleteRiskPolicyMappingPayload struct { type DeleteRiskDocumentMappingPayload struct {
DeletedRiskID gid.GID `json:"deletedRiskId"` DeletedRiskID gid.GID `json:"deletedRiskId"`
DeletedPolicyID gid.GID `json:"deletedPolicyId"` DeletedDocumentID gid.GID `json:"deletedDocumentId"`
} }
type DeleteTaskInput struct { type DeleteTaskInput struct {
@@ -542,7 +542,7 @@ type Organization struct {
Frameworks *FrameworkConnection `json:"frameworks"` Frameworks *FrameworkConnection `json:"frameworks"`
Vendors *VendorConnection `json:"vendors"` Vendors *VendorConnection `json:"vendors"`
Peoples *PeopleConnection `json:"peoples"` Peoples *PeopleConnection `json:"peoples"`
Policies *PolicyConnection `json:"policies"` Documents *DocumentConnection `json:"documents"`
Measures *MeasureConnection `json:"measures"` Measures *MeasureConnection `json:"measures"`
Risks *RiskConnection `json:"risks"` Risks *RiskConnection `json:"risks"`
Tasks *TaskConnection `json:"tasks"` Tasks *TaskConnection `json:"tasks"`
@@ -601,67 +601,67 @@ type PeopleEdge struct {
Node *People `json:"node"` Node *People `json:"node"`
} }
type Policy struct { type Document struct {
ID gid.GID `json:"id"` ID gid.GID `json:"id"`
Title string `json:"title"` Title string `json:"title"`
Description string `json:"description"` Description string `json:"description"`
CurrentPublishedVersion *int `json:"currentPublishedVersion,omitempty"` CurrentPublishedVersion *int `json:"currentPublishedVersion,omitempty"`
Owner *People `json:"owner"` Owner *People `json:"owner"`
Organization *Organization `json:"organization"` Organization *Organization `json:"organization"`
Versions *PolicyVersionConnection `json:"versions"` Versions *DocumentVersionConnection `json:"versions"`
Controls *ControlConnection `json:"controls"` Controls *ControlConnection `json:"controls"`
CreatedAt time.Time `json:"createdAt"` CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"` UpdatedAt time.Time `json:"updatedAt"`
} }
func (Policy) IsNode() {} func (Document) IsNode() {}
func (this Policy) GetID() gid.GID { return this.ID } func (this Document) GetID() gid.GID { return this.ID }
type PolicyConnection struct { type DocumentConnection struct {
Edges []*PolicyEdge `json:"edges"` Edges []*DocumentEdge `json:"edges"`
PageInfo *PageInfo `json:"pageInfo"` PageInfo *PageInfo `json:"pageInfo"`
} }
type PolicyEdge struct { type DocumentEdge struct {
Cursor page.CursorKey `json:"cursor"` Cursor page.CursorKey `json:"cursor"`
Node *Policy `json:"node"` Node *Document `json:"node"`
} }
type PolicyVersion struct { type DocumentVersion struct {
ID gid.GID `json:"id"` ID gid.GID `json:"id"`
Policy *Policy `json:"policy"` Document *Document `json:"document"`
Status coredata.PolicyStatus `json:"status"` Status coredata.DocumentStatus `json:"status"`
Version int `json:"version"` Version int `json:"version"`
Content string `json:"content"` Content string `json:"content"`
Changelog string `json:"changelog"` Changelog string `json:"changelog"`
Signatures *PolicyVersionSignatureConnection `json:"signatures"` Signatures *DocumentVersionSignatureConnection `json:"signatures"`
PublishedBy *People `json:"publishedBy,omitempty"` PublishedBy *People `json:"publishedBy,omitempty"`
PublishedAt *time.Time `json:"publishedAt,omitempty"` PublishedAt *time.Time `json:"publishedAt,omitempty"`
CreatedAt time.Time `json:"createdAt"` CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"` UpdatedAt time.Time `json:"updatedAt"`
} }
func (PolicyVersion) IsNode() {} func (DocumentVersion) IsNode() {}
func (this PolicyVersion) GetID() gid.GID { return this.ID } func (this DocumentVersion) GetID() gid.GID { return this.ID }
type PolicyVersionConnection struct { type DocumentVersionConnection struct {
Edges []*PolicyVersionEdge `json:"edges"` Edges []*DocumentVersionEdge `json:"edges"`
PageInfo *PageInfo `json:"pageInfo"` PageInfo *PageInfo `json:"pageInfo"`
} }
type PolicyVersionEdge struct { type DocumentVersionEdge struct {
Cursor page.CursorKey `json:"cursor"` Cursor page.CursorKey `json:"cursor"`
Node *PolicyVersion `json:"node"` Node *DocumentVersion `json:"node"`
} }
type PolicyVersionFilter struct { type DocumentVersionFilter struct {
Status *coredata.PolicyStatus `json:"status,omitempty"` Status *coredata.DocumentStatus `json:"status,omitempty"`
} }
type PolicyVersionSignature struct { type DocumentVersionSignature struct {
ID gid.GID `json:"id"` ID gid.GID `json:"id"`
PolicyVersion *PolicyVersion `json:"policyVersion"` DocumentVersion *DocumentVersion `json:"documentVersion"`
State coredata.PolicyVersionSignatureState `json:"state"` State coredata.DocumentVersionSignatureState `json:"state"`
SignedBy *People `json:"signedBy"` SignedBy *People `json:"signedBy"`
SignedAt *time.Time `json:"signedAt,omitempty"` SignedAt *time.Time `json:"signedAt,omitempty"`
RequestedAt time.Time `json:"requestedAt"` RequestedAt time.Time `json:"requestedAt"`
@@ -670,31 +670,31 @@ type PolicyVersionSignature struct {
UpdatedAt time.Time `json:"updatedAt"` UpdatedAt time.Time `json:"updatedAt"`
} }
func (PolicyVersionSignature) IsNode() {} func (DocumentVersionSignature) IsNode() {}
func (this PolicyVersionSignature) GetID() gid.GID { return this.ID } func (this DocumentVersionSignature) GetID() gid.GID { return this.ID }
type PolicyVersionSignatureConnection struct { type DocumentVersionSignatureConnection struct {
Edges []*PolicyVersionSignatureEdge `json:"edges"` Edges []*DocumentVersionSignatureEdge `json:"edges"`
PageInfo *PageInfo `json:"pageInfo"` PageInfo *PageInfo `json:"pageInfo"`
} }
type PolicyVersionSignatureEdge struct { type DocumentVersionSignatureEdge struct {
Cursor page.CursorKey `json:"cursor"` Cursor page.CursorKey `json:"cursor"`
Node *PolicyVersionSignature `json:"node"` Node *DocumentVersionSignature `json:"node"`
} }
type PolicyVersionSignatureOrder struct { type DocumentVersionSignatureOrder struct {
Field coredata.PolicyVersionSignatureOrderField `json:"field"` Field coredata.DocumentVersionSignatureOrderField `json:"field"`
Direction page.OrderDirection `json:"direction"` Direction page.OrderDirection `json:"direction"`
} }
type PublishPolicyVersionInput struct { type PublishDocumentVersionInput struct {
PolicyID gid.GID `json:"policyId"` DocumentID gid.GID `json:"documentId"`
} }
type PublishPolicyVersionPayload struct { type PublishDocumentVersionPayload struct {
PolicyVersion *PolicyVersion `json:"policyVersion"` DocumentVersion *DocumentVersion `json:"documentVersion"`
Policy *Policy `json:"policy"` Document *Document `json:"document"`
} }
type Query struct { type Query struct {
@@ -721,12 +721,12 @@ type RequestEvidencePayload struct {
} }
type RequestSignatureInput struct { type RequestSignatureInput struct {
PolicyVersionID gid.GID `json:"policyVersionId"` DocumentVersionID gid.GID `json:"documentVersionId"`
SignatoryID gid.GID `json:"signatoryId"` SignatoryID gid.GID `json:"signatoryId"`
} }
type RequestSignaturePayload struct { type RequestSignaturePayload struct {
PolicyVersionSignatureEdge *PolicyVersionSignatureEdge `json:"policyVersionSignatureEdge"` DocumentVersionSignatureEdge *DocumentVersionSignatureEdge `json:"documentVersionSignatureEdge"`
} }
type Risk struct { type Risk struct {
@@ -745,7 +745,7 @@ type Risk struct {
Owner *People `json:"owner,omitempty"` Owner *People `json:"owner,omitempty"`
Organization *Organization `json:"organization"` Organization *Organization `json:"organization"`
Measures *MeasureConnection `json:"measures"` Measures *MeasureConnection `json:"measures"`
Policies *PolicyConnection `json:"policies"` Documents *DocumentConnection `json:"documents"`
Controls *ControlConnection `json:"controls"` Controls *ControlConnection `json:"controls"`
CreatedAt time.Time `json:"createdAt"` CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"` UpdatedAt time.Time `json:"updatedAt"`
@@ -859,7 +859,7 @@ type UpdatePeoplePayload struct {
People *People `json:"people"` People *People `json:"people"`
} }
type UpdatePolicyInput struct { type UpdateDocumentInput struct {
ID gid.GID `json:"id"` ID gid.GID `json:"id"`
Title *string `json:"title,omitempty"` Title *string `json:"title,omitempty"`
Content *string `json:"content,omitempty"` Content *string `json:"content,omitempty"`
@@ -867,17 +867,17 @@ type UpdatePolicyInput struct {
CreatedBy *gid.GID `json:"createdBy,omitempty"` CreatedBy *gid.GID `json:"createdBy,omitempty"`
} }
type UpdatePolicyPayload struct { type UpdateDocumentPayload struct {
Policy *Policy `json:"policy"` Document *Document `json:"document"`
} }
type UpdatePolicyVersionInput struct { type UpdateDocumentVersionInput struct {
PolicyVersionID gid.GID `json:"policyVersionId"` DocumentVersionID gid.GID `json:"documentVersionId"`
Content string `json:"content"` Content string `json:"content"`
} }
type UpdatePolicyVersionPayload struct { type UpdateDocumentVersionPayload struct {
PolicyVersion *PolicyVersion `json:"policyVersion"` DocumentVersion *DocumentVersion `json:"documentVersion"`
} }
type UpdateRiskInput struct { type UpdateRiskInput struct {

View File

@@ -62,16 +62,16 @@ func (r *controlResolver) Measures(ctx context.Context, obj *types.Control, firs
return types.NewMeasureConnection(page), nil return types.NewMeasureConnection(page), nil
} }
// Policies is the resolver for the policies field. // Documents is the resolver for the documents field.
func (r *controlResolver) Policies(ctx context.Context, obj *types.Control, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.PolicyOrderBy) (*types.PolicyConnection, error) { func (r *controlResolver) Documents(ctx context.Context, obj *types.Control, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DocumentOrderBy) (*types.DocumentConnection, error) {
svc := GetTenantService(ctx, r.proboSvc, obj.ID.TenantID()) svc := GetTenantService(ctx, r.proboSvc, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.PolicyOrderField]{ pageOrderBy := page.OrderBy[coredata.DocumentOrderField]{
Field: coredata.PolicyOrderFieldCreatedAt, Field: coredata.DocumentOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc, Direction: page.OrderDirectionDesc,
} }
if orderBy != nil { if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.PolicyOrderField]{ pageOrderBy = page.OrderBy[coredata.DocumentOrderField]{
Field: orderBy.Field, Field: orderBy.Field,
Direction: orderBy.Direction, Direction: orderBy.Direction,
} }
@@ -79,12 +79,12 @@ func (r *controlResolver) Policies(ctx context.Context, obj *types.Control, firs
cursor := types.NewCursor(first, after, last, before, pageOrderBy) cursor := types.NewCursor(first, after, last, before, pageOrderBy)
page, err := svc.Policies.ListForControlID(ctx, obj.ID, cursor) page, err := svc.Documents.ListForControlID(ctx, obj.ID, cursor)
if err != nil { if err != nil {
return nil, fmt.Errorf("cannot list policies: %w", err) return nil, fmt.Errorf("cannot list documents: %w", err)
} }
return types.NewPolicyConnection(page), nil return types.NewDocumentConnection(page), nil
} }
// FileURL is the resolver for the fileUrl field. // FileURL is the resolver for the fileUrl field.
@@ -730,18 +730,18 @@ func (r *mutationResolver) CreateControlMeasureMapping(ctx context.Context, inpu
}, nil }, nil
} }
// CreateControlPolicyMapping is the resolver for the createControlPolicyMapping field. // CreateControlDocumentMapping is the resolver for the createControlDocumentMapping field.
func (r *mutationResolver) CreateControlPolicyMapping(ctx context.Context, input types.CreateControlPolicyMappingInput) (*types.CreateControlPolicyMappingPayload, error) { func (r *mutationResolver) CreateControlDocumentMapping(ctx context.Context, input types.CreateControlDocumentMappingInput) (*types.CreateControlDocumentMappingPayload, error) {
svc := GetTenantService(ctx, r.proboSvc, input.PolicyID.TenantID()) svc := GetTenantService(ctx, r.proboSvc, input.DocumentID.TenantID())
control, policy, err := svc.Controls.CreatePolicyMapping(ctx, input.ControlID, input.PolicyID) control, document, err := svc.Controls.CreateDocumentMapping(ctx, input.ControlID, input.DocumentID)
if err != nil { if err != nil {
panic(fmt.Errorf("cannot create control policy mapping: %w", err)) panic(fmt.Errorf("cannot create control document mapping: %w", err))
} }
return &types.CreateControlPolicyMappingPayload{ return &types.CreateControlDocumentMappingPayload{
ControlEdge: types.NewControlEdge(control, coredata.ControlOrderFieldCreatedAt), ControlEdge: types.NewControlEdge(control, coredata.ControlOrderFieldCreatedAt),
PolicyEdge: types.NewPolicyEdge(policy, coredata.PolicyOrderFieldTitle), DocumentEdge: types.NewDocumentEdge(document, coredata.DocumentOrderFieldTitle),
}, nil }, nil
} }
@@ -760,18 +760,18 @@ func (r *mutationResolver) DeleteControlMeasureMapping(ctx context.Context, inpu
}, nil }, nil
} }
// DeleteControlPolicyMapping is the resolver for the deleteControlPolicyMapping field. // DeleteControlDocumentMapping is the resolver for the deleteControlDocumentMapping field.
func (r *mutationResolver) DeleteControlPolicyMapping(ctx context.Context, input types.DeleteControlPolicyMappingInput) (*types.DeleteControlPolicyMappingPayload, error) { func (r *mutationResolver) DeleteControlDocumentMapping(ctx context.Context, input types.DeleteControlDocumentMappingInput) (*types.DeleteControlDocumentMappingPayload, error) {
svc := GetTenantService(ctx, r.proboSvc, input.PolicyID.TenantID()) svc := GetTenantService(ctx, r.proboSvc, input.DocumentID.TenantID())
control, policy, err := svc.Controls.DeletePolicyMapping(ctx, input.ControlID, input.PolicyID) control, document, err := svc.Controls.DeleteDocumentMapping(ctx, input.ControlID, input.DocumentID)
if err != nil { if err != nil {
panic(fmt.Errorf("cannot delete control policy mapping: %w", err)) panic(fmt.Errorf("cannot delete control document mapping: %w", err))
} }
return &types.DeleteControlPolicyMappingPayload{ return &types.DeleteControlDocumentMappingPayload{
DeletedControlID: control.ID, DeletedControlID: control.ID,
DeletedPolicyID: policy.ID, DeletedDocumentID: document.ID,
}, nil }, nil
} }
@@ -959,33 +959,33 @@ func (r *mutationResolver) DeleteRiskMeasureMapping(ctx context.Context, input t
}, nil }, nil
} }
// CreateRiskPolicyMapping is the resolver for the createRiskPolicyMapping field. // CreateRiskDocumentMapping is the resolver for the createRiskDocumentMapping field.
func (r *mutationResolver) CreateRiskPolicyMapping(ctx context.Context, input types.CreateRiskPolicyMappingInput) (*types.CreateRiskPolicyMappingPayload, error) { func (r *mutationResolver) CreateRiskDocumentMapping(ctx context.Context, input types.CreateRiskDocumentMappingInput) (*types.CreateRiskDocumentMappingPayload, error) {
svc := GetTenantService(ctx, r.proboSvc, input.RiskID.TenantID()) svc := GetTenantService(ctx, r.proboSvc, input.RiskID.TenantID())
risk, policy, err := svc.Risks.CreatePolicyMapping(ctx, input.RiskID, input.PolicyID) risk, document, err := svc.Risks.CreateDocumentMapping(ctx, input.RiskID, input.DocumentID)
if err != nil { if err != nil {
panic(fmt.Errorf("cannot create risk policy mapping: %w", err)) panic(fmt.Errorf("cannot create risk document mapping: %w", err))
} }
return &types.CreateRiskPolicyMappingPayload{ return &types.CreateRiskDocumentMappingPayload{
RiskEdge: types.NewRiskEdge(risk, coredata.RiskOrderFieldCreatedAt), RiskEdge: types.NewRiskEdge(risk, coredata.RiskOrderFieldCreatedAt),
PolicyEdge: types.NewPolicyEdge(policy, coredata.PolicyOrderFieldTitle), DocumentEdge: types.NewDocumentEdge(document, coredata.DocumentOrderFieldTitle),
}, nil }, nil
} }
// DeleteRiskPolicyMapping is the resolver for the deleteRiskPolicyMapping field. // DeleteRiskDocumentMapping is the resolver for the deleteRiskDocumentMapping field.
func (r *mutationResolver) DeleteRiskPolicyMapping(ctx context.Context, input types.DeleteRiskPolicyMappingInput) (*types.DeleteRiskPolicyMappingPayload, error) { func (r *mutationResolver) DeleteRiskDocumentMapping(ctx context.Context, input types.DeleteRiskDocumentMappingInput) (*types.DeleteRiskDocumentMappingPayload, error) {
svc := GetTenantService(ctx, r.proboSvc, input.RiskID.TenantID()) svc := GetTenantService(ctx, r.proboSvc, input.RiskID.TenantID())
risk, policy, err := svc.Risks.DeletePolicyMapping(ctx, input.RiskID, input.PolicyID) risk, document, err := svc.Risks.DeleteDocumentMapping(ctx, input.RiskID, input.DocumentID)
if err != nil { if err != nil {
panic(fmt.Errorf("cannot delete risk policy mapping: %w", err)) panic(fmt.Errorf("cannot delete risk document mapping: %w", err))
} }
return &types.DeleteRiskPolicyMappingPayload{ return &types.DeleteRiskDocumentMappingPayload{
DeletedRiskID: risk.ID, DeletedRiskID: risk.ID,
DeletedPolicyID: policy.ID, DeletedDocumentID: document.ID,
}, nil }, nil
} }
@@ -1139,8 +1139,8 @@ func (r *mutationResolver) DeleteVendorComplianceReport(ctx context.Context, inp
}, nil }, nil
} }
// CreatePolicy is the resolver for the createPolicy field. // CreateDocument is the resolver for the createDocument field.
func (r *mutationResolver) CreatePolicy(ctx context.Context, input types.CreatePolicyInput) (*types.CreatePolicyPayload, error) { func (r *mutationResolver) CreateDocument(ctx context.Context, input types.CreateDocumentInput) (*types.CreateDocumentPayload, error) {
svc := GetTenantService(ctx, r.proboSvc, input.OrganizationID.TenantID()) svc := GetTenantService(ctx, r.proboSvc, input.OrganizationID.TenantID())
user := UserFromContext(ctx) user := UserFromContext(ctx)
@@ -1149,9 +1149,9 @@ func (r *mutationResolver) CreatePolicy(ctx context.Context, input types.CreateP
panic(fmt.Errorf("cannot get people: %w", err)) panic(fmt.Errorf("cannot get people: %w", err))
} }
policy, policyVersion, err := svc.Policies.Create( document, documentVersion, err := svc.Documents.Create(
ctx, ctx,
probo.CreatePolicyRequest{ probo.CreateDocumentRequest{
OrganizationID: input.OrganizationID, OrganizationID: input.OrganizationID,
Title: input.Title, Title: input.Title,
OwnerID: input.OwnerID, OwnerID: input.OwnerID,
@@ -1160,32 +1160,32 @@ func (r *mutationResolver) CreatePolicy(ctx context.Context, input types.CreateP
}, },
) )
if err != nil { if err != nil {
panic(fmt.Errorf("cannot create policy: %w", err)) panic(fmt.Errorf("cannot create document: %w", err))
} }
return &types.CreatePolicyPayload{ return &types.CreateDocumentPayload{
PolicyEdge: types.NewPolicyEdge(policy, coredata.PolicyOrderFieldTitle), DocumentEdge: types.NewDocumentEdge(document, coredata.DocumentOrderFieldTitle),
PolicyVersionEdge: types.NewPolicyVersionEdge(policyVersion, coredata.PolicyVersionOrderFieldCreatedAt), DocumentVersionEdge: types.NewDocumentVersionEdge(documentVersion, coredata.DocumentVersionOrderFieldCreatedAt),
}, nil }, nil
} }
// DeletePolicy is the resolver for the deletePolicy field. // DeleteDocument is the resolver for the deleteDocument field.
func (r *mutationResolver) DeletePolicy(ctx context.Context, input types.DeletePolicyInput) (*types.DeletePolicyPayload, error) { func (r *mutationResolver) DeleteDocument(ctx context.Context, input types.DeleteDocumentInput) (*types.DeleteDocumentPayload, error) {
svc := GetTenantService(ctx, r.proboSvc, input.PolicyID.TenantID()) svc := GetTenantService(ctx, r.proboSvc, input.DocumentID.TenantID())
err := svc.Policies.Delete(ctx, input.PolicyID) err := svc.Documents.Delete(ctx, input.DocumentID)
if err != nil { if err != nil {
panic(fmt.Errorf("cannot delete policy: %w", err)) panic(fmt.Errorf("cannot delete document: %w", err))
} }
return &types.DeletePolicyPayload{ return &types.DeleteDocumentPayload{
DeletedPolicyID: input.PolicyID, DeletedDocumentID: input.DocumentID,
}, nil }, nil
} }
// PublishPolicyVersion is the resolver for the publishPolicyVersion field. // PublishDocumentVersion is the resolver for the publishDocumentVersion field.
func (r *mutationResolver) PublishPolicyVersion(ctx context.Context, input types.PublishPolicyVersionInput) (*types.PublishPolicyVersionPayload, error) { func (r *mutationResolver) PublishDocumentVersion(ctx context.Context, input types.PublishDocumentVersionInput) (*types.PublishDocumentVersionPayload, error) {
svc := GetTenantService(ctx, r.proboSvc, input.PolicyID.TenantID()) svc := GetTenantService(ctx, r.proboSvc, input.DocumentID.TenantID())
user := UserFromContext(ctx) user := UserFromContext(ctx)
people, err := svc.Peoples.GetByUserID(ctx, user.ID) people, err := svc.Peoples.GetByUserID(ctx, user.ID)
@@ -1193,20 +1193,20 @@ func (r *mutationResolver) PublishPolicyVersion(ctx context.Context, input types
panic(fmt.Errorf("cannot get people: %w", err)) panic(fmt.Errorf("cannot get people: %w", err))
} }
policy, policyVersion, err := svc.Policies.PublishVersion(ctx, input.PolicyID, people.ID) document, documentVersion, err := svc.Documents.PublishVersion(ctx, input.DocumentID, people.ID)
if err != nil { if err != nil {
panic(fmt.Errorf("cannot publish policy version: %w", err)) panic(fmt.Errorf("cannot publish document version: %w", err))
} }
return &types.PublishPolicyVersionPayload{ return &types.PublishDocumentVersionPayload{
PolicyVersion: types.NewPolicyVersion(policyVersion), DocumentVersion: types.NewDocumentVersion(documentVersion),
Policy: types.NewPolicy(policy), Document: types.NewDocument(document),
}, nil }, nil
} }
// CreateDraftPolicyVersion is the resolver for the createDraftPolicyVersion field. // CreateDraftDocumentVersion is the resolver for the createDraftDocumentVersion field.
func (r *mutationResolver) CreateDraftPolicyVersion(ctx context.Context, input types.CreateDraftPolicyVersionInput) (*types.CreateDraftPolicyVersionPayload, error) { func (r *mutationResolver) CreateDraftDocumentVersion(ctx context.Context, input types.CreateDraftDocumentVersionInput) (*types.CreateDraftDocumentVersionPayload, error) {
svc := GetTenantService(ctx, r.proboSvc, input.PolicyID.TenantID()) svc := GetTenantService(ctx, r.proboSvc, input.DocumentID.TenantID())
user := UserFromContext(ctx) user := UserFromContext(ctx)
people, err := svc.Peoples.GetByUserID(ctx, user.ID) people, err := svc.Peoples.GetByUserID(ctx, user.ID)
@@ -1214,36 +1214,36 @@ func (r *mutationResolver) CreateDraftPolicyVersion(ctx context.Context, input t
panic(fmt.Errorf("cannot get people: %w", err)) panic(fmt.Errorf("cannot get people: %w", err))
} }
policyVersion, err := svc.Policies.CreateDraft(ctx, input.PolicyID, people.ID) documentVersion, err := svc.Documents.CreateDraft(ctx, input.DocumentID, people.ID)
if err != nil { if err != nil {
panic(fmt.Errorf("cannot create draft policy version: %w", err)) panic(fmt.Errorf("cannot create draft document version: %w", err))
} }
return &types.CreateDraftPolicyVersionPayload{ return &types.CreateDraftDocumentVersionPayload{
PolicyVersionEdge: types.NewPolicyVersionEdge(policyVersion, coredata.PolicyVersionOrderFieldCreatedAt), DocumentVersionEdge: types.NewDocumentVersionEdge(documentVersion, coredata.DocumentVersionOrderFieldCreatedAt),
}, nil }, nil
} }
// UpdatePolicyVersion is the resolver for the updatePolicyVersion field. // UpdateDocumentVersion is the resolver for the updateDocumentVersion field.
func (r *mutationResolver) UpdatePolicyVersion(ctx context.Context, input types.UpdatePolicyVersionInput) (*types.UpdatePolicyVersionPayload, error) { func (r *mutationResolver) UpdateDocumentVersion(ctx context.Context, input types.UpdateDocumentVersionInput) (*types.UpdateDocumentVersionPayload, error) {
svc := GetTenantService(ctx, r.proboSvc, input.PolicyVersionID.TenantID()) svc := GetTenantService(ctx, r.proboSvc, input.DocumentVersionID.TenantID())
policyVersion, err := svc.Policies.UpdateVersion(ctx, probo.UpdatePolicyVersionRequest{ documentVersion, err := svc.Documents.UpdateVersion(ctx, probo.UpdateDocumentVersionRequest{
ID: input.PolicyVersionID, ID: input.DocumentVersionID,
Content: input.Content, Content: input.Content,
}) })
if err != nil { if err != nil {
panic(fmt.Errorf("cannot update policy version: %w", err)) panic(fmt.Errorf("cannot update document version: %w", err))
} }
return &types.UpdatePolicyVersionPayload{ return &types.UpdateDocumentVersionPayload{
PolicyVersion: types.NewPolicyVersion(policyVersion), DocumentVersion: types.NewDocumentVersion(documentVersion),
}, nil }, nil
} }
// RequestSignature is the resolver for the requestSignature field. // RequestSignature is the resolver for the requestSignature field.
func (r *mutationResolver) RequestSignature(ctx context.Context, input types.RequestSignatureInput) (*types.RequestSignaturePayload, error) { func (r *mutationResolver) RequestSignature(ctx context.Context, input types.RequestSignatureInput) (*types.RequestSignaturePayload, error) {
svc := GetTenantService(ctx, r.proboSvc, input.PolicyVersionID.TenantID()) svc := GetTenantService(ctx, r.proboSvc, input.DocumentVersionID.TenantID())
user := UserFromContext(ctx) user := UserFromContext(ctx)
@@ -1252,10 +1252,10 @@ func (r *mutationResolver) RequestSignature(ctx context.Context, input types.Req
panic(fmt.Errorf("cannot get people: %w", err)) panic(fmt.Errorf("cannot get people: %w", err))
} }
policyVersionSignature, err := svc.Policies.RequestSignature( documentVersionSignature, err := svc.Documents.RequestSignature(
ctx, ctx,
probo.RequestSignatureRequest{ probo.RequestSignatureRequest{
PolicyVersionID: input.PolicyVersionID, DocumentVersionID: input.DocumentVersionID,
RequestedBy: people.ID, RequestedBy: people.ID,
Signatory: input.SignatoryID, Signatory: input.SignatoryID,
}, },
@@ -1265,7 +1265,7 @@ func (r *mutationResolver) RequestSignature(ctx context.Context, input types.Req
} }
return &types.RequestSignaturePayload{ return &types.RequestSignaturePayload{
PolicyVersionSignatureEdge: types.NewPolicyVersionSignatureEdge(policyVersionSignature, coredata.PolicyVersionSignatureOrderFieldCreatedAt), DocumentVersionSignatureEdge: types.NewDocumentVersionSignatureEdge(documentVersionSignature, coredata.DocumentVersionSignatureOrderFieldCreatedAt),
}, nil }, nil
} }
@@ -1273,7 +1273,7 @@ func (r *mutationResolver) RequestSignature(ctx context.Context, input types.Req
func (r *mutationResolver) SendSigningNotifications(ctx context.Context, input types.SendSigningNotificationsInput) (*types.SendSigningNotificationsPayload, error) { func (r *mutationResolver) SendSigningNotifications(ctx context.Context, input types.SendSigningNotificationsInput) (*types.SendSigningNotificationsPayload, error) {
svc := GetTenantService(ctx, r.proboSvc, input.OrganizationID.TenantID()) svc := GetTenantService(ctx, r.proboSvc, input.OrganizationID.TenantID())
err := svc.Policies.SendSigningNotifications(ctx, input.OrganizationID) err := svc.Documents.SendSigningNotifications(ctx, input.OrganizationID)
if err != nil { if err != nil {
panic(fmt.Errorf("cannot send signing notifications: %w", err)) panic(fmt.Errorf("cannot send signing notifications: %w", err))
} }
@@ -1467,16 +1467,16 @@ func (r *organizationResolver) Peoples(ctx context.Context, obj *types.Organizat
return types.NewPeopleConnection(page), nil return types.NewPeopleConnection(page), nil
} }
// Policies is the resolver for the policies field. // Documents is the resolver for the documents field.
func (r *organizationResolver) Policies(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.PolicyOrderBy) (*types.PolicyConnection, error) { func (r *organizationResolver) Documents(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DocumentOrderBy) (*types.DocumentConnection, error) {
svc := GetTenantService(ctx, r.proboSvc, obj.ID.TenantID()) svc := GetTenantService(ctx, r.proboSvc, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.PolicyOrderField]{ pageOrderBy := page.OrderBy[coredata.DocumentOrderField]{
Field: coredata.PolicyOrderFieldTitle, Field: coredata.DocumentOrderFieldTitle,
Direction: page.OrderDirectionDesc, Direction: page.OrderDirectionDesc,
} }
if orderBy != nil { if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.PolicyOrderField]{ pageOrderBy = page.OrderBy[coredata.DocumentOrderField]{
Field: orderBy.Field, Field: orderBy.Field,
Direction: orderBy.Direction, Direction: orderBy.Direction,
} }
@@ -1484,12 +1484,12 @@ func (r *organizationResolver) Policies(ctx context.Context, obj *types.Organiza
cursor := types.NewCursor(first, after, last, before, pageOrderBy) cursor := types.NewCursor(first, after, last, before, pageOrderBy)
page, err := svc.Policies.ListByOrganizationID(ctx, obj.ID, cursor) page, err := svc.Documents.ListByOrganizationID(ctx, obj.ID, cursor)
if err != nil { if err != nil {
panic(fmt.Errorf("cannot list organization policies: %w", err)) panic(fmt.Errorf("cannot list organization documents: %w", err))
} }
return types.NewPolicyConnection(page), nil return types.NewDocumentConnection(page), nil
} }
// Measures is the resolver for the measures field. // Measures is the resolver for the measures field.
@@ -1568,16 +1568,16 @@ func (r *organizationResolver) Tasks(ctx context.Context, obj *types.Organizatio
} }
// Owner is the resolver for the owner field. // Owner is the resolver for the owner field.
func (r *policyResolver) Owner(ctx context.Context, obj *types.Policy) (*types.People, error) { func (r *documentResolver) Owner(ctx context.Context, obj *types.Document) (*types.People, error) {
svc := GetTenantService(ctx, r.proboSvc, obj.ID.TenantID()) svc := GetTenantService(ctx, r.proboSvc, obj.ID.TenantID())
policy, err := svc.Policies.Get(ctx, obj.ID) document, err := svc.Documents.Get(ctx, obj.ID)
if err != nil { if err != nil {
panic(fmt.Errorf("cannot get policy: %w", err)) panic(fmt.Errorf("cannot get document: %w", err))
} }
// Get the owner // Get the owner
owner, err := svc.Peoples.Get(ctx, policy.OwnerID) owner, err := svc.Peoples.Get(ctx, document.OwnerID)
if err != nil { if err != nil {
panic(fmt.Errorf("cannot get owner: %w", err)) panic(fmt.Errorf("cannot get owner: %w", err))
} }
@@ -1586,15 +1586,15 @@ func (r *policyResolver) Owner(ctx context.Context, obj *types.Policy) (*types.P
} }
// Organization is the resolver for the organization field. // Organization is the resolver for the organization field.
func (r *policyResolver) Organization(ctx context.Context, obj *types.Policy) (*types.Organization, error) { func (r *documentResolver) Organization(ctx context.Context, obj *types.Document) (*types.Organization, error) {
svc := GetTenantService(ctx, r.proboSvc, obj.ID.TenantID()) svc := GetTenantService(ctx, r.proboSvc, obj.ID.TenantID())
policy, err := svc.Policies.Get(ctx, obj.ID) document, err := svc.Documents.Get(ctx, obj.ID)
if err != nil { if err != nil {
panic(fmt.Errorf("cannot get policy: %w", err)) panic(fmt.Errorf("cannot get document: %w", err))
} }
organization, err := svc.Organizations.Get(ctx, policy.OrganizationID) organization, err := svc.Organizations.Get(ctx, document.OrganizationID)
if err != nil { if err != nil {
panic(fmt.Errorf("cannot get organization: %w", err)) panic(fmt.Errorf("cannot get organization: %w", err))
} }
@@ -1603,15 +1603,15 @@ func (r *policyResolver) Organization(ctx context.Context, obj *types.Policy) (*
} }
// Versions is the resolver for the versions field. // Versions is the resolver for the versions field.
func (r *policyResolver) Versions(ctx context.Context, obj *types.Policy, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.PolicyVersionOrderBy, filter *types.PolicyVersionFilter) (*types.PolicyVersionConnection, error) { func (r *documentResolver) Versions(ctx context.Context, obj *types.Document, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DocumentVersionOrderBy, filter *types.DocumentVersionFilter) (*types.DocumentVersionConnection, error) {
svc := GetTenantService(ctx, r.proboSvc, obj.ID.TenantID()) svc := GetTenantService(ctx, r.proboSvc, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.PolicyVersionOrderField]{ pageOrderBy := page.OrderBy[coredata.DocumentVersionOrderField]{
Field: coredata.PolicyVersionOrderFieldCreatedAt, Field: coredata.DocumentVersionOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc, Direction: page.OrderDirectionDesc,
} }
if orderBy != nil { if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.PolicyVersionOrderField]{ pageOrderBy = page.OrderBy[coredata.DocumentVersionOrderField]{
Field: orderBy.Field, Field: orderBy.Field,
Direction: orderBy.Direction, Direction: orderBy.Direction,
} }
@@ -1619,16 +1619,16 @@ func (r *policyResolver) Versions(ctx context.Context, obj *types.Policy, first
cursor := types.NewCursor(first, after, last, before, pageOrderBy) cursor := types.NewCursor(first, after, last, before, pageOrderBy)
page, err := svc.Policies.ListVersions(ctx, obj.ID, cursor) page, err := svc.Documents.ListVersions(ctx, obj.ID, cursor)
if err != nil { if err != nil {
panic(fmt.Errorf("cannot list policy versions: %w", err)) panic(fmt.Errorf("cannot list document versions: %w", err))
} }
return types.NewPolicyVersionConnection(page), nil return types.NewDocumentVersionConnection(page), nil
} }
// Controls is the resolver for the controls field. // Controls is the resolver for the controls field.
func (r *policyResolver) Controls(ctx context.Context, obj *types.Policy, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ControlOrderBy) (*types.ControlConnection, error) { func (r *documentResolver) Controls(ctx context.Context, obj *types.Document, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ControlOrderBy) (*types.ControlConnection, error) {
svc := GetTenantService(ctx, r.proboSvc, obj.ID.TenantID()) svc := GetTenantService(ctx, r.proboSvc, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.ControlOrderField]{ pageOrderBy := page.OrderBy[coredata.ControlOrderField]{
@@ -1644,41 +1644,41 @@ func (r *policyResolver) Controls(ctx context.Context, obj *types.Policy, first
cursor := types.NewCursor(first, after, last, before, pageOrderBy) cursor := types.NewCursor(first, after, last, before, pageOrderBy)
page, err := svc.Controls.ListForPolicyID(ctx, obj.ID, cursor) page, err := svc.Controls.ListForDocumentID(ctx, obj.ID, cursor)
if err != nil { if err != nil {
panic(fmt.Errorf("cannot list policy controls: %w", err)) panic(fmt.Errorf("cannot list document controls: %w", err))
} }
return types.NewControlConnection(page), nil return types.NewControlConnection(page), nil
} }
// Policy is the resolver for the policy field. // Document is the resolver for the document field.
func (r *policyVersionResolver) Policy(ctx context.Context, obj *types.PolicyVersion) (*types.Policy, error) { func (r *documentVersionResolver) Document(ctx context.Context, obj *types.DocumentVersion) (*types.Document, error) {
svc := GetTenantService(ctx, r.proboSvc, obj.ID.TenantID()) svc := GetTenantService(ctx, r.proboSvc, obj.ID.TenantID())
policyVersion, err := svc.Policies.GetVersion(ctx, obj.ID) documentVersion, err := svc.Documents.GetVersion(ctx, obj.ID)
if err != nil { if err != nil {
panic(fmt.Errorf("cannot get policy version: %w", err)) panic(fmt.Errorf("cannot get document version: %w", err))
} }
policy, err := svc.Policies.Get(ctx, policyVersion.PolicyID) document, err := svc.Documents.Get(ctx, documentVersion.DocumentID)
if err != nil { if err != nil {
panic(fmt.Errorf("cannot get policy: %w", err)) panic(fmt.Errorf("cannot get document: %w", err))
} }
return types.NewPolicy(policy), nil return types.NewDocument(document), nil
} }
// Signatures is the resolver for the signatures field. // Signatures is the resolver for the signatures field.
func (r *policyVersionResolver) Signatures(ctx context.Context, obj *types.PolicyVersion, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.PolicyVersionSignatureOrder) (*types.PolicyVersionSignatureConnection, error) { func (r *documentVersionResolver) Signatures(ctx context.Context, obj *types.DocumentVersion, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DocumentVersionSignatureOrder) (*types.DocumentVersionSignatureConnection, error) {
svc := GetTenantService(ctx, r.proboSvc, obj.ID.TenantID()) svc := GetTenantService(ctx, r.proboSvc, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.PolicyVersionSignatureOrderField]{ pageOrderBy := page.OrderBy[coredata.DocumentVersionSignatureOrderField]{
Field: coredata.PolicyVersionSignatureOrderFieldCreatedAt, Field: coredata.DocumentVersionSignatureOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc, Direction: page.OrderDirectionDesc,
} }
if orderBy != nil { if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.PolicyVersionSignatureOrderField]{ pageOrderBy = page.OrderBy[coredata.DocumentVersionSignatureOrderField]{
Field: orderBy.Field, Field: orderBy.Field,
Direction: orderBy.Direction, Direction: orderBy.Direction,
} }
@@ -1686,28 +1686,28 @@ func (r *policyVersionResolver) Signatures(ctx context.Context, obj *types.Polic
cursor := types.NewCursor(first, after, last, before, pageOrderBy) cursor := types.NewCursor(first, after, last, before, pageOrderBy)
page, err := svc.Policies.ListSignatures(ctx, obj.ID, cursor) page, err := svc.Documents.ListSignatures(ctx, obj.ID, cursor)
if err != nil { if err != nil {
panic(fmt.Errorf("cannot list policy version signatures: %w", err)) panic(fmt.Errorf("cannot list document version signatures: %w", err))
} }
return types.NewPolicyVersionSignatureConnection(page), nil return types.NewDocumentVersionSignatureConnection(page), nil
} }
// PublishedBy is the resolver for the publishedBy field. // PublishedBy is the resolver for the publishedBy field.
func (r *policyVersionResolver) PublishedBy(ctx context.Context, obj *types.PolicyVersion) (*types.People, error) { func (r *documentVersionResolver) PublishedBy(ctx context.Context, obj *types.DocumentVersion) (*types.People, error) {
svc := GetTenantService(ctx, r.proboSvc, obj.ID.TenantID()) svc := GetTenantService(ctx, r.proboSvc, obj.ID.TenantID())
policyVersion, err := svc.Policies.GetVersion(ctx, obj.ID) documentVersion, err := svc.Documents.GetVersion(ctx, obj.ID)
if err != nil { if err != nil {
panic(fmt.Errorf("cannot get policy version: %w", err)) panic(fmt.Errorf("cannot get document version: %w", err))
} }
if policyVersion.PublishedBy == nil { if documentVersion.PublishedBy == nil {
return nil, nil return nil, nil
} }
people, err := svc.Peoples.Get(ctx, *policyVersion.PublishedBy) people, err := svc.Peoples.Get(ctx, *documentVersion.PublishedBy)
if err != nil { if err != nil {
panic(fmt.Errorf("cannot get people: %w", err)) panic(fmt.Errorf("cannot get people: %w", err))
} }
@@ -1715,33 +1715,33 @@ func (r *policyVersionResolver) PublishedBy(ctx context.Context, obj *types.Poli
return types.NewPeople(people), nil return types.NewPeople(people), nil
} }
// PolicyVersion is the resolver for the policyVersion field. // DocumentVersion is the resolver for the documentVersion field.
func (r *policyVersionSignatureResolver) PolicyVersion(ctx context.Context, obj *types.PolicyVersionSignature) (*types.PolicyVersion, error) { func (r *documentVersionSignatureResolver) DocumentVersion(ctx context.Context, obj *types.DocumentVersionSignature) (*types.DocumentVersion, error) {
svc := GetTenantService(ctx, r.proboSvc, obj.ID.TenantID()) svc := GetTenantService(ctx, r.proboSvc, obj.ID.TenantID())
policyVersionSignature, err := svc.Policies.GetVersionSignature(ctx, obj.ID) documentVersionSignature, err := svc.Documents.GetVersionSignature(ctx, obj.ID)
if err != nil { if err != nil {
panic(fmt.Errorf("cannot get policy version signature: %w", err)) panic(fmt.Errorf("cannot get document version signature: %w", err))
} }
policyVersion, err := svc.Policies.GetVersion(ctx, policyVersionSignature.PolicyVersionID) documentVersion, err := svc.Documents.GetVersion(ctx, documentVersionSignature.DocumentVersionID)
if err != nil { if err != nil {
panic(fmt.Errorf("cannot get policy version: %w", err)) panic(fmt.Errorf("cannot get document version: %w", err))
} }
return types.NewPolicyVersion(policyVersion), nil return types.NewDocumentVersion(documentVersion), nil
} }
// SignedBy is the resolver for the signedBy field. // SignedBy is the resolver for the signedBy field.
func (r *policyVersionSignatureResolver) SignedBy(ctx context.Context, obj *types.PolicyVersionSignature) (*types.People, error) { func (r *documentVersionSignatureResolver) SignedBy(ctx context.Context, obj *types.DocumentVersionSignature) (*types.People, error) {
svc := GetTenantService(ctx, r.proboSvc, obj.ID.TenantID()) svc := GetTenantService(ctx, r.proboSvc, obj.ID.TenantID())
policyVersionSignature, err := svc.Policies.GetVersionSignature(ctx, obj.ID) documentVersionSignature, err := svc.Documents.GetVersionSignature(ctx, obj.ID)
if err != nil { if err != nil {
panic(fmt.Errorf("cannot get policy version signature: %w", err)) panic(fmt.Errorf("cannot get document version signature: %w", err))
} }
people, err := svc.Peoples.Get(ctx, policyVersionSignature.SignedBy) people, err := svc.Peoples.Get(ctx, documentVersionSignature.SignedBy)
if err != nil { if err != nil {
panic(fmt.Errorf("cannot get people: %w", err)) panic(fmt.Errorf("cannot get people: %w", err))
} }
@@ -1750,15 +1750,15 @@ func (r *policyVersionSignatureResolver) SignedBy(ctx context.Context, obj *type
} }
// RequestedBy is the resolver for the requestedBy field. // RequestedBy is the resolver for the requestedBy field.
func (r *policyVersionSignatureResolver) RequestedBy(ctx context.Context, obj *types.PolicyVersionSignature) (*types.People, error) { func (r *documentVersionSignatureResolver) RequestedBy(ctx context.Context, obj *types.DocumentVersionSignature) (*types.People, error) {
svc := GetTenantService(ctx, r.proboSvc, obj.ID.TenantID()) svc := GetTenantService(ctx, r.proboSvc, obj.ID.TenantID())
policyVersionSignature, err := svc.Policies.GetVersionSignature(ctx, obj.ID) documentVersionSignature, err := svc.Documents.GetVersionSignature(ctx, obj.ID)
if err != nil { if err != nil {
panic(fmt.Errorf("cannot get policy version signature: %w", err)) panic(fmt.Errorf("cannot get document version signature: %w", err))
} }
people, err := svc.Peoples.Get(ctx, policyVersionSignature.RequestedBy) people, err := svc.Peoples.Get(ctx, documentVersionSignature.RequestedBy)
if err != nil { if err != nil {
panic(fmt.Errorf("cannot get people: %w", err)) panic(fmt.Errorf("cannot get people: %w", err))
} }
@@ -1820,12 +1820,12 @@ func (r *queryResolver) Node(ctx context.Context, id gid.GID) (types.Node, error
} }
return types.NewEvidence(evidence), nil return types.NewEvidence(evidence), nil
case coredata.PolicyEntityType: case coredata.DocumentEntityType:
policy, err := svc.Policies.Get(ctx, id) document, err := svc.Documents.Get(ctx, id)
if err != nil { if err != nil {
panic(fmt.Errorf("cannot get policy: %w", err)) panic(fmt.Errorf("cannot get document: %w", err))
} }
return types.NewPolicy(policy), nil return types.NewDocument(document), nil
case coredata.ControlEntityType: case coredata.ControlEntityType:
control, err := svc.Controls.Get(ctx, id) control, err := svc.Controls.Get(ctx, id)
if err != nil { if err != nil {
@@ -1845,18 +1845,18 @@ func (r *queryResolver) Node(ctx context.Context, id gid.GID) (types.Node, error
panic(fmt.Errorf("cannot get vendor compliance report: %w", err)) panic(fmt.Errorf("cannot get vendor compliance report: %w", err))
} }
return types.NewVendorComplianceReport(vendorComplianceReport), nil return types.NewVendorComplianceReport(vendorComplianceReport), nil
case coredata.PolicyVersionEntityType: case coredata.DocumentVersionEntityType:
policyVersion, err := svc.Policies.GetVersion(ctx, id) documentVersion, err := svc.Documents.GetVersion(ctx, id)
if err != nil { if err != nil {
panic(fmt.Errorf("cannot get policy version: %w", err)) panic(fmt.Errorf("cannot get document version: %w", err))
} }
return types.NewPolicyVersion(policyVersion), nil return types.NewDocumentVersion(documentVersion), nil
case coredata.PolicyVersionSignatureEntityType: case coredata.DocumentVersionSignatureEntityType:
policyVersionSignature, err := svc.Policies.GetVersionSignature(ctx, id) documentVersionSignature, err := svc.Documents.GetVersionSignature(ctx, id)
if err != nil { if err != nil {
panic(fmt.Errorf("cannot get policy version signature: %w", err)) panic(fmt.Errorf("cannot get document version signature: %w", err))
} }
return types.NewPolicyVersionSignature(policyVersionSignature), nil return types.NewDocumentVersionSignature(documentVersionSignature), nil
default: default:
} }
@@ -1937,16 +1937,16 @@ func (r *riskResolver) Measures(ctx context.Context, obj *types.Risk, first *int
return types.NewMeasureConnection(page), nil return types.NewMeasureConnection(page), nil
} }
// Policies is the resolver for the policies field. // Documents is the resolver for the documents field.
func (r *riskResolver) Policies(ctx context.Context, obj *types.Risk, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.PolicyOrderBy) (*types.PolicyConnection, error) { func (r *riskResolver) Documents(ctx context.Context, obj *types.Risk, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DocumentOrderBy) (*types.DocumentConnection, error) {
svc := GetTenantService(ctx, r.proboSvc, obj.ID.TenantID()) svc := GetTenantService(ctx, r.proboSvc, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.PolicyOrderField]{ pageOrderBy := page.OrderBy[coredata.DocumentOrderField]{
Field: coredata.PolicyOrderFieldCreatedAt, Field: coredata.DocumentOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc, Direction: page.OrderDirectionDesc,
} }
if orderBy != nil { if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.PolicyOrderField]{ pageOrderBy = page.OrderBy[coredata.DocumentOrderField]{
Field: orderBy.Field, Field: orderBy.Field,
Direction: orderBy.Direction, Direction: orderBy.Direction,
} }
@@ -1954,12 +1954,12 @@ func (r *riskResolver) Policies(ctx context.Context, obj *types.Risk, first *int
cursor := types.NewCursor(first, after, last, before, pageOrderBy) cursor := types.NewCursor(first, after, last, before, pageOrderBy)
page, err := svc.Policies.ListForRiskID(ctx, obj.ID, cursor) page, err := svc.Documents.ListForRiskID(ctx, obj.ID, cursor)
if err != nil { if err != nil {
panic(fmt.Errorf("cannot list risk policies: %w", err)) panic(fmt.Errorf("cannot list risk documents: %w", err))
} }
return types.NewPolicyConnection(page), nil return types.NewDocumentConnection(page), nil
} }
// Controls is the resolver for the controls field. // Controls is the resolver for the controls field.
@@ -2283,15 +2283,17 @@ func (r *Resolver) Mutation() schema.MutationResolver { return &mutationResolver
// Organization returns schema.OrganizationResolver implementation. // Organization returns schema.OrganizationResolver implementation.
func (r *Resolver) Organization() schema.OrganizationResolver { return &organizationResolver{r} } func (r *Resolver) Organization() schema.OrganizationResolver { return &organizationResolver{r} }
// Policy returns schema.PolicyResolver implementation. // Document returns schema.DocumentResolver implementation.
func (r *Resolver) Policy() schema.PolicyResolver { return &policyResolver{r} } func (r *Resolver) Document() schema.DocumentResolver { return &documentResolver{r} }
// PolicyVersion returns schema.PolicyVersionResolver implementation. // DocumentVersion returns schema.DocumentVersionResolver implementation.
func (r *Resolver) PolicyVersion() schema.PolicyVersionResolver { return &policyVersionResolver{r} } func (r *Resolver) DocumentVersion() schema.DocumentVersionResolver {
return &documentVersionResolver{r}
}
// PolicyVersionSignature returns schema.PolicyVersionSignatureResolver implementation. // DocumentVersionSignature returns schema.DocumentVersionSignatureResolver implementation.
func (r *Resolver) PolicyVersionSignature() schema.PolicyVersionSignatureResolver { func (r *Resolver) DocumentVersionSignature() schema.DocumentVersionSignatureResolver {
return &policyVersionSignatureResolver{r} return &documentVersionSignatureResolver{r}
} }
// Query returns schema.QueryResolver implementation. // Query returns schema.QueryResolver implementation.
@@ -2328,9 +2330,9 @@ type frameworkResolver struct{ *Resolver }
type measureResolver struct{ *Resolver } type measureResolver struct{ *Resolver }
type mutationResolver struct{ *Resolver } type mutationResolver struct{ *Resolver }
type organizationResolver struct{ *Resolver } type organizationResolver struct{ *Resolver }
type policyResolver struct{ *Resolver } type documentResolver struct{ *Resolver }
type policyVersionResolver struct{ *Resolver } type documentVersionResolver struct{ *Resolver }
type policyVersionSignatureResolver struct{ *Resolver } type documentVersionSignatureResolver struct{ *Resolver }
type queryResolver struct{ *Resolver } type queryResolver struct{ *Resolver }
type riskResolver struct{ *Resolver } type riskResolver struct{ *Resolver }
type taskResolver struct{ *Resolver } type taskResolver struct{ *Resolver }