Add policies signature history

Signed-off-by: Bryan Frimin <bryan@getprobo.com>
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
Jonathan
2025-05-27 12:32:04 +02:00
committed by Sacha Al Himdani
parent 2e6741942b
commit 61b1a24149
45 changed files with 1154 additions and 946 deletions

View File

@@ -5,7 +5,7 @@
"type": "module",
"scripts": {
"dev": "vite",
"relay": "find src -type d -name \"__generated\" -exec rm -rf {} + && npx relay-compiler",
"relay": "find src -type d -name \"__generated__\" -exec rm -rf {} + && npx relay-compiler ./relay.config.json",
"build": "tsc -b && vite build",
"lint": "eslint .",
"check": "tsc --noEmit -p tsconfig.app.json",

View File

@@ -2,5 +2,6 @@
"src": "./src",
"schema": "../../pkg/server/api/console/v1/schema.graphql",
"language": "typescript",
"eagerEsModules": true
"eagerEsModules": true,
"noFutureProofEnums": true
}

View File

@@ -1,27 +1,8 @@
import { Avatar, Option, Select } from "@probo/ui";
import { Suspense } from "react";
import { useLazyLoadQuery } from "react-relay";
import { graphql } from "relay-runtime";
import type { PeopleSelectQuery as PeopleSelectQueryType } from "./__generated__/PeopleSelectQuery.graphql";
import { useTranslate } from "@probo/i18n";
import { Controller, type Control } from "react-hook-form";
const peopleQuery = graphql`
query PeopleSelectQuery($organizationId: ID!) {
organization: node(id: $organizationId) {
... on Organization {
peoples(first: 100, orderBy: { direction: ASC, field: CREATED_AT }) {
edges {
node {
id
fullName
}
}
}
}
}
}
`;
import { type Control, Controller } from "react-hook-form";
import { usePeople } from "/hooks/graph/PeopleGraph.ts";
export function PeopleSelect({
organization,
@@ -55,11 +36,7 @@ function PeopleSelectWithQuery({
control: Control;
}) {
const { __ } = useTranslate();
const data = useLazyLoadQuery<PeopleSelectQueryType>(peopleQuery, {
organizationId: organization,
});
const people = data.organization?.peoples?.edges.map((edge) => edge.node);
const people = usePeople(organization);
return (
<>

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<391c4db090caa19c60582c18d426764a>>
* @generated SignedSource<<043e8cc5beda1ac8949a7c02adcff4bf>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -9,7 +9,7 @@
// @ts-nocheck
import { ConcreteRequest } from 'relay-runtime';
export type MeasureState = "IMPLEMENTED" | "IN_PROGRESS" | "NOT_APPLICABLE" | "NOT_STARTED" | "%future added value";
export type MeasureState = "IMPLEMENTED" | "IN_PROGRESS" | "NOT_APPLICABLE" | "NOT_STARTED";
export type CreateRiskMeasureMappingInput = {
measureId: string;
riskId: string;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<746421c9f8fc0c80ed1fd5643b3bbae8>>
* @generated SignedSource<<6a9b2c4428ed2255dda81771894c0c6c>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -9,7 +9,7 @@
// @ts-nocheck
import { ConcreteRequest } from 'relay-runtime';
export type MeasureState = "IMPLEMENTED" | "IN_PROGRESS" | "NOT_APPLICABLE" | "NOT_STARTED" | "%future added value";
export type MeasureState = "IMPLEMENTED" | "IN_PROGRESS" | "NOT_APPLICABLE" | "NOT_STARTED";
export type MeasureLinkDialogQuery$variables = {
organizationId: string;
};

View File

@@ -1,76 +0,0 @@
/**
* @generated SignedSource<<3ffcc7618d81b47e39ca5731fe75e2ed>>
* @lightSyntaxTransform
* @nogrep
*/
/* tslint:disable */
/* eslint-disable */
// @ts-nocheck
import { ReaderFragment } from 'relay-runtime';
import { FragmentRefs } from "relay-runtime";
export type usePolicyFormFragment$data = {
readonly description: string;
readonly id: string;
readonly owner: {
readonly id: string;
};
readonly title: string;
readonly " $fragmentType": "usePolicyFormFragment";
};
export type usePolicyFormFragment$key = {
readonly " $data"?: usePolicyFormFragment$data;
readonly " $fragmentSpreads": FragmentRefs<"usePolicyFormFragment">;
};
const node: ReaderFragment = (function(){
var v0 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "id",
"storageKey": null
};
return {
"argumentDefinitions": [],
"kind": "Fragment",
"metadata": null,
"name": "usePolicyFormFragment",
"selections": [
(v0/*: 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,
"concreteType": "People",
"kind": "LinkedField",
"name": "owner",
"plural": false,
"selections": [
(v0/*: any*/)
],
"storageKey": null
}
],
"type": "Policy",
"abstractKey": null
};
})();
(node as any).hash = "619d6845e45fb8c052a8989ea546414d";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<6cf0470d3c2e5d8d9d6ca52bf3375026>>
* @generated SignedSource<<38b7fae585eb2c09409935db8ad3cfe9>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -9,7 +9,7 @@
// @ts-nocheck
import { ReaderFragment } from 'relay-runtime';
export type RiskTreatment = "ACCEPTED" | "AVOIDED" | "MITIGATED" | "TRANSFERRED" | "%future added value";
export type RiskTreatment = "ACCEPTED" | "AVOIDED" | "MITIGATED" | "TRANSFERRED";
import { FragmentRefs } from "relay-runtime";
export type useRiskFormFragment$data = {
readonly category: string;

View File

@@ -0,0 +1,31 @@
import { graphql } from "relay-runtime";
import type { PeopleGraphQuery } from "./__generated__/PeopleGraphQuery.graphql";
import { useLazyLoadQuery } from "react-relay";
import { useMemo } from "react";
const peopleQuery = graphql`
query PeopleGraphQuery($organizationId: ID!) {
organization: node(id: $organizationId) {
... on Organization {
peoples(first: 100, orderBy: { direction: ASC, field: CREATED_AT }) {
edges {
node {
id
fullName
primaryEmailAddress
}
}
}
}
}
}
`;
export function usePeople(organizationId: string) {
const data = useLazyLoadQuery<PeopleGraphQuery>(peopleQuery, {
organizationId: organizationId,
});
return useMemo(() => {
return data.organization?.peoples?.edges.map((edge) => edge.node) ?? [];
}, [data]);
}

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<758e3ece2d7d1d52975886d41b6ae905>>
* @generated SignedSource<<fbc31c6da75cbb26f402b2c88664950a>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -9,24 +9,25 @@
// @ts-nocheck
import { ConcreteRequest } from 'relay-runtime';
export type PeopleSelectQuery$variables = {
export type PeopleGraphQuery$variables = {
organizationId: string;
};
export type PeopleSelectQuery$data = {
export type PeopleGraphQuery$data = {
readonly organization: {
readonly peoples?: {
readonly edges: ReadonlyArray<{
readonly node: {
readonly fullName: string;
readonly id: string;
readonly primaryEmailAddress: string;
};
}>;
};
};
};
export type PeopleSelectQuery = {
response: PeopleSelectQuery$data;
variables: PeopleSelectQuery$variables;
export type PeopleGraphQuery = {
response: PeopleGraphQuery$data;
variables: PeopleGraphQuery$variables;
};
const node: ConcreteRequest = (function(){
@@ -99,6 +100,13 @@ v3 = {
"kind": "ScalarField",
"name": "fullName",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "primaryEmailAddress",
"storageKey": null
}
],
"storageKey": null
@@ -118,7 +126,7 @@ return {
"argumentDefinitions": (v0/*: any*/),
"kind": "Fragment",
"metadata": null,
"name": "PeopleSelectQuery",
"name": "PeopleGraphQuery",
"selections": [
{
"alias": "organization",
@@ -140,7 +148,7 @@ return {
"operation": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Operation",
"name": "PeopleSelectQuery",
"name": "PeopleGraphQuery",
"selections": [
{
"alias": "organization",
@@ -165,16 +173,16 @@ return {
]
},
"params": {
"cacheID": "4e58fc42b352af93ba7067921531af3e",
"cacheID": "cf76244f6aaa0c573bdeb7bf118ad2a3",
"id": null,
"metadata": {},
"name": "PeopleSelectQuery",
"name": "PeopleGraphQuery",
"operationKind": "query",
"text": "query PeopleSelectQuery(\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n ... on Organization {\n peoples(first: 100, orderBy: {direction: ASC, field: CREATED_AT}) {\n edges {\n node {\n id\n fullName\n }\n }\n }\n }\n id\n }\n}\n"
"text": "query PeopleGraphQuery(\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n ... on Organization {\n peoples(first: 100, orderBy: {direction: ASC, field: CREATED_AT}) {\n edges {\n node {\n id\n fullName\n primaryEmailAddress\n }\n }\n }\n }\n id\n }\n}\n"
}
};
})();
(node as any).hash = "77119544e99cf9dd74d8a0f446df108e";
(node as any).hash = "11220f45320400c451abeaf7479a8e47";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<26cd4feab2589e8b641b339c977905a3>>
* @generated SignedSource<<b9027c9c44291af1bebb38760fd96fc8>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -53,20 +53,11 @@ v3 = {
"name": "__typename",
"storageKey": null
},
v4 = {
"kind": "Literal",
"name": "first",
"value": 100
},
v5 = [
(v4/*: any*/),
v4 = [
{
"kind": "Literal",
"name": "orderBy",
"value": {
"direction": "DESC",
"field": "CREATED_AT"
}
"name": "first",
"value": 100
}
];
return {
@@ -118,7 +109,7 @@ return {
"selections": [
{
"alias": null,
"args": (v5/*: any*/),
"args": (v4/*: any*/),
"concreteType": "PolicyConnection",
"kind": "LinkedField",
"name": "policies",
@@ -221,9 +212,7 @@ return {
},
{
"alias": null,
"args": [
(v4/*: any*/)
],
"args": (v4/*: any*/),
"concreteType": "PolicyVersionSignatureConnection",
"kind": "LinkedField",
"name": "signatures",
@@ -306,20 +295,6 @@ return {
"kind": "ScalarField",
"name": "hasNextPage",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "hasPreviousPage",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "startCursor",
"storageKey": null
}
],
"storageKey": null
@@ -337,14 +312,12 @@ return {
]
}
],
"storageKey": "policies(first:100,orderBy:{\"direction\":\"DESC\",\"field\":\"CREATED_AT\"})"
"storageKey": "policies(first:100)"
},
{
"alias": null,
"args": (v5/*: any*/),
"filters": [
"orderBy"
],
"args": (v4/*: any*/),
"filters": null,
"handle": "connection",
"key": "PoliciesPageFragment_policies",
"kind": "LinkedHandle",
@@ -360,12 +333,12 @@ return {
]
},
"params": {
"cacheID": "838223ae76604de3893662f5a496c1d3",
"cacheID": "b0b3546b418ff2cfd5dd7678d3b0be14",
"id": null,
"metadata": {},
"name": "PolicyGraphListQuery",
"operationKind": "query",
"text": "query PolicyGraphListQuery(\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n id\n ...PoliciesPageListFragment\n }\n}\n\nfragment PoliciesPageListFragment on Organization {\n policies(first: 100, orderBy: {direction: DESC, field: CREATED_AT}) {\n edges {\n node {\n id\n ...PoliciesPageRowFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n}\n\nfragment PoliciesPageRowFragment on Policy {\n id\n title\n description\n updatedAt\n owner {\n id\n fullName\n }\n versions(first: 1) {\n edges {\n node {\n id\n status\n signatures(first: 100) {\n edges {\n node {\n id\n state\n }\n }\n }\n }\n }\n }\n}\n"
"text": "query PolicyGraphListQuery(\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n id\n ...PoliciesPageListFragment\n }\n}\n\nfragment PoliciesPageListFragment on Organization {\n policies(first: 100) {\n edges {\n node {\n id\n ...PoliciesPageRowFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n}\n\nfragment PoliciesPageRowFragment on Policy {\n id\n title\n description\n updatedAt\n owner {\n id\n fullName\n }\n versions(first: 1) {\n edges {\n node {\n id\n status\n signatures(first: 100) {\n edges {\n node {\n id\n state\n }\n }\n }\n }\n }\n }\n}\n"
}
};
})();

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<bfeead50dec41ac2f5fac7c6d70f47fb>>
* @generated SignedSource<<b7defae939287f936c1eb687fe2d9bfe>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -65,7 +65,58 @@ v5 = [
"name": "first",
"value": 20
}
];
],
v6 = [
{
"kind": "Literal",
"name": "first",
"value": 100
}
],
v7 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "cursor",
"storageKey": null
},
v8 = {
"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
},
v9 = {
"kind": "ClientExtension",
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "__id",
"storageKey": null
}
]
};
return {
"fragment": {
"argumentDefinitions": (v0/*: any*/),
@@ -201,13 +252,7 @@ return {
},
{
"alias": null,
"args": [
{
"kind": "Literal",
"name": "first",
"value": 100
}
],
"args": (v6/*: any*/),
"concreteType": "PolicyVersionSignatureConnection",
"kind": "LinkedField",
"name": "signatures",
@@ -236,16 +281,63 @@ return {
"kind": "ScalarField",
"name": "state",
"storageKey": null
}
},
{
"alias": null,
"args": null,
"concreteType": "People",
"kind": "LinkedField",
"name": "signedBy",
"plural": false,
"selections": [
(v3/*: any*/),
(v4/*: any*/),
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "primaryEmailAddress",
"storageKey": null
}
],
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "signedAt",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "requestedAt",
"storageKey": null
},
(v2/*: any*/)
],
"storageKey": null
}
},
(v7/*: any*/)
],
"storageKey": null
}
},
(v8/*: any*/),
(v9/*: any*/)
],
"storageKey": "signatures(first:100)"
},
{
"alias": null,
"args": (v6/*: any*/),
"filters": null,
"handle": "connection",
"key": "PolicyPage_signatures",
"kind": "LinkedHandle",
"name": "signatures"
},
{
"alias": null,
"args": null,
@@ -270,53 +362,12 @@ return {
],
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "cursor",
"storageKey": null
}
(v7/*: any*/)
],
"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
},
{
"kind": "ClientExtension",
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "__id",
"storageKey": null
}
]
}
(v8/*: any*/),
(v9/*: any*/)
],
"storageKey": "versions(first:20)"
},
@@ -339,12 +390,12 @@ return {
]
},
"params": {
"cacheID": "e3a62b161b9fce47237c98f90a5d6d2e",
"cacheID": "e9c0e78ebbf62684edbfa11ac1ee5d25",
"id": null,
"metadata": {},
"name": "PolicyGraphNodeQuery",
"operationKind": "query",
"text": "query PolicyGraphNodeQuery(\n $policyId: ID!\n) {\n node(id: $policyId) {\n __typename\n ... on Policy {\n ...PolicyPagePolicyFragment\n }\n id\n }\n}\n\nfragment PolicyPagePolicyFragment on Policy {\n id\n title\n owner {\n id\n fullName\n }\n versions(first: 20) {\n edges {\n node {\n id\n content\n status\n publishedAt\n version\n updatedAt\n signatures(first: 100) {\n edges {\n node {\n id\n state\n }\n }\n }\n ...PolicyVersionHistoryDialogFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n}\n\nfragment PolicyVersionHistoryDialogFragment on PolicyVersion {\n id\n version\n status\n content\n changelog\n publishedAt\n updatedAt\n publishedBy {\n fullName\n id\n }\n}\n"
"text": "query PolicyGraphNodeQuery(\n $policyId: ID!\n) {\n node(id: $policyId) {\n __typename\n ... on Policy {\n ...PolicyPagePolicyFragment\n }\n id\n }\n}\n\nfragment PolicyPagePolicyFragment on Policy {\n id\n title\n owner {\n id\n fullName\n }\n versions(first: 20) {\n edges {\n node {\n id\n content\n status\n publishedAt\n version\n updatedAt\n signatures(first: 100) {\n edges {\n node {\n id\n state\n signedBy {\n id\n }\n ...PolicySignaturesDialog_signature\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n ...PolicyVersionHistoryDialogFragment\n ...PolicySignaturesDialog_version\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n}\n\nfragment PolicySignaturesDialog_signature on PolicyVersionSignature {\n id\n state\n signedAt\n requestedAt\n signedBy {\n fullName\n primaryEmailAddress\n id\n }\n}\n\nfragment PolicySignaturesDialog_version on PolicyVersion {\n version\n status\n publishedAt\n updatedAt\n}\n\nfragment PolicyVersionHistoryDialogFragment on PolicyVersion {\n id\n version\n status\n content\n changelog\n publishedAt\n updatedAt\n publishedBy {\n fullName\n id\n }\n}\n"
}
};
})();

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<352ca1fa13e246dd48eb0cd346a251ef>>
* @generated SignedSource<<d65dc38bcf11079a304f8a5cc4070389>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -9,7 +9,7 @@
// @ts-nocheck
import { ReaderFragment } from 'relay-runtime';
export type RiskTreatment = "ACCEPTED" | "AVOIDED" | "MITIGATED" | "TRANSFERRED" | "%future added value";
export type RiskTreatment = "ACCEPTED" | "AVOIDED" | "MITIGATED" | "TRANSFERRED";
import { FragmentRefs } from "relay-runtime";
export type RiskGraphFragment$data = {
readonly id: string;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<3485aabb6e5e1992e2f0c089deaf4b2d>>
* @generated SignedSource<<18341e1d2a7f480ad73ef32506121c5e>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -10,7 +10,7 @@
import { ConcreteRequest } from 'relay-runtime';
import { FragmentRefs } from "relay-runtime";
export type RiskTreatment = "ACCEPTED" | "AVOIDED" | "MITIGATED" | "TRANSFERRED" | "%future added value";
export type RiskTreatment = "ACCEPTED" | "AVOIDED" | "MITIGATED" | "TRANSFERRED";
export type RiskGraphNodeQuery$variables = {
riskId: string;
};

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<5cce23056dd540654c65719414023e64>>
* @generated SignedSource<<7c5151b921734cd14b58af145eba7267>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -10,8 +10,8 @@
import { ConcreteRequest } from 'relay-runtime';
import { FragmentRefs } from "relay-runtime";
export type OrderDirection = "ASC" | "DESC" | "%future added value";
export type RiskOrderField = "CATEGORY" | "CREATED_AT" | "INITIAL_RISK_SCORE" | "NAME" | "RESIDUAL_RISK_SCORE" | "TREATMENT" | "UPDATED_AT" | "%future added value";
export type OrderDirection = "ASC" | "DESC";
export type RiskOrderField = "CATEGORY" | "CREATED_AT" | "INITIAL_RISK_SCORE" | "NAME" | "RESIDUAL_RISK_SCORE" | "TREATMENT" | "UPDATED_AT";
export type RiskOrder = {
direction: OrderDirection;
field: RiskOrderField;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<a35e945926fc7614549d452b1edd92f9>>
* @generated SignedSource<<d474691920e943cf5df04fa93c746b28>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -9,7 +9,7 @@
// @ts-nocheck
import { ReaderFragment } from 'relay-runtime';
export type MeasureState = "IMPLEMENTED" | "IN_PROGRESS" | "NOT_APPLICABLE" | "NOT_STARTED" | "%future added value";
export type MeasureState = "IMPLEMENTED" | "IN_PROGRESS" | "NOT_APPLICABLE" | "NOT_STARTED";
import { FragmentRefs } from "relay-runtime";
export type MeasuresPageFragment$data = {
readonly measures: {

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<5a6e0e680ef636cf776a56f490733aee>>
* @generated SignedSource<<c0e424b8b0ec7becf9ac2930c6e81b56>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -9,7 +9,7 @@
// @ts-nocheck
import { ConcreteRequest } from 'relay-runtime';
export type MeasureState = "IMPLEMENTED" | "IN_PROGRESS" | "NOT_APPLICABLE" | "NOT_STARTED" | "%future added value";
export type MeasureState = "IMPLEMENTED" | "IN_PROGRESS" | "NOT_APPLICABLE" | "NOT_STARTED";
export type ImportMeasureInput = {
file: any;
organizationId: string;

View File

@@ -33,13 +33,7 @@ import type { PoliciesPageRowFragment$key } from "./__generated__/PoliciesPageRo
const policiesFragment = graphql`
fragment PoliciesPageListFragment on Organization {
policies(
first: 100
after: null
last: null
before: null
orderBy: { direction: DESC, field: CREATED_AT }
) @connection(key: "PoliciesPageFragment_policies") {
policies(first: 100) @connection(key: "PoliciesPageFragment_policies") {
__id
edges {
node {

View File

@@ -31,6 +31,7 @@ import {
IconPencil,
useConfirmDialogRef,
IconClock,
IconSignature,
} from "@probo/ui";
import { useOrganizationId } from "/hooks/useOrganizationId";
import { Button } from "@probo/ui";
@@ -40,6 +41,7 @@ import { useNavigate } from "react-router";
import UpdateVersionDialog from "./dialogs/UpdateVersionDialog";
import { useRef } from "react";
import { PolicyVersionHistoryDialog } from "./dialogs/PolicyVersionHistoryDialog";
import { PolicySignaturesDialog } from "./dialogs/PolicySignaturesDialog";
type Props = {
queryRef: PreloadedQuery<PolicyGraphNodeQuery>;
@@ -63,15 +65,21 @@ const policyFragment = graphql`
publishedAt
version
updatedAt
signatures(first: 100) {
signatures(first: 100) @connection(key: "PolicyPage_signatures") {
__id
edges {
node {
id
state
signedBy {
id
}
...PolicySignaturesDialog_signature
}
}
}
...PolicyVersionHistoryDialogFragment
...PolicySignaturesDialog_version
}
}
}
@@ -108,7 +116,6 @@ export default function PolicyPage(props: Props) {
);
const [deletePolicy, isDeleting] = useDeletePolicyMutation();
const versionConnectionId = policy.versions.__id;
const versions = policy.versions.edges.map((edge) => edge.node);
usePageTitle(policy.title);
@@ -197,6 +204,11 @@ export default function PolicyPage(props: Props) {
{__("Version history")}
</Button>
</PolicyVersionHistoryDialog>
<PolicySignaturesDialog policy={policy}>
<Button icon={IconSignature} variant="secondary">
{__("Signatures history")}
</Button>
</PolicySignaturesDialog>
<ActionDropdown variant="secondary">
<DropdownItem

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<cd6428905d88d31ab94cb3cbcd9fcd2c>>
* @generated SignedSource<<89063899241b0557e2a6df4ff74ecea1>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -35,7 +35,7 @@ const node: ReaderFragment = {
{
"count": null,
"cursor": null,
"direction": "bidirectional",
"direction": "forward",
"path": [
"policies"
]
@@ -46,16 +46,7 @@ const node: ReaderFragment = {
"selections": [
{
"alias": "policies",
"args": [
{
"kind": "Literal",
"name": "orderBy",
"value": {
"direction": "DESC",
"field": "CREATED_AT"
}
}
],
"args": null,
"concreteType": "PolicyConnection",
"kind": "LinkedField",
"name": "__PoliciesPageFragment_policies_connection",
@@ -130,20 +121,6 @@ const node: ReaderFragment = {
"kind": "ScalarField",
"name": "hasNextPage",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "hasPreviousPage",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "startCursor",
"storageKey": null
}
],
"storageKey": null
@@ -161,13 +138,13 @@ const node: ReaderFragment = {
]
}
],
"storageKey": "__PoliciesPageFragment_policies_connection(orderBy:{\"direction\":\"DESC\",\"field\":\"CREATED_AT\"})"
"storageKey": null
}
],
"type": "Organization",
"abstractKey": null
};
(node as any).hash = "2f34601ba53a0900494a1bb0d8be1773";
(node as any).hash = "1c1fa3340a1fe9de3995ffcb374c9124";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<76980bd62a1a415efbb27298d27874da>>
* @generated SignedSource<<3d1854151a950f0b4b85faf16c995c61>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -9,8 +9,8 @@
// @ts-nocheck
import { ReaderFragment } from 'relay-runtime';
export type PolicyStatus = "DRAFT" | "PUBLISHED" | "%future added value";
export type PolicyVersionSignatureState = "REQUESTED" | "SIGNED" | "%future added value";
export type PolicyStatus = "DRAFT" | "PUBLISHED";
export type PolicyVersionSignatureState = "REQUESTED" | "SIGNED";
import { FragmentRefs } from "relay-runtime";
export type PoliciesPageRowFragment$data = {
readonly description: string;

View File

@@ -1,135 +0,0 @@
/**
* @generated SignedSource<<0c65ab6f2531f65b9687e3ca13074774>>
* @lightSyntaxTransform
* @nogrep
*/
/* tslint:disable */
/* eslint-disable */
// @ts-nocheck
import { ConcreteRequest } from 'relay-runtime';
export type PolicyStatus = "DRAFT" | "PUBLISHED" | "%future added value";
export type CreateDraftPolicyVersionInput = {
policyID: string;
};
export type PolicyPageCreateDraftPolicyVersionMutation$variables = {
input: CreateDraftPolicyVersionInput;
};
export type PolicyPageCreateDraftPolicyVersionMutation$data = {
readonly createDraftPolicyVersion: {
readonly policyVersionEdge: {
readonly node: {
readonly id: string;
readonly status: PolicyStatus;
readonly version: number;
};
};
};
};
export type PolicyPageCreateDraftPolicyVersionMutation = {
response: PolicyPageCreateDraftPolicyVersionMutation$data;
variables: PolicyPageCreateDraftPolicyVersionMutation$variables;
};
const node: ConcreteRequest = (function(){
var v0 = [
{
"defaultValue": null,
"kind": "LocalArgument",
"name": "input"
}
],
v1 = [
{
"alias": null,
"args": [
{
"kind": "Variable",
"name": "input",
"variableName": "input"
}
],
"concreteType": "CreateDraftPolicyVersionPayload",
"kind": "LinkedField",
"name": "createDraftPolicyVersion",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"concreteType": "PolicyVersionEdge",
"kind": "LinkedField",
"name": "policyVersionEdge",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"concreteType": "PolicyVersion",
"kind": "LinkedField",
"name": "node",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "id",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "version",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "status",
"storageKey": null
}
],
"storageKey": null
}
],
"storageKey": null
}
],
"storageKey": null
}
];
return {
"fragment": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Fragment",
"metadata": null,
"name": "PolicyPageCreateDraftPolicyVersionMutation",
"selections": (v1/*: any*/),
"type": "Mutation",
"abstractKey": null
},
"kind": "Request",
"operation": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Operation",
"name": "PolicyPageCreateDraftPolicyVersionMutation",
"selections": (v1/*: any*/)
},
"params": {
"cacheID": "197f53d67c5393a8163be2a8ce356cd0",
"id": null,
"metadata": {},
"name": "PolicyPageCreateDraftPolicyVersionMutation",
"operationKind": "mutation",
"text": "mutation PolicyPageCreateDraftPolicyVersionMutation(\n $input: CreateDraftPolicyVersionInput!\n) {\n createDraftPolicyVersion(input: $input) {\n policyVersionEdge {\n node {\n id\n version\n status\n }\n }\n }\n}\n"
}
};
})();
(node as any).hash = "7fcf72158c1dc58ae8f9d7efaa6d93a9";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<769555856fa8bff973c4685249abbb2f>>
* @generated SignedSource<<088b04713ff854ffccb30532513bb093>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -9,8 +9,8 @@
// @ts-nocheck
import { ReaderFragment } from 'relay-runtime';
export type PolicyStatus = "DRAFT" | "PUBLISHED" | "%future added value";
export type PolicyVersionSignatureState = "REQUESTED" | "SIGNED" | "%future added value";
export type PolicyStatus = "DRAFT" | "PUBLISHED";
export type PolicyVersionSignatureState = "REQUESTED" | "SIGNED";
import { FragmentRefs } from "relay-runtime";
export type PolicyPagePolicyFragment$data = {
readonly id: string;
@@ -27,17 +27,22 @@ export type PolicyPagePolicyFragment$data = {
readonly id: string;
readonly publishedAt: any | null | undefined;
readonly signatures: {
readonly __id: string;
readonly edges: ReadonlyArray<{
readonly node: {
readonly id: string;
readonly signedBy: {
readonly id: string;
};
readonly state: PolicyVersionSignatureState;
readonly " $fragmentSpreads": FragmentRefs<"PolicySignaturesDialog_signature">;
};
}>;
};
readonly status: PolicyStatus;
readonly updatedAt: any;
readonly version: number;
readonly " $fragmentSpreads": FragmentRefs<"PolicyVersionHistoryDialogFragment">;
readonly " $fragmentSpreads": FragmentRefs<"PolicySignaturesDialog_version" | "PolicyVersionHistoryDialogFragment">;
};
}>;
};
@@ -55,12 +60,69 @@ var v0 = {
"kind": "ScalarField",
"name": "id",
"storageKey": null
},
v1 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "__typename",
"storageKey": null
},
v2 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "cursor",
"storageKey": null
},
v3 = {
"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
},
v4 = {
"kind": "ClientExtension",
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "__id",
"storageKey": null
}
]
};
return {
"argumentDefinitions": [],
"kind": "Fragment",
"metadata": {
"connection": [
{
"count": null,
"cursor": null,
"direction": "forward",
"path": null
},
{
"count": null,
"cursor": null,
@@ -161,17 +223,11 @@ return {
"storageKey": null
},
{
"alias": null,
"args": [
{
"kind": "Literal",
"name": "first",
"value": 100
}
],
"alias": "signatures",
"args": null,
"concreteType": "PolicyVersionSignatureConnection",
"kind": "LinkedField",
"name": "signatures",
"name": "__PolicyPage_signatures_connection",
"plural": false,
"selections": [
{
@@ -197,15 +253,36 @@ return {
"kind": "ScalarField",
"name": "state",
"storageKey": null
}
},
{
"alias": null,
"args": null,
"concreteType": "People",
"kind": "LinkedField",
"name": "signedBy",
"plural": false,
"selections": [
(v0/*: any*/)
],
"storageKey": null
},
{
"args": null,
"kind": "FragmentSpread",
"name": "PolicySignaturesDialog_signature"
},
(v1/*: any*/)
],
"storageKey": null
}
},
(v2/*: any*/)
],
"storageKey": null
}
},
(v3/*: any*/),
(v4/*: any*/)
],
"storageKey": "signatures(first:100)"
"storageKey": null
},
{
"args": null,
@@ -213,62 +290,20 @@ return {
"name": "PolicyVersionHistoryDialogFragment"
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "__typename",
"storageKey": null
}
"kind": "FragmentSpread",
"name": "PolicySignaturesDialog_version"
},
(v1/*: any*/)
],
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "cursor",
"storageKey": null
}
(v2/*: any*/)
],
"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
},
{
"kind": "ClientExtension",
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "__id",
"storageKey": null
}
]
}
(v3/*: any*/),
(v4/*: any*/)
],
"storageKey": null
}
@@ -278,6 +313,6 @@ return {
};
})();
(node as any).hash = "684db4b721c50638ee5ec1f9f4ebdd16";
(node as any).hash = "b53b22a05e1abd608ecd688b6a9d5bad";
export default node;

