Allow linking controls
Signed-off-by: Bryan Frimin <bryan@getprobo.com> Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
committed by
Sacha Al Himdani
parent
93aeedf1e1
commit
ab077c385e
@@ -31,6 +31,7 @@
|
||||
"react-relay": "^19.0.0",
|
||||
"react-router": "^7.6.0",
|
||||
"relay-runtime": "^19.0.0",
|
||||
"use-debounce": "^10.0.5",
|
||||
"usehooks-ts": "^3.1.1",
|
||||
"zod": "^3.25.17"
|
||||
},
|
||||
|
||||
@@ -3,17 +3,20 @@ import {
|
||||
Button,
|
||||
Tr,
|
||||
Td,
|
||||
Table,
|
||||
Thead,
|
||||
Tbody,
|
||||
Th,
|
||||
IconTrashCan,
|
||||
Badge,
|
||||
TrButton,
|
||||
} from "@probo/ui";
|
||||
import { useTranslate } from "@probo/i18n";
|
||||
import type { LinkedControlsCardFragment$key } from "./__generated__/LinkedControlsCardFragment.graphql";
|
||||
import { useFragment } from "react-relay";
|
||||
import { useOrganizationId } from "/hooks/useOrganizationId";
|
||||
import { LinkedControlsDialog } from "./LinkedControlsDialog";
|
||||
import { SortableTable, SortableTh } from "../SortableTable";
|
||||
import type { ComponentProps } from "react";
|
||||
|
||||
const linkedControlFragment = graphql`
|
||||
fragment LinkedControlsCardFragment on Control {
|
||||
@@ -46,6 +49,10 @@ type Props<Params> = {
|
||||
connectionId: string;
|
||||
// Mutation to detach a control (will receive {controlId, ...params})
|
||||
onDetach: Mutation<Params>;
|
||||
// Mutation to attach a control (will receive {controlId, ...params})
|
||||
onAttach?: Mutation<Params>;
|
||||
// Allow sorting in the table
|
||||
refetch: Pick<ComponentProps<typeof SortableTable>, "refetch">;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -67,11 +74,26 @@ export function LinkedControlsCard<Params>(props: Props<Params>) {
|
||||
});
|
||||
};
|
||||
|
||||
const onAttach = (controlId: string) => {
|
||||
if (!props.onAttach) {
|
||||
return;
|
||||
}
|
||||
props.onAttach({
|
||||
variables: {
|
||||
input: {
|
||||
controlId,
|
||||
...props.params,
|
||||
},
|
||||
connections: [props.connectionId],
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Table>
|
||||
<SortableTable refetch={props.refetch as any}>
|
||||
<Thead>
|
||||
<Tr>
|
||||
<Th>{__("Reference")}</Th>
|
||||
<SortableTh field="SECTION_TITLE">{__("Reference")}</SortableTh>
|
||||
<Th>{__("Name")}</Th>
|
||||
<Th></Th>
|
||||
</Tr>
|
||||
@@ -85,16 +107,31 @@ export function LinkedControlsCard<Params>(props: Props<Params>) {
|
||||
</Tr>
|
||||
)}
|
||||
{controls.map((control) => (
|
||||
<ControlRow key={control.id} control={control} onClick={onDetach} />
|
||||
<ControlRow
|
||||
key={control.id}
|
||||
control={control}
|
||||
onClick={onDetach}
|
||||
onAttach={onAttach}
|
||||
/>
|
||||
))}
|
||||
<LinkedControlsDialog
|
||||
connectionId={props.connectionId}
|
||||
disabled={props.disabled}
|
||||
linkedControls={controls}
|
||||
onLink={onAttach}
|
||||
onUnlink={onDetach}
|
||||
>
|
||||
<TrButton colspan={3}>{__("Link control")}</TrButton>
|
||||
</LinkedControlsDialog>
|
||||
</Tbody>
|
||||
</Table>
|
||||
</SortableTable>
|
||||
);
|
||||
}
|
||||
|
||||
function ControlRow(props: {
|
||||
control: LinkedControlsCardFragment$key & { id: string };
|
||||
onClick: (controlId: string) => void;
|
||||
onAttach?: (controlId: string) => void;
|
||||
}) {
|
||||
const control = useFragment(linkedControlFragment, props.control);
|
||||
const organizationId = useOrganizationId();
|
||||
|
||||
185
apps/console2/src/components/controls/LinkedControlsDialog.tsx
Normal file
185
apps/console2/src/components/controls/LinkedControlsDialog.tsx
Normal file
@@ -0,0 +1,185 @@
|
||||
import {
|
||||
Badge,
|
||||
Button,
|
||||
Dialog,
|
||||
DialogContent,
|
||||
IconMagnifyingGlass,
|
||||
IconPlusLarge,
|
||||
IconTrashCan,
|
||||
InfiniteScrollTrigger,
|
||||
Input,
|
||||
Spinner,
|
||||
} from "@probo/ui";
|
||||
import {
|
||||
Suspense,
|
||||
useMemo,
|
||||
useRef,
|
||||
type ReactNode,
|
||||
type RefObject,
|
||||
} from "react";
|
||||
import { useTranslate } from "@probo/i18n";
|
||||
import { graphql } from "relay-runtime";
|
||||
import { useOrganizationId } from "/hooks/useOrganizationId";
|
||||
import { useLazyLoadQuery, usePaginationFragment } from "react-relay";
|
||||
import type { LinkedControlsDialogQuery } from "./__generated__/LinkedControlsDialogQuery.graphql";
|
||||
import type {
|
||||
LinkedControlsDialogFragment$data,
|
||||
LinkedControlsDialogFragment$key,
|
||||
} from "./__generated__/LinkedControlsDialogFragment.graphql";
|
||||
import type { NodeOf } from "/types";
|
||||
import { useDebounceCallback } from "usehooks-ts";
|
||||
|
||||
const query = graphql`
|
||||
query LinkedControlsDialogQuery($organizationId: ID!) {
|
||||
organization: node(id: $organizationId) {
|
||||
id
|
||||
...LinkedControlsDialogFragment
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const controlsFragment = graphql`
|
||||
fragment LinkedControlsDialogFragment on Organization
|
||||
@argumentDefinitions(
|
||||
first: { type: "Int", defaultValue: 1 }
|
||||
after: { type: "CursorKey" }
|
||||
last: { type: "Int", defaultValue: null }
|
||||
before: { type: "CursorKey", defaultValue: null }
|
||||
order: { type: "ControlOrder", defaultValue: null }
|
||||
filter: { type: "ControlFilter", defaultValue: null }
|
||||
)
|
||||
@refetchable(queryName: "LinkedControlsDialogControlsQuery") {
|
||||
controls(
|
||||
first: $first
|
||||
after: $after
|
||||
last: $last
|
||||
before: $before
|
||||
orderBy: $order
|
||||
filter: $filter
|
||||
) @connection(key: "LinkedControlsDialogControlsQuery_controls") {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
name
|
||||
sectionTitle
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
type Props = {
|
||||
children: ReactNode;
|
||||
connectionId: string;
|
||||
disabled?: boolean;
|
||||
linkedControls?: { id: string }[];
|
||||
onLink: (controlId: string) => void;
|
||||
onUnlink: (controlId: string) => void;
|
||||
};
|
||||
|
||||
type SearchRef = RefObject<{ search: (v: string) => void } | null>;
|
||||
|
||||
export function LinkedControlsDialog(props: Props) {
|
||||
const { __ } = useTranslate();
|
||||
const searchRef: SearchRef = useRef(null);
|
||||
const onSearch = (v: string) => {
|
||||
searchRef.current?.search(v);
|
||||
};
|
||||
return (
|
||||
<Dialog trigger={props.children} title={__("Link controls")}>
|
||||
<DialogContent>
|
||||
<div className="flex items-center gap-2 sticky top-0 relative py-4 bg-linear-to-b from-50% from-level-2 to-level-2/0 px-6">
|
||||
<Input
|
||||
icon={IconMagnifyingGlass}
|
||||
placeholder={__("Search measures...")}
|
||||
onValueChange={onSearch}
|
||||
/>
|
||||
</div>
|
||||
<Suspense fallback={<Spinner centered />}>
|
||||
<LinkedControlsDialogContent {...props} ref={searchRef} />
|
||||
</Suspense>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
function LinkedControlsDialogContent(props: Props & { ref: SearchRef }) {
|
||||
const organizationId = useOrganizationId();
|
||||
const mainData = useLazyLoadQuery<LinkedControlsDialogQuery>(query, {
|
||||
organizationId,
|
||||
});
|
||||
const { data, loadNext, hasNext, isLoadingNext, refetch } =
|
||||
usePaginationFragment(
|
||||
controlsFragment,
|
||||
mainData.organization as LinkedControlsDialogFragment$key
|
||||
);
|
||||
|
||||
const controls = data.controls?.edges?.map((edge) => edge.node) ?? [];
|
||||
const controlIds = useMemo(() => {
|
||||
return new Set(props.linkedControls?.map((c) => c.id) ?? []);
|
||||
}, [props.linkedControls]);
|
||||
|
||||
props.ref.current = {
|
||||
search: useDebounceCallback((v: string) => {
|
||||
refetch({
|
||||
first: 20,
|
||||
filter: {
|
||||
query: v,
|
||||
},
|
||||
});
|
||||
}, 500),
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="divide-y divide-border-low">
|
||||
{controls.map((control) => (
|
||||
<ControlRow
|
||||
key={control.id}
|
||||
control={control}
|
||||
controlIds={controlIds}
|
||||
{...props}
|
||||
/>
|
||||
))}
|
||||
{hasNext && (
|
||||
<InfiniteScrollTrigger
|
||||
loading={isLoadingNext}
|
||||
onView={() => loadNext(20)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function ControlRow(
|
||||
props: {
|
||||
control: NodeOf<LinkedControlsDialogFragment$data["controls"]>;
|
||||
controlIds: Set<string>;
|
||||
} & Props
|
||||
) {
|
||||
const { __ } = useTranslate();
|
||||
const isLinked = props.controlIds.has(props.control.id);
|
||||
const onClick = isLinked ? props.onUnlink : props.onLink;
|
||||
const IconComponent = isLinked ? IconTrashCan : IconPlusLarge;
|
||||
return (
|
||||
<button
|
||||
className="py-4 flex items-center gap-4 hover:bg-subtle cursor-pointer px-6 w-full text-start"
|
||||
onClick={() => onClick(props.control.id)}
|
||||
>
|
||||
<Badge size="md">{props.control.sectionTitle}</Badge>
|
||||
{props.control.name}
|
||||
|
||||
<Button
|
||||
disabled={props.disabled}
|
||||
className="ml-auto"
|
||||
variant={isLinked ? "secondary" : "primary"}
|
||||
asChild
|
||||
>
|
||||
<span>
|
||||
<IconComponent size={16} /> {isLinked ? __("Unlink") : __("Link")}
|
||||
</span>
|
||||
</Button>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
337
apps/console2/src/components/controls/__generated__/LinkedControlsDialogControlsQuery.graphql.ts
generated
Normal file
337
apps/console2/src/components/controls/__generated__/LinkedControlsDialogControlsQuery.graphql.ts
generated
Normal file
@@ -0,0 +1,337 @@
|
||||
/**
|
||||
* @generated SignedSource<<abe97be0de1c878a30ced882c0d22fee>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
|
||||
import { ConcreteRequest } from 'relay-runtime';
|
||||
import { FragmentRefs } from "relay-runtime";
|
||||
export type ControlOrderField = "CREATED_AT" | "SECTION_TITLE";
|
||||
export type OrderDirection = "ASC" | "DESC";
|
||||
export type ControlFilter = {
|
||||
query?: string | null | undefined;
|
||||
};
|
||||
export type ControlOrder = {
|
||||
direction: OrderDirection;
|
||||
field: ControlOrderField;
|
||||
};
|
||||
export type LinkedControlsDialogControlsQuery$variables = {
|
||||
after?: any | null | undefined;
|
||||
before?: any | null | undefined;
|
||||
filter?: ControlFilter | null | undefined;
|
||||
first?: number | null | undefined;
|
||||
id: string;
|
||||
last?: number | null | undefined;
|
||||
order?: ControlOrder | null | undefined;
|
||||
};
|
||||
export type LinkedControlsDialogControlsQuery$data = {
|
||||
readonly node: {
|
||||
readonly " $fragmentSpreads": FragmentRefs<"LinkedControlsDialogFragment">;
|
||||
};
|
||||
};
|
||||
export type LinkedControlsDialogControlsQuery = {
|
||||
response: LinkedControlsDialogControlsQuery$data;
|
||||
variables: LinkedControlsDialogControlsQuery$variables;
|
||||
};
|
||||
|
||||
const node: ConcreteRequest = (function(){
|
||||
var v0 = {
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "after"
|
||||
},
|
||||
v1 = {
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "before"
|
||||
},
|
||||
v2 = {
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "filter"
|
||||
},
|
||||
v3 = {
|
||||
"defaultValue": 1,
|
||||
"kind": "LocalArgument",
|
||||
"name": "first"
|
||||
},
|
||||
v4 = {
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "id"
|
||||
},
|
||||
v5 = {
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "last"
|
||||
},
|
||||
v6 = {
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "order"
|
||||
},
|
||||
v7 = [
|
||||
{
|
||||
"kind": "Variable",
|
||||
"name": "id",
|
||||
"variableName": "id"
|
||||
}
|
||||
],
|
||||
v8 = {
|
||||
"kind": "Variable",
|
||||
"name": "after",
|
||||
"variableName": "after"
|
||||
},
|
||||
v9 = {
|
||||
"kind": "Variable",
|
||||
"name": "before",
|
||||
"variableName": "before"
|
||||
},
|
||||
v10 = {
|
||||
"kind": "Variable",
|
||||
"name": "filter",
|
||||
"variableName": "filter"
|
||||
},
|
||||
v11 = {
|
||||
"kind": "Variable",
|
||||
"name": "first",
|
||||
"variableName": "first"
|
||||
},
|
||||
v12 = {
|
||||
"kind": "Variable",
|
||||
"name": "last",
|
||||
"variableName": "last"
|
||||
},
|
||||
v13 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "__typename",
|
||||
"storageKey": null
|
||||
},
|
||||
v14 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "id",
|
||||
"storageKey": null
|
||||
},
|
||||
v15 = [
|
||||
(v8/*: any*/),
|
||||
(v9/*: any*/),
|
||||
(v10/*: any*/),
|
||||
(v11/*: any*/),
|
||||
(v12/*: any*/),
|
||||
{
|
||||
"kind": "Variable",
|
||||
"name": "orderBy",
|
||||
"variableName": "order"
|
||||
}
|
||||
];
|
||||
return {
|
||||
"fragment": {
|
||||
"argumentDefinitions": [
|
||||
(v0/*: any*/),
|
||||
(v1/*: any*/),
|
||||
(v2/*: any*/),
|
||||
(v3/*: any*/),
|
||||
(v4/*: any*/),
|
||||
(v5/*: any*/),
|
||||
(v6/*: any*/)
|
||||
],
|
||||
"kind": "Fragment",
|
||||
"metadata": null,
|
||||
"name": "LinkedControlsDialogControlsQuery",
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v7/*: any*/),
|
||||
"concreteType": null,
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"args": [
|
||||
(v8/*: any*/),
|
||||
(v9/*: any*/),
|
||||
(v10/*: any*/),
|
||||
(v11/*: any*/),
|
||||
(v12/*: any*/),
|
||||
{
|
||||
"kind": "Variable",
|
||||
"name": "order",
|
||||
"variableName": "order"
|
||||
}
|
||||
],
|
||||
"kind": "FragmentSpread",
|
||||
"name": "LinkedControlsDialogFragment"
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"type": "Query",
|
||||
"abstractKey": null
|
||||
},
|
||||
"kind": "Request",
|
||||
"operation": {
|
||||
"argumentDefinitions": [
|
||||
(v0/*: any*/),
|
||||
(v1/*: any*/),
|
||||
(v2/*: any*/),
|
||||
(v3/*: any*/),
|
||||
(v5/*: any*/),
|
||||
(v6/*: any*/),
|
||||
(v4/*: any*/)
|
||||
],
|
||||
"kind": "Operation",
|
||||
"name": "LinkedControlsDialogControlsQuery",
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v7/*: any*/),
|
||||
"concreteType": null,
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v13/*: any*/),
|
||||
(v14/*: any*/),
|
||||
{
|
||||
"kind": "InlineFragment",
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v15/*: any*/),
|
||||
"concreteType": "ControlConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "controls",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "ControlEdge",
|
||||
"kind": "LinkedField",
|
||||
"name": "edges",
|
||||
"plural": true,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Control",
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v14/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "name",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "sectionTitle",
|
||||
"storageKey": null
|
||||
},
|
||||
(v13/*: 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
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "hasPreviousPage",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "startCursor",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v15/*: any*/),
|
||||
"filters": [
|
||||
"orderBy",
|
||||
"filter"
|
||||
],
|
||||
"handle": "connection",
|
||||
"key": "LinkedControlsDialogControlsQuery_controls",
|
||||
"kind": "LinkedHandle",
|
||||
"name": "controls"
|
||||
}
|
||||
],
|
||||
"type": "Organization",
|
||||
"abstractKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "ececbd47b66b771cf95244ee81dae1f7",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "LinkedControlsDialogControlsQuery",
|
||||
"operationKind": "query",
|
||||
"text": "query LinkedControlsDialogControlsQuery(\n $after: CursorKey\n $before: CursorKey = null\n $filter: ControlFilter = null\n $first: Int = 1\n $last: Int = null\n $order: ControlOrder = null\n $id: ID!\n) {\n node(id: $id) {\n __typename\n ...LinkedControlsDialogFragment_4cFWzS\n id\n }\n}\n\nfragment LinkedControlsDialogFragment_4cFWzS on Organization {\n controls(first: $first, after: $after, last: $last, before: $before, orderBy: $order, filter: $filter) {\n edges {\n node {\n id\n name\n sectionTitle\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n id\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "b4dbf5c3271581e4317726870476da8d";
|
||||
|
||||
export default node;
|
||||
232
apps/console2/src/components/controls/__generated__/LinkedControlsDialogFragment.graphql.ts
generated
Normal file
232
apps/console2/src/components/controls/__generated__/LinkedControlsDialogFragment.graphql.ts
generated
Normal file
@@ -0,0 +1,232 @@
|
||||
/**
|
||||
* @generated SignedSource<<0be68327d7fa04dbceb53404ed1d5df4>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
|
||||
import { ReaderFragment } from 'relay-runtime';
|
||||
import { FragmentRefs } from "relay-runtime";
|
||||
export type LinkedControlsDialogFragment$data = {
|
||||
readonly controls: {
|
||||
readonly edges: ReadonlyArray<{
|
||||
readonly node: {
|
||||
readonly id: string;
|
||||
readonly name: string;
|
||||
readonly sectionTitle: string;
|
||||
};
|
||||
}>;
|
||||
};
|
||||
readonly id: string;
|
||||
readonly " $fragmentType": "LinkedControlsDialogFragment";
|
||||
};
|
||||
export type LinkedControlsDialogFragment$key = {
|
||||
readonly " $data"?: LinkedControlsDialogFragment$data;
|
||||
readonly " $fragmentSpreads": FragmentRefs<"LinkedControlsDialogFragment">;
|
||||
};
|
||||
|
||||
import LinkedControlsDialogControlsQuery_graphql from './LinkedControlsDialogControlsQuery.graphql';
|
||||
|
||||
const node: ReaderFragment = (function(){
|
||||
var v0 = [
|
||||
"controls"
|
||||
],
|
||||
v1 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "id",
|
||||
"storageKey": null
|
||||
};
|
||||
return {
|
||||
"argumentDefinitions": [
|
||||
{
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "after"
|
||||
},
|
||||
{
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "before"
|
||||
},
|
||||
{
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "filter"
|
||||
},
|
||||
{
|
||||
"defaultValue": 1,
|
||||
"kind": "LocalArgument",
|
||||
"name": "first"
|
||||
},
|
||||
{
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "last"
|
||||
},
|
||||
{
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "order"
|
||||
}
|
||||
],
|
||||
"kind": "Fragment",
|
||||
"metadata": {
|
||||
"connection": [
|
||||
{
|
||||
"count": null,
|
||||
"cursor": null,
|
||||
"direction": "bidirectional",
|
||||
"path": (v0/*: any*/)
|
||||
}
|
||||
],
|
||||
"refetch": {
|
||||
"connection": {
|
||||
"forward": {
|
||||
"count": "first",
|
||||
"cursor": "after"
|
||||
},
|
||||
"backward": {
|
||||
"count": "last",
|
||||
"cursor": "before"
|
||||
},
|
||||
"path": (v0/*: any*/)
|
||||
},
|
||||
"fragmentPathInResult": [
|
||||
"node"
|
||||
],
|
||||
"operation": LinkedControlsDialogControlsQuery_graphql,
|
||||
"identifierInfo": {
|
||||
"identifierField": "id",
|
||||
"identifierQueryVariableName": "id"
|
||||
}
|
||||
}
|
||||
},
|
||||
"name": "LinkedControlsDialogFragment",
|
||||
"selections": [
|
||||
{
|
||||
"alias": "controls",
|
||||
"args": [
|
||||
{
|
||||
"kind": "Variable",
|
||||
"name": "filter",
|
||||
"variableName": "filter"
|
||||
},
|
||||
{
|
||||
"kind": "Variable",
|
||||
"name": "orderBy",
|
||||
"variableName": "order"
|
||||
}
|
||||
],
|
||||
"concreteType": "ControlConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "__LinkedControlsDialogControlsQuery_controls_connection",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "ControlEdge",
|
||||
"kind": "LinkedField",
|
||||
"name": "edges",
|
||||
"plural": true,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Control",
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v1/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "name",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "sectionTitle",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "__typename",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"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
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "hasPreviousPage",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "startCursor",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
(v1/*: any*/)
|
||||
],
|
||||
"type": "Organization",
|
||||
"abstractKey": null
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "b4dbf5c3271581e4317726870476da8d";
|
||||
|
||||
export default node;
|
||||
239
apps/console2/src/components/controls/__generated__/LinkedControlsDialogQuery.graphql.ts
generated
Normal file
239
apps/console2/src/components/controls/__generated__/LinkedControlsDialogQuery.graphql.ts
generated
Normal file
@@ -0,0 +1,239 @@
|
||||
/**
|
||||
* @generated SignedSource<<ed40a9cdded98d98bf3d626f9d645d54>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
|
||||
import { ConcreteRequest } from 'relay-runtime';
|
||||
import { FragmentRefs } from "relay-runtime";
|
||||
export type LinkedControlsDialogQuery$variables = {
|
||||
organizationId: string;
|
||||
};
|
||||
export type LinkedControlsDialogQuery$data = {
|
||||
readonly organization: {
|
||||
readonly id: string;
|
||||
readonly " $fragmentSpreads": FragmentRefs<"LinkedControlsDialogFragment">;
|
||||
};
|
||||
};
|
||||
export type LinkedControlsDialogQuery = {
|
||||
response: LinkedControlsDialogQuery$data;
|
||||
variables: LinkedControlsDialogQuery$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 = [
|
||||
{
|
||||
"kind": "Literal",
|
||||
"name": "first",
|
||||
"value": 1
|
||||
}
|
||||
];
|
||||
return {
|
||||
"fragment": {
|
||||
"argumentDefinitions": (v0/*: any*/),
|
||||
"kind": "Fragment",
|
||||
"metadata": null,
|
||||
"name": "LinkedControlsDialogQuery",
|
||||
"selections": [
|
||||
{
|
||||
"alias": "organization",
|
||||
"args": (v1/*: any*/),
|
||||
"concreteType": null,
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v2/*: any*/),
|
||||
{
|
||||
"args": null,
|
||||
"kind": "FragmentSpread",
|
||||
"name": "LinkedControlsDialogFragment"
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"type": "Query",
|
||||
"abstractKey": null
|
||||
},
|
||||
"kind": "Request",
|
||||
"operation": {
|
||||
"argumentDefinitions": (v0/*: any*/),
|
||||
"kind": "Operation",
|
||||
"name": "LinkedControlsDialogQuery",
|
||||
"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": (v4/*: any*/),
|
||||
"concreteType": "ControlConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "controls",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "ControlEdge",
|
||||
"kind": "LinkedField",
|
||||
"name": "edges",
|
||||
"plural": true,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Control",
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v2/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "name",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "sectionTitle",
|
||||
"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
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "hasPreviousPage",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "startCursor",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": "controls(first:1)"
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v4/*: any*/),
|
||||
"filters": [
|
||||
"orderBy",
|
||||
"filter"
|
||||
],
|
||||
"handle": "connection",
|
||||
"key": "LinkedControlsDialogControlsQuery_controls",
|
||||
"kind": "LinkedHandle",
|
||||
"name": "controls"
|
||||
}
|
||||
],
|
||||
"type": "Organization",
|
||||
"abstractKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "1b0f918add0dcf173a84255896a3b46c",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "LinkedControlsDialogQuery",
|
||||
"operationKind": "query",
|
||||
"text": "query LinkedControlsDialogQuery(\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n id\n ...LinkedControlsDialogFragment\n }\n}\n\nfragment LinkedControlsDialogFragment on Organization {\n controls(first: 1) {\n edges {\n node {\n id\n name\n sectionTitle\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n id\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "1be60a2dc1efbd8992472862ca32910e";
|
||||
|
||||
export default node;
|
||||
@@ -50,7 +50,12 @@ export const useRiskForm = (riskKey?: RiskKey) => {
|
||||
...risk,
|
||||
ownerId: risk.owner?.id,
|
||||
}
|
||||
: {},
|
||||
: {
|
||||
inherentLikelihood: 3,
|
||||
inherentImpact: 3,
|
||||
residualLikelihood: 3,
|
||||
residualImpact: 3,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<660dce2bed93af9863423c7d15ce41a9>>
|
||||
* @generated SignedSource<<ca3d966d484c7e482511919e00a4cf70>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -63,7 +63,7 @@ v5 = [
|
||||
{
|
||||
"kind": "Literal",
|
||||
"name": "first",
|
||||
"value": 100
|
||||
"value": 20
|
||||
}
|
||||
],
|
||||
v6 = {
|
||||
@@ -83,29 +83,18 @@ v7 = {
|
||||
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
|
||||
}
|
||||
],
|
||||
"kind": "ScalarField",
|
||||
"name": "endCursor",
|
||||
"storageKey": null
|
||||
},
|
||||
v9 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "hasNextPage",
|
||||
"storageKey": null
|
||||
},
|
||||
v10 = {
|
||||
"kind": "ClientExtension",
|
||||
"selections": [
|
||||
{
|
||||
@@ -117,13 +106,26 @@ v9 = {
|
||||
}
|
||||
]
|
||||
},
|
||||
v10 = [
|
||||
v11 = [
|
||||
{
|
||||
"kind": "Literal",
|
||||
"name": "first",
|
||||
"value": 20
|
||||
"value": 100
|
||||
}
|
||||
];
|
||||
],
|
||||
v12 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "PageInfo",
|
||||
"kind": "LinkedField",
|
||||
"name": "pageInfo",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v8/*: any*/),
|
||||
(v9/*: any*/)
|
||||
],
|
||||
"storageKey": null
|
||||
};
|
||||
return {
|
||||
"fragment": {
|
||||
"argumentDefinitions": (v0/*: any*/),
|
||||
@@ -251,23 +253,52 @@ return {
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
(v8/*: any*/),
|
||||
(v9/*: any*/)
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "PageInfo",
|
||||
"kind": "LinkedField",
|
||||
"name": "pageInfo",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v8/*: any*/),
|
||||
(v9/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "hasPreviousPage",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "startCursor",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
(v10/*: any*/)
|
||||
],
|
||||
"storageKey": "controls(first:100)"
|
||||
"storageKey": "controls(first:20)"
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v5/*: any*/),
|
||||
"filters": null,
|
||||
"filters": [
|
||||
"orderBy",
|
||||
"filter"
|
||||
],
|
||||
"handle": "connection",
|
||||
"key": "DocumentDetailPage_controls",
|
||||
"key": "DocumentControlsTab_controls",
|
||||
"kind": "LinkedHandle",
|
||||
"name": "controls"
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v10/*: any*/),
|
||||
"args": (v5/*: any*/),
|
||||
"concreteType": "DocumentVersionConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "versions",
|
||||
@@ -327,7 +358,7 @@ return {
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v5/*: any*/),
|
||||
"args": (v11/*: any*/),
|
||||
"concreteType": "DocumentVersionSignatureConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "signatures",
|
||||
@@ -399,14 +430,14 @@ return {
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
(v8/*: any*/),
|
||||
(v9/*: any*/)
|
||||
(v12/*: any*/),
|
||||
(v10/*: any*/)
|
||||
],
|
||||
"storageKey": "signatures(first:100)"
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v5/*: any*/),
|
||||
"args": (v11/*: any*/),
|
||||
"filters": null,
|
||||
"handle": "connection",
|
||||
"key": "DocumentDetailPage_signatures",
|
||||
@@ -441,14 +472,14 @@ return {
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
(v8/*: any*/),
|
||||
(v9/*: any*/)
|
||||
(v12/*: any*/),
|
||||
(v10/*: any*/)
|
||||
],
|
||||
"storageKey": "versions(first:20)"
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v10/*: any*/),
|
||||
"args": (v5/*: any*/),
|
||||
"filters": null,
|
||||
"handle": "connection",
|
||||
"key": "DocumentDetailPage_versions",
|
||||
@@ -465,12 +496,12 @@ return {
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "9660b8b2cc438fd732fcf0eb8265996b",
|
||||
"cacheID": "010d49252c4c3098beb66f3550885cfc",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "DocumentGraphNodeQuery",
|
||||
"operationKind": "query",
|
||||
"text": "query DocumentGraphNodeQuery(\n $documentId: ID!\n) {\n node(id: $documentId) {\n __typename\n ... on Document {\n ...DocumentDetailPageDocumentFragment\n }\n id\n }\n}\n\nfragment DocumentDetailPageDocumentFragment on Document {\n id\n title\n owner {\n id\n fullName\n }\n controls(first: 100) {\n edges {\n node {\n id\n ...LinkedControlsCardFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\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 ...DocumentSignaturesDialog_signature\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n ...DocumentVersionHistoryDialogFragment\n ...DocumentSignaturesDialog_version\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n}\n\nfragment DocumentSignaturesDialog_signature on DocumentVersionSignature {\n id\n state\n signedAt\n requestedAt\n signedBy {\n fullName\n primaryEmailAddress\n id\n }\n}\n\nfragment DocumentSignaturesDialog_version on DocumentVersion {\n version\n status\n publishedAt\n updatedAt\n}\n\nfragment DocumentVersionHistoryDialogFragment on DocumentVersion {\n id\n version\n status\n content\n changelog\n publishedAt\n updatedAt\n publishedBy {\n fullName\n id\n }\n}\n\nfragment LinkedControlsCardFragment on Control {\n id\n name\n sectionTitle\n framework {\n name\n id\n }\n}\n"
|
||||
"text": "query DocumentGraphNodeQuery(\n $documentId: ID!\n) {\n node(id: $documentId) {\n __typename\n ... on Document {\n ...DocumentDetailPageDocumentFragment\n }\n id\n }\n}\n\nfragment DocumentControlsTabFragment on Document {\n id\n controls(first: 20) {\n edges {\n node {\n id\n ...LinkedControlsCardFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n}\n\nfragment DocumentDetailPageDocumentFragment on Document {\n id\n title\n owner {\n id\n fullName\n }\n ...DocumentControlsTabFragment\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 ...DocumentSignaturesDialog_signature\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n ...DocumentVersionHistoryDialogFragment\n ...DocumentSignaturesDialog_version\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n}\n\nfragment DocumentSignaturesDialog_signature on DocumentVersionSignature {\n id\n state\n signedAt\n requestedAt\n signedBy {\n fullName\n primaryEmailAddress\n id\n }\n}\n\nfragment DocumentSignaturesDialog_version on DocumentVersion {\n version\n status\n publishedAt\n updatedAt\n}\n\nfragment DocumentVersionHistoryDialogFragment on DocumentVersion {\n id\n version\n status\n content\n changelog\n publishedAt\n updatedAt\n publishedBy {\n fullName\n id\n }\n}\n\nfragment LinkedControlsCardFragment on Control {\n id\n name\n sectionTitle\n framework {\n name\n id\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<e7d82cc2843376766d45bdaac45f3b13>>
|
||||
* @generated SignedSource<<19b79280f8cf27e7e36a700ae2ea003a>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -140,6 +140,40 @@ v13 = {
|
||||
]
|
||||
},
|
||||
v14 = [
|
||||
{
|
||||
"kind": "Literal",
|
||||
"name": "first",
|
||||
"value": 20
|
||||
}
|
||||
],
|
||||
v15 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "PageInfo",
|
||||
"kind": "LinkedField",
|
||||
"name": "pageInfo",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v10/*: any*/),
|
||||
(v11/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "hasPreviousPage",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "startCursor",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
v16 = [
|
||||
{
|
||||
"kind": "Literal",
|
||||
"name": "first",
|
||||
@@ -387,7 +421,7 @@ return {
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v8/*: any*/),
|
||||
"args": (v14/*: any*/),
|
||||
"concreteType": "ControlConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "controls",
|
||||
@@ -439,23 +473,26 @@ return {
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
(v12/*: any*/),
|
||||
(v15/*: any*/),
|
||||
(v13/*: any*/)
|
||||
],
|
||||
"storageKey": "controls(first:100)"
|
||||
"storageKey": "controls(first:20)"
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v8/*: any*/),
|
||||
"filters": null,
|
||||
"args": (v14/*: any*/),
|
||||
"filters": [
|
||||
"orderBy",
|
||||
"filter"
|
||||
],
|
||||
"handle": "connection",
|
||||
"key": "MeasureControlsTabFragment_controls",
|
||||
"key": "MeasureControlsTab_controls",
|
||||
"kind": "LinkedHandle",
|
||||
"name": "controls"
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v14/*: any*/),
|
||||
"args": (v16/*: any*/),
|
||||
"concreteType": "EvidenceConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "evidences",
|
||||
@@ -528,40 +565,14 @@ return {
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "PageInfo",
|
||||
"kind": "LinkedField",
|
||||
"name": "pageInfo",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v10/*: any*/),
|
||||
(v11/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "hasPreviousPage",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "startCursor",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
(v15/*: any*/),
|
||||
(v13/*: any*/)
|
||||
],
|
||||
"storageKey": "evidences(first:50)"
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v14/*: any*/),
|
||||
"args": (v16/*: any*/),
|
||||
"filters": [
|
||||
"orderBy"
|
||||
],
|
||||
@@ -580,12 +591,12 @@ return {
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "b5f77889cfcec3b09ae7f6707c65200f",
|
||||
"cacheID": "22ec6d5ae51e192283ffe91b9edc39d0",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "MeasureGraphNodeQuery",
|
||||
"operationKind": "query",
|
||||
"text": "query MeasureGraphNodeQuery(\n $measureId: ID!\n) {\n node(id: $measureId) {\n __typename\n ... on Measure {\n id\n name\n description\n state\n category\n ...MeasureRisksTabFragment\n ...MeasureTasksTabFragment\n ...MeasureControlsTabFragment\n ...MeasureFormDialogMeasureFragment\n ...MeasureEvidencesTabFragment\n }\n id\n }\n}\n\nfragment LinkedControlsCardFragment on Control {\n id\n name\n sectionTitle\n framework {\n name\n id\n }\n}\n\nfragment LinkedRisksCardFragment on Risk {\n id\n name\n inherentRiskScore\n residualRiskScore\n}\n\nfragment MeasureControlsTabFragment on Measure {\n id\n controls(first: 100) {\n edges {\n node {\n id\n ...LinkedControlsCardFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n}\n\nfragment MeasureEvidencesTabFragment on Measure {\n id\n evidences(first: 50) {\n edges {\n node {\n id\n ...MeasureEvidencesTabFragment_evidence\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n}\n\nfragment MeasureEvidencesTabFragment_evidence on Evidence {\n id\n filename\n size\n type\n createdAt\n fileUrl\n mimeType\n}\n\nfragment MeasureFormDialogMeasureFragment on Measure {\n id\n description\n name\n category\n state\n}\n\nfragment MeasureRisksTabFragment on Measure {\n id\n risks(first: 100) {\n edges {\n node {\n id\n ...LinkedRisksCardFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n}\n\nfragment MeasureTasksTabFragment on Measure {\n tasks(first: 100) {\n edges {\n node {\n id\n name\n state\n description\n ...TaskFormDialogFragment\n assignedTo {\n id\n fullName\n }\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n}\n\nfragment TaskFormDialogFragment on Task {\n id\n description\n name\n state\n timeEstimate\n deadline\n assignedTo {\n id\n }\n measure {\n id\n }\n}\n"
|
||||
"text": "query MeasureGraphNodeQuery(\n $measureId: ID!\n) {\n node(id: $measureId) {\n __typename\n ... on Measure {\n id\n name\n description\n state\n category\n ...MeasureRisksTabFragment\n ...MeasureTasksTabFragment\n ...MeasureControlsTabFragment\n ...MeasureFormDialogMeasureFragment\n ...MeasureEvidencesTabFragment\n }\n id\n }\n}\n\nfragment LinkedControlsCardFragment on Control {\n id\n name\n sectionTitle\n framework {\n name\n id\n }\n}\n\nfragment LinkedRisksCardFragment on Risk {\n id\n name\n inherentRiskScore\n residualRiskScore\n}\n\nfragment MeasureControlsTabFragment on Measure {\n id\n controls(first: 20) {\n edges {\n node {\n id\n ...LinkedControlsCardFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n}\n\nfragment MeasureEvidencesTabFragment on Measure {\n id\n evidences(first: 50) {\n edges {\n node {\n id\n ...MeasureEvidencesTabFragment_evidence\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n}\n\nfragment MeasureEvidencesTabFragment_evidence on Evidence {\n id\n filename\n size\n type\n createdAt\n fileUrl\n mimeType\n}\n\nfragment MeasureFormDialogMeasureFragment on Measure {\n id\n description\n name\n category\n state\n}\n\nfragment MeasureRisksTabFragment on Measure {\n id\n risks(first: 100) {\n edges {\n node {\n id\n ...LinkedRisksCardFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n}\n\nfragment MeasureTasksTabFragment on Measure {\n tasks(first: 100) {\n edges {\n node {\n id\n name\n state\n description\n ...TaskFormDialogFragment\n assignedTo {\n id\n fullName\n }\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n}\n\nfragment TaskFormDialogFragment on Task {\n id\n description\n name\n state\n timeEstimate\n deadline\n assignedTo {\n id\n }\n measure {\n id\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
@@ -43,6 +43,8 @@ import UpdateVersionDialog from "./dialogs/UpdateVersionDialog";
|
||||
import { useRef } from "react";
|
||||
import { DocumentVersionHistoryDialog } from "./dialogs/DocumentVersionHistoryDialog";
|
||||
import { DocumentSignaturesDialog } from "./dialogs/DocumentSignaturesDialog";
|
||||
import { controlsFragment } from "./tabs/DocumentControlsTab";
|
||||
import type { DocumentControlsTabFragment$key } from "./tabs/__generated__/DocumentControlsTabFragment.graphql";
|
||||
|
||||
type Props = {
|
||||
queryRef: PreloadedQuery<DocumentGraphNodeQuery>;
|
||||
@@ -56,15 +58,7 @@ const documentFragment = graphql`
|
||||
id
|
||||
fullName
|
||||
}
|
||||
controls(first: 100) @connection(key: "DocumentDetailPage_controls") {
|
||||
__id
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
...LinkedControlsCardFragment
|
||||
}
|
||||
}
|
||||
}
|
||||
...DocumentControlsTabFragment
|
||||
versions(first: 20) @connection(key: "DocumentDetailPage_versions") {
|
||||
__id
|
||||
edges {
|
||||
@@ -182,6 +176,10 @@ export default function DocumentDetailPage(props: Props) {
|
||||
};
|
||||
|
||||
const updateDialogRef = useRef<{ open: () => void }>(null);
|
||||
const controls = useFragment(
|
||||
controlsFragment,
|
||||
document as DocumentControlsTabFragment$key
|
||||
).controls;
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -254,7 +252,7 @@ export default function DocumentDetailPage(props: Props) {
|
||||
to={`/organizations/${organizationId}/documents/${document.id}/controls`}
|
||||
>
|
||||
{__("Controls")}
|
||||
<TabBadge>{document.controls.edges.length}</TabBadge>
|
||||
<TabBadge>{controls.edges.length}</TabBadge>
|
||||
</TabLink>
|
||||
</Tabs>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<72689566d977ab4171c75ba9ce2c62f4>>
|
||||
* @generated SignedSource<<6c0262b14b79c61016ad404fab7a1da0>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -13,15 +13,6 @@ export type DocumentStatus = "DRAFT" | "PUBLISHED";
|
||||
export type DocumentVersionSignatureState = "REQUESTED" | "SIGNED";
|
||||
import { FragmentRefs } from "relay-runtime";
|
||||
export type DocumentDetailPageDocumentFragment$data = {
|
||||
readonly controls: {
|
||||
readonly __id: string;
|
||||
readonly edges: ReadonlyArray<{
|
||||
readonly node: {
|
||||
readonly id: string;
|
||||
readonly " $fragmentSpreads": FragmentRefs<"LinkedControlsCardFragment">;
|
||||
};
|
||||
}>;
|
||||
};
|
||||
readonly id: string;
|
||||
readonly owner: {
|
||||
readonly fullName: string;
|
||||
@@ -55,6 +46,7 @@ export type DocumentDetailPageDocumentFragment$data = {
|
||||
};
|
||||
}>;
|
||||
};
|
||||
readonly " $fragmentSpreads": FragmentRefs<"DocumentControlsTabFragment">;
|
||||
readonly " $fragmentType": "DocumentDetailPageDocumentFragment";
|
||||
};
|
||||
export type DocumentDetailPageDocumentFragment$key = {
|
||||
@@ -126,14 +118,6 @@ return {
|
||||
"kind": "Fragment",
|
||||
"metadata": {
|
||||
"connection": [
|
||||
{
|
||||
"count": null,
|
||||
"cursor": null,
|
||||
"direction": "forward",
|
||||
"path": [
|
||||
"controls"
|
||||
]
|
||||
},
|
||||
{
|
||||
"count": null,
|
||||
"cursor": null,
|
||||
@@ -180,47 +164,9 @@ return {
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": "controls",
|
||||
"args": null,
|
||||
"concreteType": "ControlConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "__DocumentDetailPage_controls_connection",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "ControlEdge",
|
||||
"kind": "LinkedField",
|
||||
"name": "edges",
|
||||
"plural": true,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Control",
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v0/*: any*/),
|
||||
{
|
||||
"args": null,
|
||||
"kind": "FragmentSpread",
|
||||
"name": "LinkedControlsCardFragment"
|
||||
},
|
||||
(v1/*: any*/)
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
(v2/*: any*/)
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
(v3/*: any*/),
|
||||
(v4/*: any*/)
|
||||
],
|
||||
"storageKey": null
|
||||
"kind": "FragmentSpread",
|
||||
"name": "DocumentControlsTabFragment"
|
||||
},
|
||||
{
|
||||
"alias": "versions",
|
||||
@@ -373,6 +319,6 @@ return {
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "df93b2fdd0ceea0637ddac2e4186181c";
|
||||
(node as any).hash = "02b0af2263f78304097136c2466be18c";
|
||||
|
||||
export default node;
|
||||
|
||||
@@ -1,8 +1,39 @@
|
||||
import { LinkedControlsCard } from "/components/controls/LinkedControlsCard";
|
||||
import { useOutletContext } from "react-router";
|
||||
import type { DocumentDetailPageDocumentFragment$data } from "../__generated__/DocumentDetailPageDocumentFragment.graphql";
|
||||
import { graphql } from "relay-runtime";
|
||||
import { useMutation } from "react-relay";
|
||||
import { useMutation, useRefetchableFragment } from "react-relay";
|
||||
import type { DocumentControlsTabFragment$key } from "./__generated__/DocumentControlsTabFragment.graphql";
|
||||
|
||||
export const controlsFragment = graphql`
|
||||
fragment DocumentControlsTabFragment on Document
|
||||
@argumentDefinitions(
|
||||
first: { type: "Int", defaultValue: 20 }
|
||||
after: { type: "CursorKey" }
|
||||
last: { type: "Int", defaultValue: null }
|
||||
before: { type: "CursorKey", defaultValue: null }
|
||||
order: { type: "ControlOrder", defaultValue: null }
|
||||
filter: { type: "ControlFilter", defaultValue: null }
|
||||
)
|
||||
@refetchable(queryName: "DocumentControlsTabControlsQuery") {
|
||||
id
|
||||
controls(
|
||||
first: $first
|
||||
after: $after
|
||||
last: $last
|
||||
before: $before
|
||||
orderBy: $order
|
||||
filter: $filter
|
||||
) @connection(key: "DocumentControlsTab_controls") {
|
||||
__id
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
...LinkedControlsCardFragment
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const detachControlMutation = graphql`
|
||||
mutation DocumentControlsTab_detachControlMutation(
|
||||
@@ -15,19 +46,40 @@ const detachControlMutation = graphql`
|
||||
}
|
||||
`;
|
||||
|
||||
const attachControlMutation = graphql`
|
||||
mutation DocumentControlsTab_attachControlMutation(
|
||||
$input: CreateControlDocumentMappingInput!
|
||||
$connections: [ID!]!
|
||||
) {
|
||||
createControlDocumentMapping(input: $input) {
|
||||
controlEdge @prependEdge(connections: $connections) {
|
||||
node {
|
||||
id
|
||||
...LinkedControlsCardFragment
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export default function DocumentControlsTab() {
|
||||
const { document } = useOutletContext<{
|
||||
document: DocumentDetailPageDocumentFragment$data;
|
||||
document: DocumentControlsTabFragment$key;
|
||||
}>();
|
||||
const controls = document.controls.edges.map((edge) => edge.node);
|
||||
const [detachControl] = useMutation(detachControlMutation);
|
||||
console.log(controls.map((c) => c.id));
|
||||
const [data, refetch] = useRefetchableFragment(controlsFragment, document);
|
||||
const controls = data.controls.edges.map((edge) => edge.node);
|
||||
const [detachControl, isDetaching] = useMutation(detachControlMutation);
|
||||
const [attachControl, isAttaching] = useMutation(attachControlMutation);
|
||||
const isLoading = isDetaching || isAttaching;
|
||||
return (
|
||||
<LinkedControlsCard
|
||||
disabled={isLoading}
|
||||
controls={controls}
|
||||
params={{ documentId: document.id }}
|
||||
connectionId={document.controls.__id}
|
||||
params={{ documentId: data.id }}
|
||||
connectionId={data.controls.__id}
|
||||
onDetach={detachControl}
|
||||
onAttach={attachControl}
|
||||
refetch={refetch}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,363 @@
|
||||
/**
|
||||
* @generated SignedSource<<bc26166734fbdf91c377510fdb9dbfd6>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
|
||||
import { ConcreteRequest } from 'relay-runtime';
|
||||
import { FragmentRefs } from "relay-runtime";
|
||||
export type ControlOrderField = "CREATED_AT" | "SECTION_TITLE";
|
||||
export type OrderDirection = "ASC" | "DESC";
|
||||
export type ControlFilter = {
|
||||
query?: string | null | undefined;
|
||||
};
|
||||
export type ControlOrder = {
|
||||
direction: OrderDirection;
|
||||
field: ControlOrderField;
|
||||
};
|
||||
export type DocumentControlsTabControlsQuery$variables = {
|
||||
after?: any | null | undefined;
|
||||
before?: any | null | undefined;
|
||||
filter?: ControlFilter | null | undefined;
|
||||
first?: number | null | undefined;
|
||||
id: string;
|
||||
last?: number | null | undefined;
|
||||
order?: ControlOrder | null | undefined;
|
||||
};
|
||||
export type DocumentControlsTabControlsQuery$data = {
|
||||
readonly node: {
|
||||
readonly " $fragmentSpreads": FragmentRefs<"DocumentControlsTabFragment">;
|
||||
};
|
||||
};
|
||||
export type DocumentControlsTabControlsQuery = {
|
||||
response: DocumentControlsTabControlsQuery$data;
|
||||
variables: DocumentControlsTabControlsQuery$variables;
|
||||
};
|
||||
|
||||
const node: ConcreteRequest = (function(){
|
||||
var v0 = {
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "after"
|
||||
},
|
||||
v1 = {
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "before"
|
||||
},
|
||||
v2 = {
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "filter"
|
||||
},
|
||||
v3 = {
|
||||
"defaultValue": 20,
|
||||
"kind": "LocalArgument",
|
||||
"name": "first"
|
||||
},
|
||||
v4 = {
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "id"
|
||||
},
|
||||
v5 = {
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "last"
|
||||
},
|
||||
v6 = {
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "order"
|
||||
},
|
||||
v7 = [
|
||||
{
|
||||
"kind": "Variable",
|
||||
"name": "id",
|
||||
"variableName": "id"
|
||||
}
|
||||
],
|
||||
v8 = {
|
||||
"kind": "Variable",
|
||||
"name": "after",
|
||||
"variableName": "after"
|
||||
},
|
||||
v9 = {
|
||||
"kind": "Variable",
|
||||
"name": "before",
|
||||
"variableName": "before"
|
||||
},
|
||||
v10 = {
|
||||
"kind": "Variable",
|
||||
"name": "filter",
|
||||
"variableName": "filter"
|
||||
},
|
||||
v11 = {
|
||||
"kind": "Variable",
|
||||
"name": "first",
|
||||
"variableName": "first"
|
||||
},
|
||||
v12 = {
|
||||
"kind": "Variable",
|
||||
"name": "last",
|
||||
"variableName": "last"
|
||||
},
|
||||
v13 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "__typename",
|
||||
"storageKey": null
|
||||
},
|
||||
v14 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "id",
|
||||
"storageKey": null
|
||||
},
|
||||
v15 = [
|
||||
(v8/*: any*/),
|
||||
(v9/*: any*/),
|
||||
(v10/*: any*/),
|
||||
(v11/*: any*/),
|
||||
(v12/*: any*/),
|
||||
{
|
||||
"kind": "Variable",
|
||||
"name": "orderBy",
|
||||
"variableName": "order"
|
||||
}
|
||||
],
|
||||
v16 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "name",
|
||||
"storageKey": null
|
||||
};
|
||||
return {
|
||||
"fragment": {
|
||||
"argumentDefinitions": [
|
||||
(v0/*: any*/),
|
||||
(v1/*: any*/),
|
||||
(v2/*: any*/),
|
||||
(v3/*: any*/),
|
||||
(v4/*: any*/),
|
||||
(v5/*: any*/),
|
||||
(v6/*: any*/)
|
||||
],
|
||||
"kind": "Fragment",
|
||||
"metadata": null,
|
||||
"name": "DocumentControlsTabControlsQuery",
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v7/*: any*/),
|
||||
"concreteType": null,
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"args": [
|
||||
(v8/*: any*/),
|
||||
(v9/*: any*/),
|
||||
(v10/*: any*/),
|
||||
(v11/*: any*/),
|
||||
(v12/*: any*/),
|
||||
{
|
||||
"kind": "Variable",
|
||||
"name": "order",
|
||||
"variableName": "order"
|
||||
}
|
||||
],
|
||||
"kind": "FragmentSpread",
|
||||
"name": "DocumentControlsTabFragment"
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"type": "Query",
|
||||
"abstractKey": null
|
||||
},
|
||||
"kind": "Request",
|
||||
"operation": {
|
||||
"argumentDefinitions": [
|
||||
(v0/*: any*/),
|
||||
(v1/*: any*/),
|
||||
(v2/*: any*/),
|
||||
(v3/*: any*/),
|
||||
(v5/*: any*/),
|
||||
(v6/*: any*/),
|
||||
(v4/*: any*/)
|
||||
],
|
||||
"kind": "Operation",
|
||||
"name": "DocumentControlsTabControlsQuery",
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v7/*: any*/),
|
||||
"concreteType": null,
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v13/*: any*/),
|
||||
(v14/*: any*/),
|
||||
{
|
||||
"kind": "InlineFragment",
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v15/*: any*/),
|
||||
"concreteType": "ControlConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "controls",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "ControlEdge",
|
||||
"kind": "LinkedField",
|
||||
"name": "edges",
|
||||
"plural": true,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Control",
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v14/*: any*/),
|
||||
(v16/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "sectionTitle",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Framework",
|
||||
"kind": "LinkedField",
|
||||
"name": "framework",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v16/*: any*/),
|
||||
(v14/*: any*/)
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
(v13/*: 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
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "hasPreviousPage",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "startCursor",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"kind": "ClientExtension",
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "__id",
|
||||
"storageKey": null
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v15/*: any*/),
|
||||
"filters": [
|
||||
"orderBy",
|
||||
"filter"
|
||||
],
|
||||
"handle": "connection",
|
||||
"key": "DocumentControlsTab_controls",
|
||||
"kind": "LinkedHandle",
|
||||
"name": "controls"
|
||||
}
|
||||
],
|
||||
"type": "Document",
|
||||
"abstractKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "9db5367f71ee867e25df15eb9babf4ce",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "DocumentControlsTabControlsQuery",
|
||||
"operationKind": "query",
|
||||
"text": "query DocumentControlsTabControlsQuery(\n $after: CursorKey\n $before: CursorKey = null\n $filter: ControlFilter = null\n $first: Int = 20\n $last: Int = null\n $order: ControlOrder = null\n $id: ID!\n) {\n node(id: $id) {\n __typename\n ...DocumentControlsTabFragment_4cFWzS\n id\n }\n}\n\nfragment DocumentControlsTabFragment_4cFWzS on Document {\n id\n controls(first: $first, after: $after, last: $last, before: $before, orderBy: $order, filter: $filter) {\n edges {\n node {\n id\n ...LinkedControlsCardFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n}\n\nfragment LinkedControlsCardFragment on Control {\n id\n name\n sectionTitle\n framework {\n name\n id\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "c1b6d5212b3fa33f60c02ddee32d5cea";
|
||||
|
||||
export default node;
|
||||
@@ -0,0 +1,235 @@
|
||||
/**
|
||||
* @generated SignedSource<<aad16d17ffa1259b4e99ceb4e583df5f>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
|
||||
import { ReaderFragment } from 'relay-runtime';
|
||||
import { FragmentRefs } from "relay-runtime";
|
||||
export type DocumentControlsTabFragment$data = {
|
||||
readonly controls: {
|
||||
readonly __id: string;
|
||||
readonly edges: ReadonlyArray<{
|
||||
readonly node: {
|
||||
readonly id: string;
|
||||
readonly " $fragmentSpreads": FragmentRefs<"LinkedControlsCardFragment">;
|
||||
};
|
||||
}>;
|
||||
};
|
||||
readonly id: string;
|
||||
readonly " $fragmentType": "DocumentControlsTabFragment";
|
||||
};
|
||||
export type DocumentControlsTabFragment$key = {
|
||||
readonly " $data"?: DocumentControlsTabFragment$data;
|
||||
readonly " $fragmentSpreads": FragmentRefs<"DocumentControlsTabFragment">;
|
||||
};
|
||||
|
||||
import DocumentControlsTabControlsQuery_graphql from './DocumentControlsTabControlsQuery.graphql';
|
||||
|
||||
const node: ReaderFragment = (function(){
|
||||
var v0 = [
|
||||
"controls"
|
||||
],
|
||||
v1 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "id",
|
||||
"storageKey": null
|
||||
};
|
||||
return {
|
||||
"argumentDefinitions": [
|
||||
{
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "after"
|
||||
},
|
||||
{
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "before"
|
||||
},
|
||||
{
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "filter"
|
||||
},
|
||||
{
|
||||
"defaultValue": 20,
|
||||
"kind": "LocalArgument",
|
||||
"name": "first"
|
||||
},
|
||||
{
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "last"
|
||||
},
|
||||
{
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "order"
|
||||
}
|
||||
],
|
||||
"kind": "Fragment",
|
||||
"metadata": {
|
||||
"connection": [
|
||||
{
|
||||
"count": null,
|
||||
"cursor": null,
|
||||
"direction": "bidirectional",
|
||||
"path": (v0/*: any*/)
|
||||
}
|
||||
],
|
||||
"refetch": {
|
||||
"connection": {
|
||||
"forward": {
|
||||
"count": "first",
|
||||
"cursor": "after"
|
||||
},
|
||||
"backward": {
|
||||
"count": "last",
|
||||
"cursor": "before"
|
||||
},
|
||||
"path": (v0/*: any*/)
|
||||
},
|
||||
"fragmentPathInResult": [
|
||||
"node"
|
||||
],
|
||||
"operation": DocumentControlsTabControlsQuery_graphql,
|
||||
"identifierInfo": {
|
||||
"identifierField": "id",
|
||||
"identifierQueryVariableName": "id"
|
||||
}
|
||||
}
|
||||
},
|
||||
"name": "DocumentControlsTabFragment",
|
||||
"selections": [
|
||||
(v1/*: any*/),
|
||||
{
|
||||
"alias": "controls",
|
||||
"args": [
|
||||
{
|
||||
"kind": "Variable",
|
||||
"name": "filter",
|
||||
"variableName": "filter"
|
||||
},
|
||||
{
|
||||
"kind": "Variable",
|
||||
"name": "orderBy",
|
||||
"variableName": "order"
|
||||
}
|
||||
],
|
||||
"concreteType": "ControlConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "__DocumentControlsTab_controls_connection",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "ControlEdge",
|
||||
"kind": "LinkedField",
|
||||
"name": "edges",
|
||||
"plural": true,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Control",
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v1/*: any*/),
|
||||
{
|
||||
"args": null,
|
||||
"kind": "FragmentSpread",
|
||||
"name": "LinkedControlsCardFragment"
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "__typename",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"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
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "hasPreviousPage",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "startCursor",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"kind": "ClientExtension",
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "__id",
|
||||
"storageKey": null
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"type": "Document",
|
||||
"abstractKey": null
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "c1b6d5212b3fa33f60c02ddee32d5cea";
|
||||
|
||||
export default node;
|
||||
@@ -0,0 +1,216 @@
|
||||
/**
|
||||
* @generated SignedSource<<74725fda85d702538289d6a97ef17399>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
|
||||
import { ConcreteRequest } from 'relay-runtime';
|
||||
import { FragmentRefs } from "relay-runtime";
|
||||
export type CreateControlDocumentMappingInput = {
|
||||
controlId: string;
|
||||
documentId: string;
|
||||
};
|
||||
export type DocumentControlsTab_attachControlMutation$variables = {
|
||||
connections: ReadonlyArray<string>;
|
||||
input: CreateControlDocumentMappingInput;
|
||||
};
|
||||
export type DocumentControlsTab_attachControlMutation$data = {
|
||||
readonly createControlDocumentMapping: {
|
||||
readonly controlEdge: {
|
||||
readonly node: {
|
||||
readonly id: string;
|
||||
readonly " $fragmentSpreads": FragmentRefs<"LinkedControlsCardFragment">;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
export type DocumentControlsTab_attachControlMutation = {
|
||||
response: DocumentControlsTab_attachControlMutation$data;
|
||||
variables: DocumentControlsTab_attachControlMutation$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": "name",
|
||||
"storageKey": null
|
||||
};
|
||||
return {
|
||||
"fragment": {
|
||||
"argumentDefinitions": [
|
||||
(v0/*: any*/),
|
||||
(v1/*: any*/)
|
||||
],
|
||||
"kind": "Fragment",
|
||||
"metadata": null,
|
||||
"name": "DocumentControlsTab_attachControlMutation",
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v2/*: any*/),
|
||||
"concreteType": "CreateControlDocumentMappingPayload",
|
||||
"kind": "LinkedField",
|
||||
"name": "createControlDocumentMapping",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "ControlEdge",
|
||||
"kind": "LinkedField",
|
||||
"name": "controlEdge",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Control",
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v3/*: any*/),
|
||||
{
|
||||
"args": null,
|
||||
"kind": "FragmentSpread",
|
||||
"name": "LinkedControlsCardFragment"
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"type": "Mutation",
|
||||
"abstractKey": null
|
||||
},
|
||||
"kind": "Request",
|
||||
"operation": {
|
||||
"argumentDefinitions": [
|
||||
(v1/*: any*/),
|
||||
(v0/*: any*/)
|
||||
],
|
||||
"kind": "Operation",
|
||||
"name": "DocumentControlsTab_attachControlMutation",
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v2/*: any*/),
|
||||
"concreteType": "CreateControlDocumentMappingPayload",
|
||||
"kind": "LinkedField",
|
||||
"name": "createControlDocumentMapping",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "ControlEdge",
|
||||
"kind": "LinkedField",
|
||||
"name": "controlEdge",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Control",
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v3/*: any*/),
|
||||
(v4/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "sectionTitle",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Framework",
|
||||
"kind": "LinkedField",
|
||||
"name": "framework",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v4/*: any*/),
|
||||
(v3/*: any*/)
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"filters": null,
|
||||
"handle": "prependEdge",
|
||||
"key": "",
|
||||
"kind": "LinkedHandle",
|
||||
"name": "controlEdge",
|
||||
"handleArgs": [
|
||||
{
|
||||
"kind": "Variable",
|
||||
"name": "connections",
|
||||
"variableName": "connections"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "d283633e6a7ca3af074af6a8b716fc1c",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "DocumentControlsTab_attachControlMutation",
|
||||
"operationKind": "mutation",
|
||||
"text": "mutation DocumentControlsTab_attachControlMutation(\n $input: CreateControlDocumentMappingInput!\n) {\n createControlDocumentMapping(input: $input) {\n controlEdge {\n node {\n id\n ...LinkedControlsCardFragment\n }\n }\n }\n}\n\nfragment LinkedControlsCardFragment on Control {\n id\n name\n sectionTitle\n framework {\n name\n id\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "273f0d619a2be7df7451e7354c53315a";
|
||||
|
||||
export default node;
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
Option,
|
||||
PropertyRow,
|
||||
Select,
|
||||
TabBadge,
|
||||
TabLink,
|
||||
Tabs,
|
||||
useConfirm,
|
||||
@@ -23,6 +24,7 @@ import {
|
||||
import { useTranslate } from "@probo/i18n";
|
||||
import {
|
||||
ConnectionHandler,
|
||||
useFragment,
|
||||
usePreloadedQuery,
|
||||
type PreloadedQuery,
|
||||
} from "react-relay";
|
||||
@@ -38,6 +40,14 @@ import { getMeasureStateLabel, measureStates, slugify } from "@probo/helpers";
|
||||
import MeasureFormDialog from "./dialog/MeasureFormDialog";
|
||||
import { sprintf } from "@probo/helpers";
|
||||
import { useNavigate } from "react-router";
|
||||
import { tasksFragment } from "./tabs/MeasureTasksTab";
|
||||
import type { MeasureTasksTabFragment$key } from "./tabs/__generated__/MeasureTasksTabFragment.graphql";
|
||||
import { evidencesFragment } from "./tabs/MeasureEvidencesTab";
|
||||
import type { MeasureEvidencesTabFragment$key } from "./tabs/__generated__/MeasureEvidencesTabFragment.graphql";
|
||||
import { controlsFragment } from "./tabs/MeasureControlsTab";
|
||||
import type { MeasureControlsTabFragment$key } from "./tabs/__generated__/MeasureControlsTabFragment.graphql";
|
||||
import { risksFragment } from "./tabs/MeasureRisksTab";
|
||||
import type { MeasureRisksTabFragment$key } from "./tabs/__generated__/MeasureRisksTabFragment.graphql";
|
||||
|
||||
type Props = {
|
||||
queryRef: PreloadedQuery<MeasureGraphNodeQuery>;
|
||||
@@ -60,6 +70,23 @@ export default function MeasureDetailPage(props: Props) {
|
||||
);
|
||||
}
|
||||
|
||||
const tasksCount = useFragment(
|
||||
tasksFragment,
|
||||
measure as MeasureTasksTabFragment$key
|
||||
).tasks.edges.length;
|
||||
const evidencesCount = useFragment(
|
||||
evidencesFragment,
|
||||
measure as MeasureEvidencesTabFragment$key
|
||||
).evidences.edges.length;
|
||||
const controlsCount = useFragment(
|
||||
controlsFragment,
|
||||
measure as MeasureControlsTabFragment$key
|
||||
).controls.edges.length;
|
||||
const risksCount = useFragment(
|
||||
risksFragment,
|
||||
measure as MeasureRisksTabFragment$key
|
||||
).risks.edges.length;
|
||||
|
||||
const onDelete = () => {
|
||||
const connectionId = ConnectionHandler.getConnectionID(
|
||||
organizationId,
|
||||
@@ -157,24 +184,28 @@ export default function MeasureDetailPage(props: Props) {
|
||||
>
|
||||
<IconPageTextLine size={20} />
|
||||
{__("Evidences")}
|
||||
{evidencesCount > 0 && <TabBadge>{evidencesCount}</TabBadge>}
|
||||
</TabLink>
|
||||
<TabLink
|
||||
to={`/organizations/${organizationId}/measures/${measureId}/tasks`}
|
||||
>
|
||||
<IconCheckmark1 size={20} />
|
||||
{__("Tasks")}
|
||||
{tasksCount > 0 && <TabBadge>{tasksCount}</TabBadge>}
|
||||
</TabLink>
|
||||
<TabLink
|
||||
to={`/organizations/${organizationId}/measures/${measureId}/controls`}
|
||||
>
|
||||
<IconFrame2 size={20} />
|
||||
{__("Controls")}
|
||||
{controlsCount > 0 && <TabBadge>{controlsCount}</TabBadge>}
|
||||
</TabLink>
|
||||
<TabLink
|
||||
to={`/organizations/${organizationId}/measures/${measureId}/risks`}
|
||||
>
|
||||
<IconWarning size={20} />
|
||||
{__("Risks")}
|
||||
{risksCount > 0 && <TabBadge>{risksCount}</TabBadge>}
|
||||
</TabLink>
|
||||
</Tabs>
|
||||
|
||||
|
||||
@@ -1,13 +1,33 @@
|
||||
import { graphql, useFragment, useMutation } from "react-relay";
|
||||
import {
|
||||
graphql,
|
||||
useFragment,
|
||||
useMutation,
|
||||
useRefetchableFragment,
|
||||
} from "react-relay";
|
||||
import { useOutletContext } from "react-router";
|
||||
import { LinkedControlsCard } from "/components/controls/LinkedControlsCard";
|
||||
import type { MeasureControlsTabFragment$key } from "./__generated__/MeasureControlsTabFragment.graphql";
|
||||
|
||||
const ControlsFragment = graphql`
|
||||
fragment MeasureControlsTabFragment on Measure {
|
||||
export const controlsFragment = graphql`
|
||||
fragment MeasureControlsTabFragment on Measure
|
||||
@argumentDefinitions(
|
||||
first: { type: "Int", defaultValue: 20 }
|
||||
after: { type: "CursorKey" }
|
||||
last: { type: "Int", defaultValue: null }
|
||||
before: { type: "CursorKey", defaultValue: null }
|
||||
order: { type: "ControlOrder", defaultValue: null }
|
||||
filter: { type: "ControlFilter", defaultValue: null }
|
||||
)
|
||||
@refetchable(queryName: "MeasureControlsTabControlsQuery") {
|
||||
id
|
||||
controls(first: 100)
|
||||
@connection(key: "MeasureControlsTabFragment_controls") {
|
||||
controls(
|
||||
first: $first
|
||||
after: $after
|
||||
last: $last
|
||||
before: $before
|
||||
orderBy: $order
|
||||
filter: $filter
|
||||
) @connection(key: "MeasureControlsTab_controls") {
|
||||
__id
|
||||
edges {
|
||||
node {
|
||||
@@ -30,23 +50,43 @@ export const detachControlMutation = graphql`
|
||||
}
|
||||
`;
|
||||
|
||||
export const attachControlMutation = graphql`
|
||||
mutation MeasureControlsTabAttachMutation(
|
||||
$input: CreateControlMeasureMappingInput!
|
||||
$connections: [ID!]!
|
||||
) {
|
||||
createControlMeasureMapping(input: $input) {
|
||||
controlEdge @prependEdge(connections: $connections) {
|
||||
node {
|
||||
id
|
||||
...LinkedControlsCardFragment
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export default function MeasureControlsTab() {
|
||||
const { measure } = useOutletContext<{
|
||||
measure: MeasureControlsTabFragment$key & { id: string };
|
||||
}>();
|
||||
const data = useFragment(ControlsFragment, measure);
|
||||
const [data, refetch] = useRefetchableFragment(controlsFragment, measure);
|
||||
const connectionId = data.controls.__id;
|
||||
const controls = data.controls?.edges?.map((edge) => edge.node) ?? [];
|
||||
|
||||
const [detachControl, isDetaching] = useMutation(detachControlMutation);
|
||||
const [attachControl, isAttaching] = useMutation(attachControlMutation);
|
||||
const isLoading = isDetaching || isAttaching;
|
||||
|
||||
return (
|
||||
<LinkedControlsCard
|
||||
disabled={isDetaching}
|
||||
disabled={isLoading}
|
||||
controls={controls}
|
||||
onDetach={detachControl}
|
||||
onAttach={attachControl}
|
||||
params={{ measureId: data.id }}
|
||||
connectionId={connectionId}
|
||||
refetch={refetch}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ import type { MeasureEvidencesTabFragment_evidence$key } from "./__generated__/M
|
||||
import { fileSize, fileType } from "@probo/helpers";
|
||||
import { promisifyMutation, sprintf } from "@probo/helpers";
|
||||
|
||||
const evidencesFragment = graphql`
|
||||
export const evidencesFragment = graphql`
|
||||
fragment MeasureEvidencesTabFragment on Measure
|
||||
@refetchable(queryName: "MeasureEvidencesTabQuery")
|
||||
@argumentDefinitions(
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { MeasureRisksTabFragment$key } from "./__generated__/MeasureRisksTa
|
||||
import { useOutletContext } from "react-router";
|
||||
import { LinkedRisksCard } from "/components/risks/LinkedRisksCard";
|
||||
|
||||
const risksFragment = graphql`
|
||||
export const risksFragment = graphql`
|
||||
fragment MeasureRisksTabFragment on Measure {
|
||||
id
|
||||
risks(first: 100) @connection(key: "Measure__risks") {
|
||||
|
||||
@@ -7,7 +7,7 @@ import { Button, IconPlusLarge } from "@probo/ui";
|
||||
import { useTranslate } from "@probo/i18n";
|
||||
import TaskFormDialog from "/components/tasks/TaskFormDialog";
|
||||
|
||||
const tasksFragment = graphql`
|
||||
export const tasksFragment = graphql`
|
||||
fragment MeasureTasksTabFragment on Measure {
|
||||
tasks(first: 100) @connection(key: "Measure__tasks") {
|
||||
__id
|
||||
|
||||
@@ -0,0 +1,216 @@
|
||||
/**
|
||||
* @generated SignedSource<<70f20e2c5e4b88b101691f90aecde2da>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
|
||||
import { ConcreteRequest } from 'relay-runtime';
|
||||
import { FragmentRefs } from "relay-runtime";
|
||||
export type CreateControlMeasureMappingInput = {
|
||||
controlId: string;
|
||||
measureId: string;
|
||||
};
|
||||
export type MeasureControlsTabAttachMutation$variables = {
|
||||
connections: ReadonlyArray<string>;
|
||||
input: CreateControlMeasureMappingInput;
|
||||
};
|
||||
export type MeasureControlsTabAttachMutation$data = {
|
||||
readonly createControlMeasureMapping: {
|
||||
readonly controlEdge: {
|
||||
readonly node: {
|
||||
readonly id: string;
|
||||
readonly " $fragmentSpreads": FragmentRefs<"LinkedControlsCardFragment">;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
export type MeasureControlsTabAttachMutation = {
|
||||
response: MeasureControlsTabAttachMutation$data;
|
||||
variables: MeasureControlsTabAttachMutation$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": "name",
|
||||
"storageKey": null
|
||||
};
|
||||
return {
|
||||
"fragment": {
|
||||
"argumentDefinitions": [
|
||||
(v0/*: any*/),
|
||||
(v1/*: any*/)
|
||||
],
|
||||
"kind": "Fragment",
|
||||
"metadata": null,
|
||||
"name": "MeasureControlsTabAttachMutation",
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v2/*: any*/),
|
||||
"concreteType": "CreateControlMeasureMappingPayload",
|
||||
"kind": "LinkedField",
|
||||
"name": "createControlMeasureMapping",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "ControlEdge",
|
||||
"kind": "LinkedField",
|
||||
"name": "controlEdge",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Control",
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v3/*: any*/),
|
||||
{
|
||||
"args": null,
|
||||
"kind": "FragmentSpread",
|
||||
"name": "LinkedControlsCardFragment"
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"type": "Mutation",
|
||||
"abstractKey": null
|
||||
},
|
||||
"kind": "Request",
|
||||
"operation": {
|
||||
"argumentDefinitions": [
|
||||
(v1/*: any*/),
|
||||
(v0/*: any*/)
|
||||
],
|
||||
"kind": "Operation",
|
||||
"name": "MeasureControlsTabAttachMutation",
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v2/*: any*/),
|
||||
"concreteType": "CreateControlMeasureMappingPayload",
|
||||
"kind": "LinkedField",
|
||||
"name": "createControlMeasureMapping",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "ControlEdge",
|
||||
"kind": "LinkedField",
|
||||
"name": "controlEdge",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Control",
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v3/*: any*/),
|
||||
(v4/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "sectionTitle",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Framework",
|
||||
"kind": "LinkedField",
|
||||
"name": "framework",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v4/*: any*/),
|
||||
(v3/*: any*/)
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"filters": null,
|
||||
"handle": "prependEdge",
|
||||
"key": "",
|
||||
"kind": "LinkedHandle",
|
||||
"name": "controlEdge",
|
||||
"handleArgs": [
|
||||
{
|
||||
"kind": "Variable",
|
||||
"name": "connections",
|
||||
"variableName": "connections"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "7b0bd217fa037088f76cb4b6fc4a420a",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "MeasureControlsTabAttachMutation",
|
||||
"operationKind": "mutation",
|
||||
"text": "mutation MeasureControlsTabAttachMutation(\n $input: CreateControlMeasureMappingInput!\n) {\n createControlMeasureMapping(input: $input) {\n controlEdge {\n node {\n id\n ...LinkedControlsCardFragment\n }\n }\n }\n}\n\nfragment LinkedControlsCardFragment on Control {\n id\n name\n sectionTitle\n framework {\n name\n id\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "010619cccaa46b2e02738bb0148341c0";
|
||||
|
||||
export default node;
|
||||
@@ -0,0 +1,363 @@
|
||||
/**
|
||||
* @generated SignedSource<<a1db6b0b06d18d2d5cd1d2c6e6ea7617>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
|
||||
import { ConcreteRequest } from 'relay-runtime';
|
||||
import { FragmentRefs } from "relay-runtime";
|
||||
export type ControlOrderField = "CREATED_AT" | "SECTION_TITLE";
|
||||
export type OrderDirection = "ASC" | "DESC";
|
||||
export type ControlFilter = {
|
||||
query?: string | null | undefined;
|
||||
};
|
||||
export type ControlOrder = {
|
||||
direction: OrderDirection;
|
||||
field: ControlOrderField;
|
||||
};
|
||||
export type MeasureControlsTabControlsQuery$variables = {
|
||||
after?: any | null | undefined;
|
||||
before?: any | null | undefined;
|
||||
filter?: ControlFilter | null | undefined;
|
||||
first?: number | null | undefined;
|
||||
id: string;
|
||||
last?: number | null | undefined;
|
||||
order?: ControlOrder | null | undefined;
|
||||
};
|
||||
export type MeasureControlsTabControlsQuery$data = {
|
||||
readonly node: {
|
||||
readonly " $fragmentSpreads": FragmentRefs<"MeasureControlsTabFragment">;
|
||||
};
|
||||
};
|
||||
export type MeasureControlsTabControlsQuery = {
|
||||
response: MeasureControlsTabControlsQuery$data;
|
||||
variables: MeasureControlsTabControlsQuery$variables;
|
||||
};
|
||||
|
||||
const node: ConcreteRequest = (function(){
|
||||
var v0 = {
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "after"
|
||||
},
|
||||
v1 = {
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "before"
|
||||
},
|
||||
v2 = {
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "filter"
|
||||
},
|
||||
v3 = {
|
||||
"defaultValue": 20,
|
||||
"kind": "LocalArgument",
|
||||
"name": "first"
|
||||
},
|
||||
v4 = {
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "id"
|
||||
},
|
||||
v5 = {
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "last"
|
||||
},
|
||||
v6 = {
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "order"
|
||||
},
|
||||
v7 = [
|
||||
{
|
||||
"kind": "Variable",
|
||||
"name": "id",
|
||||
"variableName": "id"
|
||||
}
|
||||
],
|
||||
v8 = {
|
||||
"kind": "Variable",
|
||||
"name": "after",
|
||||
"variableName": "after"
|
||||
},
|
||||
v9 = {
|
||||
"kind": "Variable",
|
||||
"name": "before",
|
||||
"variableName": "before"
|
||||
},
|
||||
v10 = {
|
||||
"kind": "Variable",
|
||||
"name": "filter",
|
||||
"variableName": "filter"
|
||||
},
|
||||
v11 = {
|
||||
"kind": "Variable",
|
||||
"name": "first",
|
||||
"variableName": "first"
|
||||
},
|
||||
v12 = {
|
||||
"kind": "Variable",
|
||||
"name": "last",
|
||||
"variableName": "last"
|
||||
},
|
||||
v13 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "__typename",
|
||||
"storageKey": null
|
||||
},
|
||||
v14 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "id",
|
||||
"storageKey": null
|
||||
},
|
||||
v15 = [
|
||||
(v8/*: any*/),
|
||||
(v9/*: any*/),
|
||||
(v10/*: any*/),
|
||||
(v11/*: any*/),
|
||||
(v12/*: any*/),
|
||||
{
|
||||
"kind": "Variable",
|
||||
"name": "orderBy",
|
||||
"variableName": "order"
|
||||
}
|
||||
],
|
||||
v16 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "name",
|
||||
"storageKey": null
|
||||
};
|
||||
return {
|
||||
"fragment": {
|
||||
"argumentDefinitions": [
|
||||
(v0/*: any*/),
|
||||
(v1/*: any*/),
|
||||
(v2/*: any*/),
|
||||
(v3/*: any*/),
|
||||
(v4/*: any*/),
|
||||
(v5/*: any*/),
|
||||
(v6/*: any*/)
|
||||
],
|
||||
"kind": "Fragment",
|
||||
"metadata": null,
|
||||
"name": "MeasureControlsTabControlsQuery",
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v7/*: any*/),
|
||||
"concreteType": null,
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"args": [
|
||||
(v8/*: any*/),
|
||||
(v9/*: any*/),
|
||||
(v10/*: any*/),
|
||||
(v11/*: any*/),
|
||||
(v12/*: any*/),
|
||||
{
|
||||
"kind": "Variable",
|
||||
"name": "order",
|
||||
"variableName": "order"
|
||||
}
|
||||
],
|
||||
"kind": "FragmentSpread",
|
||||
"name": "MeasureControlsTabFragment"
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"type": "Query",
|
||||
"abstractKey": null
|
||||
},
|
||||
"kind": "Request",
|
||||
"operation": {
|
||||
"argumentDefinitions": [
|
||||
(v0/*: any*/),
|
||||
(v1/*: any*/),
|
||||
(v2/*: any*/),
|
||||
(v3/*: any*/),
|
||||
(v5/*: any*/),
|
||||
(v6/*: any*/),
|
||||
(v4/*: any*/)
|
||||
],
|
||||
"kind": "Operation",
|
||||
"name": "MeasureControlsTabControlsQuery",
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v7/*: any*/),
|
||||
"concreteType": null,
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v13/*: any*/),
|
||||
(v14/*: any*/),
|
||||
{
|
||||
"kind": "InlineFragment",
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v15/*: any*/),
|
||||
"concreteType": "ControlConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "controls",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "ControlEdge",
|
||||
"kind": "LinkedField",
|
||||
"name": "edges",
|
||||
"plural": true,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Control",
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v14/*: any*/),
|
||||
(v16/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "sectionTitle",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Framework",
|
||||
"kind": "LinkedField",
|
||||
"name": "framework",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v16/*: any*/),
|
||||
(v14/*: any*/)
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
(v13/*: 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
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "hasPreviousPage",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "startCursor",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"kind": "ClientExtension",
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "__id",
|
||||
"storageKey": null
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v15/*: any*/),
|
||||
"filters": [
|
||||
"orderBy",
|
||||
"filter"
|
||||
],
|
||||
"handle": "connection",
|
||||
"key": "MeasureControlsTab_controls",
|
||||
"kind": "LinkedHandle",
|
||||
"name": "controls"
|
||||
}
|
||||
],
|
||||
"type": "Measure",
|
||||
"abstractKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "33e321fd8342ba1909b806fca25debf4",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "MeasureControlsTabControlsQuery",
|
||||
"operationKind": "query",
|
||||
"text": "query MeasureControlsTabControlsQuery(\n $after: CursorKey\n $before: CursorKey = null\n $filter: ControlFilter = null\n $first: Int = 20\n $last: Int = null\n $order: ControlOrder = null\n $id: ID!\n) {\n node(id: $id) {\n __typename\n ...MeasureControlsTabFragment_4cFWzS\n id\n }\n}\n\nfragment LinkedControlsCardFragment on Control {\n id\n name\n sectionTitle\n framework {\n name\n id\n }\n}\n\nfragment MeasureControlsTabFragment_4cFWzS on Measure {\n id\n controls(first: $first, after: $after, last: $last, before: $before, orderBy: $order, filter: $filter) {\n edges {\n node {\n id\n ...LinkedControlsCardFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "a9a268e40cc503e7e11fca8464f3e62c";
|
||||
|
||||
export default node;
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<ca62a85532feb9efd0d7489b36a5b017>>
|
||||
* @generated SignedSource<<08d4e9940fe4265f66568c81985cb591>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -28,8 +28,13 @@ export type MeasureControlsTabFragment$key = {
|
||||
readonly " $fragmentSpreads": FragmentRefs<"MeasureControlsTabFragment">;
|
||||
};
|
||||
|
||||
import MeasureControlsTabControlsQuery_graphql from './MeasureControlsTabControlsQuery.graphql';
|
||||
|
||||
const node: ReaderFragment = (function(){
|
||||
var v0 = {
|
||||
var v0 = [
|
||||
"controls"
|
||||
],
|
||||
v1 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
@@ -37,29 +42,90 @@ var v0 = {
|
||||
"storageKey": null
|
||||
};
|
||||
return {
|
||||
"argumentDefinitions": [],
|
||||
"argumentDefinitions": [
|
||||
{
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "after"
|
||||
},
|
||||
{
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "before"
|
||||
},
|
||||
{
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "filter"
|
||||
},
|
||||
{
|
||||
"defaultValue": 20,
|
||||
"kind": "LocalArgument",
|
||||
"name": "first"
|
||||
},
|
||||
{
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "last"
|
||||
},
|
||||
{
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "order"
|
||||
}
|
||||
],
|
||||
"kind": "Fragment",
|
||||
"metadata": {
|
||||
"connection": [
|
||||
{
|
||||
"count": null,
|
||||
"cursor": null,
|
||||
"direction": "forward",
|
||||
"path": [
|
||||
"controls"
|
||||
]
|
||||
"direction": "bidirectional",
|
||||
"path": (v0/*: any*/)
|
||||
}
|
||||
]
|
||||
],
|
||||
"refetch": {
|
||||
"connection": {
|
||||
"forward": {
|
||||
"count": "first",
|
||||
"cursor": "after"
|
||||
},
|
||||
"backward": {
|
||||
"count": "last",
|
||||
"cursor": "before"
|
||||
},
|
||||
"path": (v0/*: any*/)
|
||||
},
|
||||
"fragmentPathInResult": [
|
||||
"node"
|
||||
],
|
||||
"operation": MeasureControlsTabControlsQuery_graphql,
|
||||
"identifierInfo": {
|
||||
"identifierField": "id",
|
||||
"identifierQueryVariableName": "id"
|
||||
}
|
||||
}
|
||||
},
|
||||
"name": "MeasureControlsTabFragment",
|
||||
"selections": [
|
||||
(v0/*: any*/),
|
||||
(v1/*: any*/),
|
||||
{
|
||||
"alias": "controls",
|
||||
"args": null,
|
||||
"args": [
|
||||
{
|
||||
"kind": "Variable",
|
||||
"name": "filter",
|
||||
"variableName": "filter"
|
||||
},
|
||||
{
|
||||
"kind": "Variable",
|
||||
"name": "orderBy",
|
||||
"variableName": "order"
|
||||
}
|
||||
],
|
||||
"concreteType": "ControlConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "__MeasureControlsTabFragment_controls_connection",
|
||||
"name": "__MeasureControlsTab_controls_connection",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
@@ -78,7 +144,7 @@ return {
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v0/*: any*/),
|
||||
(v1/*: any*/),
|
||||
{
|
||||
"args": null,
|
||||
"kind": "FragmentSpread",
|
||||
@@ -125,6 +191,20 @@ 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
|
||||
@@ -150,6 +230,6 @@ return {
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "ce7a8ffb4c5837e7b5f71a781f332064";
|
||||
(node as any).hash = "a9a268e40cc503e7e11fca8464f3e62c";
|
||||
|
||||
export default node;
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
IconTrashCan,
|
||||
PageHeader,
|
||||
PropertyRow,
|
||||
TabBadge,
|
||||
TabLink,
|
||||
Tabs,
|
||||
useConfirm,
|
||||
@@ -18,7 +19,11 @@ import { Outlet, useNavigate, useParams } from "react-router";
|
||||
import { useTranslate } from "@probo/i18n";
|
||||
import { getTreatment, sprintf } from "@probo/helpers";
|
||||
import { ConnectionHandler } from "relay-runtime";
|
||||
import { usePreloadedQuery, type PreloadedQuery } from "react-relay";
|
||||
import {
|
||||
useFragment,
|
||||
usePreloadedQuery,
|
||||
type PreloadedQuery,
|
||||
} from "react-relay";
|
||||
import FormRiskDialog from "./FormRiskDialog";
|
||||
import { usePageTitle } from "@probo/hooks";
|
||||
import { useOrganizationId } from "/hooks/useOrganizationId";
|
||||
@@ -28,6 +33,10 @@ import {
|
||||
useDeleteRiskMutation,
|
||||
} from "/hooks/graph/RiskGraph";
|
||||
import type { RiskGraphNodeQuery } from "/hooks/graph/__generated__/RiskGraphNodeQuery.graphql";
|
||||
import { documentsFragment } from "./tabs/RiskDocumentsTab";
|
||||
import type { RiskDocumentsTabFragment$key } from "./tabs/__generated__/RiskDocumentsTabFragment.graphql";
|
||||
import { measuresFragment } from "./tabs/RiskMeasuresTab";
|
||||
import type { RiskMeasuresTabFragment$key } from "./tabs/__generated__/RiskMeasuresTabFragment.graphql";
|
||||
|
||||
type Props = {
|
||||
queryRef: PreloadedQuery<RiskGraphNodeQuery>;
|
||||
@@ -80,6 +89,15 @@ export default function RiskDetailPage(props: Props) {
|
||||
);
|
||||
};
|
||||
|
||||
const documentsCount = useFragment(
|
||||
documentsFragment,
|
||||
risk as RiskDocumentsTabFragment$key
|
||||
).documents.edges.length;
|
||||
const measuresCount = useFragment(
|
||||
measuresFragment,
|
||||
risk as RiskMeasuresTabFragment$key
|
||||
).measures.edges.length;
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
{/* Header */}
|
||||
@@ -128,11 +146,13 @@ export default function RiskDetailPage(props: Props) {
|
||||
to={`/organizations/${organizationId}/risks/${riskId}/measures`}
|
||||
>
|
||||
{__("Measures")}
|
||||
{measuresCount > 0 && <TabBadge>{measuresCount}</TabBadge>}
|
||||
</TabLink>
|
||||
<TabLink
|
||||
to={`/organizations/${organizationId}/risks/${riskId}/documents`}
|
||||
>
|
||||
{__("Documents")}
|
||||
{documentsCount > 0 && <TabBadge>{documentsCount}</TabBadge>}
|
||||
</TabLink>
|
||||
</Tabs>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import { useOutletContext } from "react-router";
|
||||
import { LinkedDocumentsCard } from "/components/documents/LinkedDocumentsCard";
|
||||
import type { RiskDocumentsTabFragment$key } from "./__generated__/RiskDocumentsTabFragment.graphql";
|
||||
|
||||
const documentsFragment = graphql`
|
||||
export const documentsFragment = graphql`
|
||||
fragment RiskDocumentsTabFragment on Risk {
|
||||
id
|
||||
documents(first: 100) @connection(key: "Risk__documents") {
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { RiskMeasuresTabFragment$key } from "./__generated__/RiskMeasuresTa
|
||||
import { useOutletContext } from "react-router";
|
||||
import { LinkedMeasuresCard } from "/components/measures/LinkedMeasuresCard";
|
||||
|
||||
const measuresFragment = graphql`
|
||||
export const measuresFragment = graphql`
|
||||
fragment RiskMeasuresTabFragment on Risk {
|
||||
id
|
||||
measures(first: 100) @connection(key: "Risk__measures") {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import {
|
||||
ConnectionHandler,
|
||||
useFragment,
|
||||
usePreloadedQuery,
|
||||
type PreloadedQuery,
|
||||
} from "react-relay";
|
||||
@@ -16,6 +17,7 @@ import {
|
||||
DropdownItem,
|
||||
IconPageTextLine,
|
||||
IconTrashCan,
|
||||
TabBadge,
|
||||
TabLink,
|
||||
Tabs,
|
||||
} from "@probo/ui";
|
||||
@@ -24,6 +26,8 @@ import { useOrganizationId } from "/hooks/useOrganizationId";
|
||||
import { Outlet } from "react-router";
|
||||
import { faviconUrl } from "@probo/helpers";
|
||||
import { ImportAssessmentDialog } from "./dialogs/ImportAssessmentDialog";
|
||||
import { complianceReportsFragment } from "./tabs/VendorComplianceTab";
|
||||
import type { VendorComplianceTabFragment$key } from "./tabs/__generated__/VendorComplianceTabFragment.graphql";
|
||||
|
||||
type Props = {
|
||||
queryRef: PreloadedQuery<VendorGraphNodeQuery>;
|
||||
@@ -39,6 +43,10 @@ export default function VendorDetailPage(props: Props) {
|
||||
ConnectionHandler.getConnectionID(organizationId, vendorConnectionKey)
|
||||
);
|
||||
const logo = faviconUrl(vendor.websiteUrl);
|
||||
const reportsCount = useFragment(
|
||||
complianceReportsFragment,
|
||||
vendor as VendorComplianceTabFragment$key
|
||||
).complianceReports.edges.length;
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
@@ -97,6 +105,7 @@ export default function VendorDetailPage(props: Props) {
|
||||
to={`/organizations/${organizationId}/vendors/${vendor.id}/compliance`}
|
||||
>
|
||||
{__("Compliance reports")}
|
||||
{reportsCount > 0 && <TabBadge>{reportsCount}</TabBadge>}
|
||||
</TabLink>
|
||||
<TabLink
|
||||
to={`/organizations/${organizationId}/vendors/${vendor.id}/risks`}
|
||||
|
||||
@@ -73,7 +73,6 @@ export function ImportAssessmentDialog({ vendorId, children }: Props) {
|
||||
return (
|
||||
<Dialog
|
||||
ref={dialogRef}
|
||||
defaultOpen
|
||||
trigger={children}
|
||||
title={__("Assessment from website")}
|
||||
className="max-w-lg"
|
||||
|
||||
@@ -21,7 +21,7 @@ import { useMutationWithToasts } from "/hooks/useMutationWithToasts";
|
||||
import { sprintf, fileSize } from "@probo/helpers";
|
||||
import { SortableTable, SortableTh } from "/components/SortableTable";
|
||||
|
||||
const complianceReportsFragment = graphql`
|
||||
export const complianceReportsFragment = graphql`
|
||||
fragment VendorComplianceTabFragment on Vendor
|
||||
@refetchable(queryName: "ComplianceReportListQuery")
|
||||
@argumentDefinitions(
|
||||
|
||||
@@ -108,7 +108,10 @@ export default function VendorOverviewTab() {
|
||||
<h2 className="text-base font-medium">{__("Links")}</h2>
|
||||
<Card className="divide-y divide-border-low">
|
||||
{urls.map((url) => (
|
||||
<div className="grid grid-cols-2 items-center divide-x divide-border-low">
|
||||
<div
|
||||
key={url.name}
|
||||
className="grid grid-cols-2 items-center divide-x divide-border-low"
|
||||
>
|
||||
<label
|
||||
className="p-4 text-sm font-medium text-txt-secondary"
|
||||
htmlFor={url.name}
|
||||
|
||||
@@ -16,7 +16,6 @@ export function InfiniteScrollTrigger({ children, onView, loading }: Props) {
|
||||
threshold: 0,
|
||||
});
|
||||
const onViewRef = useRefSync(onView);
|
||||
console.log(inView);
|
||||
useEffect(() => {
|
||||
if (inView && !loading) onViewRef.current();
|
||||
}, [inView, loading]);
|
||||
|
||||
@@ -19,8 +19,8 @@ export const input = tv({
|
||||
variant: {
|
||||
bordered:
|
||||
"py-[6px] bg-secondary border border-border-mid rounded-[10px] hover:border-border-strong text-sm px-3 text-txt-primary",
|
||||
ghost: "text-base text-txt-secondary",
|
||||
title: "text-2xl font-semibold text-txt-primary",
|
||||
ghost: "text-base text-txt-secondary outline-none",
|
||||
title: "text-2xl font-semibold text-txt-primary outline-none",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
|
||||
Reference in New Issue
Block a user