View File

@@ -0,0 +1,267 @@
import {
Avatar,
Badge,
Button,
Dialog,
DialogContent,
DialogFooter,
DialogTitle,
IconCircleCheck,
IconClock,
PolicyVersionBadge,
Spinner,
} from "@probo/ui";
import { useTranslate } from "@probo/i18n";
import { useState, type ReactNode, Suspense } from "react";
import type { PolicyPagePolicyFragment$data } from "../__generated__/PolicyPagePolicyFragment.graphql";
import clsx from "clsx";
import type { ItemOf, NodeOf } from "/types";
import { graphql, useFragment } from "react-relay";
import type { PolicySignaturesDialog_version$key } from "./__generated__/PolicySignaturesDialog_version.graphql";
import type { PolicySignaturesDialog_signature$key } from "./__generated__/PolicySignaturesDialog_signature.graphql";
import { usePeople } from "/hooks/graph/PeopleGraph.ts";
import { useOrganizationId } from "/hooks/useOrganizationId.ts";
import { useMutationWithToasts } from "/hooks/useMutationWithToasts.ts";
import { sprintf } from "@probo/helpers";
type Props = {
policy: PolicyPagePolicyFragment$data;
children?: ReactNode;
};
type Version = NodeOf<PolicyPagePolicyFragment$data["versions"]>;
export function PolicySignaturesDialog(props: Props) {
const { __ } = useTranslate();
const versions = props.policy.versions.edges.map((edge) => edge.node);
const [selectedVersionId, setSelectedVersionId] = useState<string>(
versions[0].id
);
const selectedVersion = versions.find((v) => v.id === selectedVersionId);
return (
<Dialog trigger={props.children}>
<DialogContent className="flex" scrollableChildren>
<aside className="p-6 overflow-y-auto w-60 flex-none space-y-2">
<div className="text-base text-txt-primary font-medium mb-4">
{__("Version History")}
</div>
{versions.map((version) => (
<VersionItem
key={version.id}
version={version}
active={selectedVersionId === version.id}
onSelect={setSelectedVersionId}
/>
))}
</aside>
<main className="flex-1 px-12 py-8">
<DialogTitle className="text-2xl font-bold text-txt-primary mb-4">
{__("Signatures")}
</DialogTitle>
<p className="text-sm text-txt-secondary mb-4">
{__(
"Click request to ask for a signature from people in your organization."
)}
</p>
<Suspense fallback={<Spinner centered />}>
<SignatureList version={selectedVersion} />
</Suspense>
</main>
</DialogContent>
<DialogFooter></DialogFooter>
</Dialog>
);
}
const versionFragment = graphql`
fragment PolicySignaturesDialog_version on PolicyVersion {
version
status
publishedAt
updatedAt
}
`;
function VersionItem(props: {
version: Version;
active?: boolean;
onSelect: (v: string) => void;
}) {
const { dateTimeFormat, __ } = useTranslate();
const version = useFragment<PolicySignaturesDialog_version$key>(
versionFragment,
props.version
);
return (
<button
onClick={() => props.onSelect(props.version.id)}
className={clsx(
"text-start space-y-1 w-full overflow-hidden py-2 px-3 w-full hover:bg-tertiary-hover cursor-pointer rounded",
props.active && "bg-tertiary-pressed"
)}
>
<div className="flex gap-1 text-sm text-txt-primary">
<span>
{__("Version")} {version.version}
</span>
<PolicyVersionBadge state={version.status} />
</div>
<div className="text-xs text-txt-secondary">
{dateTimeFormat(version.publishedAt ?? version.updatedAt)}
</div>
</button>
);
}
function SignatureList(props: { version: Version }) {
const signatures = props.version.signatures.edges.map((edge) => edge.node);
const { __ } = useTranslate();
const signatureMap = new Map(signatures.map((s) => [s.signedBy.id, s]));
const organizationId = useOrganizationId();
const people = usePeople(organizationId);
if (people.length === 0) {
return (
<div className="text-center text-sm text-txt-tertiary py-3">
{__("No people available to request signatures from")}
</div>
);
}
return (
<div className="space-y-2 divide-y divide-border-solid">
{people.map((p) => (
<SignatureItem
key={p.id}
versionId={props.version.id}
signature={signatureMap.get(p.id)}
people={p}
connectionId={props.version.signatures.__id}
/>
))}
</div>
);
}
/**
* Fragments
*/
const signatureFragment = graphql`
fragment PolicySignaturesDialog_signature on PolicyVersionSignature {
id
state
signedAt
requestedAt
signedBy {
fullName
primaryEmailAddress
}
}
`;
/**
* Mutations
*/
const requestSignatureMutation = graphql`
mutation PolicySignaturesDialog_requestSignatureMutation(
$input: RequestSignatureInput!
$connections: [ID!]!
) {
requestSignature(input: $input) {
policyVersionSignatureEdge @prependEdge(connections: $connections) {
node {
id
state
signedBy {
id
}
...PolicySignaturesDialog_signature
}
}
}
}
`;
function SignatureItem(props: {
versionId: string;
signature?: PolicySignaturesDialog_signature$key;
people: ItemOf<ReturnType<typeof usePeople>>;
connectionId: string;
}) {
const signature = useFragment(signatureFragment, props.signature);
const { __, dateTimeFormat } = useTranslate();
const [requestSignature, isSendingRequest] = useMutationWithToasts(
requestSignatureMutation,
{
successMessage: __("Signature request sent successfully"),
errorMessage: __("Failed to send signature request"),
}
);
// No signature request for this user
if (!signature) {
return (
<div className="flex gap-3 items-center py-3">
<Avatar size="l" name={props.people.fullName} />
<div className="space-y-1">
<div className="text-sm text-txt-primary font-medium">
{props.people.fullName}
</div>
<div className="text-xs text-txt-secondary">
{props.people.primaryEmailAddress}
</div>
</div>
<Button
variant="secondary"
className="ml-auto"
disabled={isSendingRequest}
onClick={() => {
requestSignature({
variables: {
input: {
policyVersionId: props.versionId,
signatoryId: props.people.id,
},
connections: [props.connectionId],
},
});
}}
>
{__("Request signature")}
</Button>
</div>
);
}
const isSigned = signature.state === "SIGNED";
const label = isSigned ? __("Signed on %s") : __("Requested on %s");
return (
<div className="flex gap-3 items-center py-3">
<Avatar size="l" name={signature.signedBy.fullName} />
<div className="space-y-1">
<div className="text-sm text-txt-primary font-medium">
{signature.signedBy.fullName}
</div>
<div className="text-xs text-txt-secondary flex items-center gap-1">
{isSigned ? (
<IconCircleCheck size={16} className="text-txt-accent" />
) : (
<IconClock size={16} />
)}
<span>
{sprintf(
label,
dateTimeFormat(
isSigned ? signature.signedAt : signature.requestedAt
)
)}
</span>
</div>
</div>
<Badge variant={isSigned ? "success" : "warning"} className="ml-auto">
{isSigned ? __("Signed") : __("Pending")}
</Badge>
</div>
);
}

View File

@@ -9,15 +9,9 @@ import {
import { graphql } from "relay-runtime";
import { useTranslate } from "@probo/i18n";
import { useState, type ReactNode } from "react";
import type {
PolicyPagePolicyFragment$data,
PolicyPagePolicyFragment$key,
} from "../__generated__/PolicyPagePolicyFragment.graphql";
import type { PolicyPagePolicyFragment$data } from "../__generated__/PolicyPagePolicyFragment.graphql";
import { useFragment } from "react-relay";
import type {
PolicyVersionHistoryDialogFragment$data,
PolicyVersionHistoryDialogFragment$key,
} from "./__generated__/PolicyVersionHistoryDialogFragment.graphql";
import type { PolicyVersionHistoryDialogFragment$key } from "./__generated__/PolicyVersionHistoryDialogFragment.graphql";
import clsx from "clsx";
import type { NodeOf } from "/types";
@@ -48,15 +42,16 @@ export function PolicyVersionHistoryDialog(props: Props) {
const versions = props.policy.versions.edges.map((edge) => edge.node);
const [selectedVersion, setSelectedVersion] = useState<Version>(versions[0]);
return (
<Dialog defaultOpen trigger={props.children}>
<Dialog trigger={props.children}>
<DialogContent className="flex" scrollableChildren>
<aside className="p-6 overflow-y-auto w-60 flex-none">
<aside className="p-6 overflow-y-auto w-60 flex-none space-y-2">
<DialogTitle className="text-base text-txt-primary font-medium mb-4">
{__("Version History")}
</DialogTitle>
{versions.map((version) => (
<VersionItem
key={version.id}
policy={props.policy}
version={version}
active={selectedVersion === version}
onSelect={setSelectedVersion}
@@ -67,12 +62,13 @@ export function PolicyVersionHistoryDialog(props: Props) {
<Markdown content={selectedVersion.content} />
</main>
</DialogContent>
<DialogFooter></DialogFooter>
<DialogFooter />
</Dialog>
);
}
function VersionItem(props: {
policy: PolicyPagePolicyFragment$data;
version: Version;
active?: boolean;
onSelect: (v: Version) => void;
@@ -81,26 +77,25 @@ function VersionItem(props: {
historyFragment,
props.version
);
const { dateFormat } = useTranslate();
const { dateTimeFormat } = useTranslate();
return (
<button
onClick={() => props.onSelect(props.version)}
className={clsx(
"flex items-center gap-1 py-2 px-[10px] w-full hover:bg-tertiary-hover cursor-pointer rounded",
"flex items-center gap-2 py-2 px-[10px] w-full hover:bg-tertiary-hover cursor-pointer rounded",
props.active && "bg-tertiary-pressed"
)}
>
<Avatar name={version.publishedBy?.fullName ?? ""} size="l" />
<div className="space-y-[2px]">
<div className="text-sm text-txt-primary">
{version.publishedBy?.fullName ?? "Anonymous"}
<Avatar
name={version.publishedBy?.fullName ?? props.policy.owner.fullName}
size="l"
/>
<div className="text-start space-y-[2px] w-full overflow-hidden">
<div className="text-sm text-txt-primary whitespace-nowrap overflow-hidden text-ellipsis">
{version.publishedBy?.fullName ?? props.policy.owner.fullName}
</div>
<div className="text-xs text-txt-secondary">
{dateFormat(version.publishedAt, {
day: "numeric",
month: "short",
year: "numeric",
})}
<div className="text-xs text-txt-secondary whitespace-nowrap overflow-hidden text-ellipsis">
{dateTimeFormat(version.publishedAt ?? version.updatedAt)}
</div>
</div>
</button>

View File

@@ -0,0 +1,254 @@
/**
* @generated SignedSource<<af123c927212dd99fbaeb81e3b2f2bd9>>
* @lightSyntaxTransform
* @nogrep
*/
/* tslint:disable */
/* eslint-disable */
// @ts-nocheck
import { ConcreteRequest } from 'relay-runtime';
import { FragmentRefs } from "relay-runtime";
export type PolicyVersionSignatureState = "REQUESTED" | "SIGNED";
export type RequestSignatureInput = {
policyVersionId: string;
signatoryId: string;
};
export type PolicySignaturesDialog_requestSignatureMutation$variables = {
connections: ReadonlyArray<string>;
input: RequestSignatureInput;
};
export type PolicySignaturesDialog_requestSignatureMutation$data = {
readonly requestSignature: {
readonly policyVersionSignatureEdge: {
readonly node: {
readonly id: string;
readonly signedBy: {
readonly id: string;
};
readonly state: PolicyVersionSignatureState;
readonly " $fragmentSpreads": FragmentRefs<"PolicySignaturesDialog_signature">;
};
};
};
};
export type PolicySignaturesDialog_requestSignatureMutation = {
response: PolicySignaturesDialog_requestSignatureMutation$data;
variables: PolicySignaturesDialog_requestSignatureMutation$variables;
};
const node: ConcreteRequest = (function(){
var v0 = {
"defaultValue": null,
"kind": "LocalArgument",
"name": "connections"
},
v1 = {
"defaultValue": null,
"kind": "LocalArgument",
"name": "input"
},
v2 = [
{
"kind": "Variable",
"name": "input",
"variableName": "input"
}
],
v3 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "id",
"storageKey": null
},
v4 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "state",
"storageKey": null
};
return {
"fragment": {
"argumentDefinitions": [
(v0/*: any*/),
(v1/*: any*/)
],
"kind": "Fragment",
"metadata": null,
"name": "PolicySignaturesDialog_requestSignatureMutation",
"selections": [
{
"alias": null,
"args": (v2/*: any*/),
"concreteType": "RequestSignaturePayload",
"kind": "LinkedField",
"name": "requestSignature",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"concreteType": "PolicyVersionSignatureEdge",
"kind": "LinkedField",
"name": "policyVersionSignatureEdge",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"concreteType": "PolicyVersionSignature",
"kind": "LinkedField",
"name": "node",
"plural": false,
"selections": [
(v3/*: any*/),
(v4/*: any*/),
{
"alias": null,
"args": null,
"concreteType": "People",
"kind": "LinkedField",
"name": "signedBy",
"plural": false,
"selections": [
(v3/*: any*/)
],
"storageKey": null
},
{
"args": null,
"kind": "FragmentSpread",
"name": "PolicySignaturesDialog_signature"
}
],
"storageKey": null
}
],
"storageKey": null
}
],
"storageKey": null
}
],
"type": "Mutation",
"abstractKey": null
},
"kind": "Request",
"operation": {
"argumentDefinitions": [
(v1/*: any*/),
(v0/*: any*/)
],
"kind": "Operation",
"name": "PolicySignaturesDialog_requestSignatureMutation",
"selections": [
{
"alias": null,
"args": (v2/*: any*/),
"concreteType": "RequestSignaturePayload",
"kind": "LinkedField",
"name": "requestSignature",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"concreteType": "PolicyVersionSignatureEdge",
"kind": "LinkedField",
"name": "policyVersionSignatureEdge",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"concreteType": "PolicyVersionSignature",
"kind": "LinkedField",
"name": "node",
"plural": false,
"selections": [
(v3/*: any*/),
(v4/*: any*/),
{
"alias": null,
"args": null,
"concreteType": "People",
"kind": "LinkedField",
"name": "signedBy",
"plural": false,
"selections": [
(v3/*: any*/),
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "fullName",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "primaryEmailAddress",
"storageKey": null
}
],
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "signedAt",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "requestedAt",
"storageKey": null
}
],
"storageKey": null
}
],
"storageKey": null
},
{
"alias": null,
"args": null,
"filters": null,
"handle": "prependEdge",
"key": "",
"kind": "LinkedHandle",
"name": "policyVersionSignatureEdge",
"handleArgs": [
{
"kind": "Variable",
"name": "connections",
"variableName": "connections"
}
]
}
],
"storageKey": null
}
]
},
"params": {
"cacheID": "20c460adbc3480622c4c91220a6e54fe",
"id": null,
"metadata": {},
"name": "PolicySignaturesDialog_requestSignatureMutation",
"operationKind": "mutation",
"text": "mutation PolicySignaturesDialog_requestSignatureMutation(\n $input: RequestSignatureInput!\n) {\n requestSignature(input: $input) {\n policyVersionSignatureEdge {\n node {\n id\n state\n signedBy {\n id\n }\n ...PolicySignaturesDialog_signature\n }\n }\n }\n}\n\nfragment PolicySignaturesDialog_signature on PolicyVersionSignature {\n id\n state\n signedAt\n requestedAt\n signedBy {\n fullName\n primaryEmailAddress\n id\n }\n}\n"
}
};
})();
(node as any).hash = "24825b1c4040debb7edda76c8ad3d662";
export default node;

View File

@@ -0,0 +1,96 @@
/**
* @generated SignedSource<<4bda7ac839740680ea31b4c20299d9d4>>
* @lightSyntaxTransform
* @nogrep
*/
/* tslint:disable */
/* eslint-disable */
// @ts-nocheck
import { ReaderFragment } from 'relay-runtime';
export type PolicyVersionSignatureState = "REQUESTED" | "SIGNED";
import { FragmentRefs } from "relay-runtime";
export type PolicySignaturesDialog_signature$data = {
readonly id: string;
readonly requestedAt: any;
readonly signedAt: any | null | undefined;
readonly signedBy: {
readonly fullName: string;
readonly primaryEmailAddress: string;
};
readonly state: PolicyVersionSignatureState;
readonly " $fragmentType": "PolicySignaturesDialog_signature";
};
export type PolicySignaturesDialog_signature$key = {
readonly " $data"?: PolicySignaturesDialog_signature$data;
readonly " $fragmentSpreads": FragmentRefs<"PolicySignaturesDialog_signature">;
};
const node: ReaderFragment = {
"argumentDefinitions": [],
"kind": "Fragment",
"metadata": null,
"name": "PolicySignaturesDialog_signature",
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "id",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "state",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "signedAt",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "requestedAt",
"storageKey": null
},
{
"alias": null,
"args": null,
"concreteType": "People",
"kind": "LinkedField",
"name": "signedBy",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "fullName",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "primaryEmailAddress",
"storageKey": null
}
],
"storageKey": null
}
],
"type": "PolicyVersionSignature",
"abstractKey": null
};
(node as any).hash = "b2e435dc6db3a0df223af98251adcb30";
export default node;

View File

@@ -0,0 +1,67 @@
/**
* @generated SignedSource<<efbbec863b7456c271e408fb553f9ea1>>
* @lightSyntaxTransform
* @nogrep
*/
/* tslint:disable */
/* eslint-disable */
// @ts-nocheck
import { ReaderFragment } from 'relay-runtime';
export type PolicyStatus = "DRAFT" | "PUBLISHED";
import { FragmentRefs } from "relay-runtime";
export type PolicySignaturesDialog_version$data = {
readonly publishedAt: any | null | undefined;
readonly status: PolicyStatus;
readonly updatedAt: any;
readonly version: number;
readonly " $fragmentType": "PolicySignaturesDialog_version";
};
export type PolicySignaturesDialog_version$key = {
readonly " $data"?: PolicySignaturesDialog_version$data;
readonly " $fragmentSpreads": FragmentRefs<"PolicySignaturesDialog_version">;
};
const node: ReaderFragment = {
"argumentDefinitions": [],
"kind": "Fragment",
"metadata": null,
"name": "PolicySignaturesDialog_version",
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "version",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "status",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "publishedAt",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "updatedAt",
"storageKey": null
}
],
"type": "PolicyVersion",
"abstractKey": null
};
(node as any).hash = "cdec8e3244fd6329a86b5825a4133c44";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<929e2bdd729e8b9654b27cd9e9dbccb2>>
* @generated SignedSource<<45feb21e3f613b3818af04725831a427>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -9,7 +9,7 @@
// @ts-nocheck
import { ReaderFragment } from 'relay-runtime';
export type PolicyStatus = "DRAFT" | "PUBLISHED" | "%future added value";
export type PolicyStatus = "DRAFT" | "PUBLISHED";
import { FragmentRefs } from "relay-runtime";
export type PolicyVersionHistoryDialogFragment$data = {
readonly changelog: string;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<e90085131e94bcac0f94ecf5b1329712>>
* @generated SignedSource<<7b7cbab5e73007ace1e7d07970b633e8>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -9,8 +9,8 @@
// @ts-nocheck
import { ConcreteRequest } from 'relay-runtime';
export type PolicyStatus = "DRAFT" | "PUBLISHED" | "%future added value";
export type PolicyVersionSignatureState = "REQUESTED" | "SIGNED" | "%future added value";
export type PolicyStatus = "DRAFT" | "PUBLISHED";
export type PolicyVersionSignatureState = "REQUESTED" | "SIGNED";
export type CreateDraftPolicyVersionInput = {
policyID: string;
};

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<05dd3d535fb39d12fc0c015864a85d31>>
* @generated SignedSource<<7d5730a1c721f5256e6e0c07199aa0d2>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -10,7 +10,7 @@
import { ConcreteRequest } from 'relay-runtime';
import { FragmentRefs } from "relay-runtime";
export type RiskTreatment = "ACCEPTED" | "AVOIDED" | "MITIGATED" | "TRANSFERRED" | "%future added value";
export type RiskTreatment = "ACCEPTED" | "AVOIDED" | "MITIGATED" | "TRANSFERRED";
export type CreateRiskInput = {
category: string;
description: string;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<71792ccd18aa886a5df0ecfa8a23fda9>>
* @generated SignedSource<<dc5427f9197a47414ed10738473fdca1>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -10,7 +10,7 @@
import { ConcreteRequest } from 'relay-runtime';
import { FragmentRefs } from "relay-runtime";
export type RiskTreatment = "ACCEPTED" | "AVOIDED" | "MITIGATED" | "TRANSFERRED" | "%future added value";
export type RiskTreatment = "ACCEPTED" | "AVOIDED" | "MITIGATED" | "TRANSFERRED";
export type UpdateRiskInput = {
category?: string | null | undefined;
description?: string | null | undefined;

View File

@@ -1,262 +0,0 @@
/**
* @generated SignedSource<<cfb39c3c814ed520de659842d6fffe38>>
* @lightSyntaxTransform
* @nogrep
*/
/* tslint:disable */
/* eslint-disable */
// @ts-nocheck
import { ConcreteRequest } from 'relay-runtime';
import { FragmentRefs } from "relay-runtime";
export type RiskTreatment = "ACCEPTED" | "AVOIDED" | "MITIGATED" | "TRANSFERRED" | "%future added value";
export type RiskDetailPageQuery$variables = {
riskId: string;
};
export type RiskDetailPageQuery$data = {
readonly node: {
readonly createdAt?: any;
readonly description?: string;
readonly inherentImpact?: number;
readonly inherentLikelihood?: number;
readonly name?: string;
readonly note?: string;
readonly owner?: {
readonly fullName: string;
readonly id: string;
} | null | undefined;
readonly residualImpact?: number;
readonly residualLikelihood?: number;
readonly treatment?: RiskTreatment;
readonly updatedAt?: any;
readonly " $fragmentSpreads": FragmentRefs<"useRiskFormFragment">;
};
};
export type RiskDetailPageQuery = {
response: RiskDetailPageQuery$data;
variables: RiskDetailPageQuery$variables;
};
const node: ConcreteRequest = (function(){
var v0 = [
{
"defaultValue": null,
"kind": "LocalArgument",
"name": "riskId"
}
],
v1 = [
{
"kind": "Variable",
"name": "id",
"variableName": "riskId"
}
],
v2 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "name",
"storageKey": null
},
v3 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "description",
"storageKey": null
},
v4 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "treatment",
"storageKey": null
},
v5 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "id",
"storageKey": null
},
v6 = {
"alias": null,
"args": null,
"concreteType": "People",
"kind": "LinkedField",
"name": "owner",
"plural": false,
"selections": [
(v5/*: any*/),
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "fullName",
"storageKey": null
}
],
"storageKey": null
},
v7 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "inherentLikelihood",
"storageKey": null
},
v8 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "inherentImpact",
"storageKey": null
},
v9 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "residualLikelihood",
"storageKey": null
},
v10 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "residualImpact",
"storageKey": null
},
v11 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "note",
"storageKey": null
},
v12 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "createdAt",
"storageKey": null
},
v13 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "updatedAt",
"storageKey": null
};
return {
"fragment": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Fragment",
"metadata": null,
"name": "RiskDetailPageQuery",
"selections": [
{
"alias": null,
"args": (v1/*: any*/),
"concreteType": null,
"kind": "LinkedField",
"name": "node",
"plural": false,
"selections": [
{
"kind": "InlineFragment",
"selections": [
(v2/*: any*/),
(v3/*: any*/),
(v4/*: any*/),
(v6/*: any*/),
(v7/*: any*/),
(v8/*: any*/),
(v9/*: any*/),
(v10/*: any*/),
(v11/*: any*/),
(v12/*: any*/),
(v13/*: any*/),
{
"args": null,
"kind": "FragmentSpread",
"name": "useRiskFormFragment"
}
],
"type": "Risk",
"abstractKey": null
}
],
"storageKey": null
}
],
"type": "Query",
"abstractKey": null
},
"kind": "Request",
"operation": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Operation",
"name": "RiskDetailPageQuery",
"selections": [
{
"alias": null,
"args": (v1/*: any*/),
"concreteType": null,
"kind": "LinkedField",
"name": "node",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "__typename",
"storageKey": null
},
(v5/*: any*/),
{
"kind": "InlineFragment",
"selections": [
(v2/*: any*/),
(v3/*: any*/),
(v4/*: any*/),
(v6/*: any*/),
(v7/*: any*/),
(v8/*: any*/),
(v9/*: any*/),
(v10/*: any*/),
(v11/*: any*/),
(v12/*: any*/),
(v13/*: any*/),
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "category",
"storageKey": null
}
],
"type": "Risk",
"abstractKey": null
}
],
"storageKey": null
}
]
},
"params": {
"cacheID": "0ed24be13c829da91705d506a46eb562",
"id": null,
"metadata": {},
"name": "RiskDetailPageQuery",
"operationKind": "query",
"text": "query RiskDetailPageQuery(\n $riskId: ID!\n) {\n node(id: $riskId) {\n __typename\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 ...useRiskFormFragment\n }\n id\n }\n}\n\nfragment useRiskFormFragment on Risk {\n id\n name\n category\n description\n treatment\n inherentLikelihood\n inherentImpact\n residualLikelihood\n residualImpact\n note\n owner {\n id\n }\n}\n"
}
};
})();
(node as any).hash = "94de027c557f9b633765f9dde7c0aae1";
export default node;

View File

@@ -1,132 +0,0 @@
/**
* @generated SignedSource<<b410e2d0b99401f7ad86c1d4f7a0fcfe>>
* @lightSyntaxTransform
* @nogrep
*/
/* tslint:disable */
/* eslint-disable */
// @ts-nocheck
import { ConcreteRequest } from 'relay-runtime';
export type DeleteRiskInput = {
riskId: string;
};
export type RisksPageDeleteMutation$variables = {
connections: ReadonlyArray<string>;
input: DeleteRiskInput;
};
export type RisksPageDeleteMutation$data = {
readonly deleteRisk: {
readonly deletedRiskId: string;
};
};
export type RisksPageDeleteMutation = {
response: RisksPageDeleteMutation$data;
variables: RisksPageDeleteMutation$variables;
};
const node: ConcreteRequest = (function(){
var v0 = {
"defaultValue": null,
"kind": "LocalArgument",
"name": "connections"
},
v1 = {
"defaultValue": null,
"kind": "LocalArgument",
"name": "input"
},
v2 = [
{
"kind": "Variable",
"name": "input",
"variableName": "input"
}
],
v3 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "deletedRiskId",
"storageKey": null
};
return {
"fragment": {
"argumentDefinitions": [
(v0/*: any*/),
(v1/*: any*/)
],
"kind": "Fragment",
"metadata": null,
"name": "RisksPageDeleteMutation",
"selections": [
{
"alias": null,
"args": (v2/*: any*/),
"concreteType": "DeleteRiskPayload",
"kind": "LinkedField",
"name": "deleteRisk",
"plural": false,
"selections": [
(v3/*: any*/)
],
"storageKey": null
}
],
"type": "Mutation",
"abstractKey": null
},
"kind": "Request",
"operation": {
"argumentDefinitions": [
(v1/*: any*/),
(v0/*: any*/)
],
"kind": "Operation",
"name": "RisksPageDeleteMutation",
"selections": [
{
"alias": null,
"args": (v2/*: any*/),
"concreteType": "DeleteRiskPayload",
"kind": "LinkedField",
"name": "deleteRisk",
"plural": false,
"selections": [
(v3/*: any*/),
{
"alias": null,
"args": null,
"filters": null,
"handle": "deleteEdge",
"key": "",
"kind": "ScalarHandle",
"name": "deletedRiskId",
"handleArgs": [
{
"kind": "Variable",
"name": "connections",
"variableName": "connections"
}
]
}
],
"storageKey": null
}
]
},
"params": {
"cacheID": "a08977dc1d81b5ab63e431014b2d2b41",
"id": null,
"metadata": {},
"name": "RisksPageDeleteMutation",
"operationKind": "mutation",
"text": "mutation RisksPageDeleteMutation(\n $input: DeleteRiskInput!\n) {\n deleteRisk(input: $input) {\n deletedRiskId\n }\n}\n"
}
};
})();
(node as any).hash = "fb17a17779665063283d3d73fcb39785";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<83a07ae53aaa5005db49f5ea8b4479c6>>
* @generated SignedSource<<62ef6617862f528f26edaffe3adc3069>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -9,7 +9,7 @@
// @ts-nocheck
import { ReaderFragment } from 'relay-runtime';
export type MeasureState = "IMPLEMENTED" | "IN_PROGRESS" | "NOT_APPLICABLE" | "NOT_STARTED" | "%future added value";
export type MeasureState = "IMPLEMENTED" | "IN_PROGRESS" | "NOT_APPLICABLE" | "NOT_STARTED";
import { FragmentRefs } from "relay-runtime";
export type RiskMeasuresTabFragment$data = {
readonly id: string;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<ddd22d66836f5fd323ddf25475dd6d72>>
* @generated SignedSource<<2de1bbc55eb7b45a9546c8ec306ad979>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -9,8 +9,8 @@
// @ts-nocheck
import { ConcreteRequest } from 'relay-runtime';
export type BusinessImpact = "CRITICAL" | "HIGH" | "LOW" | "MEDIUM" | "%future added value";
export type DataSensitivity = "CRITICAL" | "HIGH" | "LOW" | "MEDIUM" | "NONE" | "%future added value";
export type BusinessImpact = "CRITICAL" | "HIGH" | "LOW" | "MEDIUM";
export type DataSensitivity = "CRITICAL" | "HIGH" | "LOW" | "MEDIUM" | "NONE";
export type VendorsPageQuery$variables = {
organizationId: string;
};