Add controls snapshots
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
200
apps/console/src/components/snapshots/LinkedSnapshotsCard.tsx
Normal file
200
apps/console/src/components/snapshots/LinkedSnapshotsCard.tsx
Normal file
@@ -0,0 +1,200 @@
|
||||
import { graphql } from "relay-runtime";
|
||||
import {
|
||||
Card,
|
||||
IconPlusLarge,
|
||||
Button,
|
||||
Tr,
|
||||
Td,
|
||||
Table,
|
||||
Thead,
|
||||
Tbody,
|
||||
Th,
|
||||
IconChevronDown,
|
||||
IconTrashCan,
|
||||
Badge,
|
||||
TrButton,
|
||||
} from "@probo/ui";
|
||||
import { useTranslate } from "@probo/i18n";
|
||||
import type { LinkedSnapshotsCardFragment$key } from "./__generated__/LinkedSnapshotsCardFragment.graphql";
|
||||
import { useFragment } from "react-relay";
|
||||
import { useMemo, useState } from "react";
|
||||
import { sprintf, getSnapshotTypeLabel, getSnapshotTypeUrlPath } from "@probo/helpers";
|
||||
import { useOrganizationId } from "/hooks/useOrganizationId";
|
||||
import { LinkedSnapshotsDialog } from "./LinkedSnapshotsDialog";
|
||||
import clsx from "clsx";
|
||||
|
||||
const linkedSnapshotFragment = graphql`
|
||||
fragment LinkedSnapshotsCardFragment on Snapshot {
|
||||
id
|
||||
name
|
||||
description
|
||||
type
|
||||
createdAt
|
||||
}
|
||||
`;
|
||||
|
||||
type Mutation<Params> = (p: {
|
||||
variables: {
|
||||
input: {
|
||||
snapshotId: string;
|
||||
} & Params;
|
||||
connections: string[];
|
||||
};
|
||||
}) => void;
|
||||
|
||||
type Props<Params> = {
|
||||
snapshots: (LinkedSnapshotsCardFragment$key & { id: string })[];
|
||||
params: Params;
|
||||
disabled?: boolean;
|
||||
connectionId: string;
|
||||
onAttach: Mutation<Params>;
|
||||
onDetach: Mutation<Params>;
|
||||
variant?: "card" | "table";
|
||||
};
|
||||
|
||||
export function LinkedSnapshotsCard<Params>(props: Props<Params>) {
|
||||
const { __ } = useTranslate();
|
||||
const [limit, setLimit] = useState<number | null>(4);
|
||||
const snapshots = useMemo(() => {
|
||||
return limit ? props.snapshots.slice(0, limit) : props.snapshots;
|
||||
}, [props.snapshots, limit]);
|
||||
const showMoreButton = limit !== null && props.snapshots.length > limit;
|
||||
const variant = props.variant ?? "table";
|
||||
|
||||
const onAttach = (snapshotId: string) => {
|
||||
props.onAttach({
|
||||
variables: {
|
||||
input: {
|
||||
snapshotId,
|
||||
...props.params,
|
||||
},
|
||||
connections: [props.connectionId],
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const onDetach = (snapshotId: string) => {
|
||||
props.onDetach({
|
||||
variables: {
|
||||
input: {
|
||||
snapshotId,
|
||||
...props.params,
|
||||
},
|
||||
connections: [props.connectionId],
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const Wrapper = variant === "card" ? Card : "div";
|
||||
|
||||
return (
|
||||
<Wrapper padded className="space-y-[10px]">
|
||||
{variant === "card" && (
|
||||
<div className="flex justify-between">
|
||||
<div className="text-lg font-semibold">{__("Snapshots")}</div>
|
||||
<LinkedSnapshotsDialog
|
||||
disabled={props.disabled}
|
||||
linkedSnapshots={props.snapshots}
|
||||
onLink={onAttach}
|
||||
onUnlink={onDetach}
|
||||
>
|
||||
<Button variant="tertiary" icon={IconPlusLarge}>
|
||||
{__("Link snapshot")}
|
||||
</Button>
|
||||
</LinkedSnapshotsDialog>
|
||||
</div>
|
||||
)}
|
||||
<Table className={clsx(variant === "card" && "bg-invert")}>
|
||||
<Thead>
|
||||
<Tr>
|
||||
<Th>{__("Name")}</Th>
|
||||
<Th>{__("Type")}</Th>
|
||||
{variant === "table" && <Th>{__("Description")}</Th>}
|
||||
<Th>{__("Created")}</Th>
|
||||
<Th></Th>
|
||||
</Tr>
|
||||
</Thead>
|
||||
<Tbody>
|
||||
{snapshots.length === 0 && (
|
||||
<Tr>
|
||||
<Td colSpan={variant === "table" ? 5 : 3} className="text-center text-txt-secondary">
|
||||
{__("No snapshots linked")}
|
||||
</Td>
|
||||
</Tr>
|
||||
)}
|
||||
{snapshots.map((snapshot) => (
|
||||
<SnapshotRow
|
||||
key={snapshot.id}
|
||||
snapshot={snapshot}
|
||||
onClick={onDetach}
|
||||
variant={variant}
|
||||
/>
|
||||
))}
|
||||
{variant === "table" && (
|
||||
<LinkedSnapshotsDialog
|
||||
disabled={props.disabled}
|
||||
linkedSnapshots={props.snapshots}
|
||||
onLink={onAttach}
|
||||
onUnlink={onDetach}
|
||||
>
|
||||
<TrButton colspan={variant === "table" ? 5 : 3} icon={IconPlusLarge}>
|
||||
{__("Link snapshot")}
|
||||
</TrButton>
|
||||
</LinkedSnapshotsDialog>
|
||||
)}
|
||||
</Tbody>
|
||||
</Table>
|
||||
{showMoreButton && (
|
||||
<Button
|
||||
variant="tertiary"
|
||||
onClick={() => setLimit(null)}
|
||||
className="mt-3 mx-auto"
|
||||
icon={IconChevronDown}
|
||||
>
|
||||
{sprintf(__("Show %s more"), props.snapshots.length - limit)}
|
||||
</Button>
|
||||
)}
|
||||
</Wrapper>
|
||||
);
|
||||
}
|
||||
|
||||
function SnapshotRow(props: {
|
||||
snapshot: LinkedSnapshotsCardFragment$key & { id: string };
|
||||
onClick: (snapshotId: string) => void;
|
||||
variant: "card" | "table";
|
||||
}) {
|
||||
const snapshot = useFragment(linkedSnapshotFragment, props.snapshot);
|
||||
const organizationId = useOrganizationId();
|
||||
const { __, dateFormat } = useTranslate();
|
||||
|
||||
const urlPath = getSnapshotTypeUrlPath(snapshot.type);
|
||||
const snapshotUrl = `/organizations/${organizationId}/snapshots/${snapshot.id}${urlPath}`;
|
||||
|
||||
return (
|
||||
<Tr to={snapshotUrl}>
|
||||
<Td className="font-medium">{snapshot.name}</Td>
|
||||
<Td>
|
||||
<Badge variant="neutral">
|
||||
{getSnapshotTypeLabel(__, snapshot.type)}
|
||||
</Badge>
|
||||
</Td>
|
||||
{props.variant === "table" && (
|
||||
<Td className="text-txt-secondary">
|
||||
{snapshot.description || __("No description")}
|
||||
</Td>
|
||||
)}
|
||||
<Td className="text-txt-tertiary">
|
||||
{dateFormat(snapshot.createdAt, { year: "numeric", month: "short", day: "numeric" })}
|
||||
</Td>
|
||||
<Td noLink width={50} className="text-end">
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={() => props.onClick(snapshot.id)}
|
||||
icon={IconTrashCan}
|
||||
>
|
||||
{__("Unlink")}
|
||||
</Button>
|
||||
</Td>
|
||||
</Tr>
|
||||
);
|
||||
}
|
||||
194
apps/console/src/components/snapshots/LinkedSnapshotsDialog.tsx
Normal file
194
apps/console/src/components/snapshots/LinkedSnapshotsDialog.tsx
Normal file
@@ -0,0 +1,194 @@
|
||||
import {
|
||||
Button,
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogFooter,
|
||||
Badge,
|
||||
InfiniteScrollTrigger,
|
||||
Input,
|
||||
Spinner,
|
||||
IconMagnifyingGlass,
|
||||
IconPlusLarge,
|
||||
IconTrashCan,
|
||||
} from "@probo/ui";
|
||||
import { useTranslate } from "@probo/i18n";
|
||||
import { getSnapshotTypeLabel } from "@probo/helpers";
|
||||
import { Suspense, useMemo, useState, type ReactNode } from "react";
|
||||
import { graphql } from "relay-runtime";
|
||||
import { useLazyLoadQuery, usePaginationFragment } from "react-relay";
|
||||
import type { LinkedSnapshotsDialogQuery } from "./__generated__/LinkedSnapshotsDialogQuery.graphql";
|
||||
import { useOrganizationId } from "/hooks/useOrganizationId";
|
||||
import type { NodeOf } from "/types";
|
||||
import type {
|
||||
LinkedSnapshotsDialogFragment$data,
|
||||
LinkedSnapshotsDialogFragment$key,
|
||||
} from "./__generated__/LinkedSnapshotsDialogFragment.graphql";
|
||||
|
||||
const snapshotsQuery = graphql`
|
||||
query LinkedSnapshotsDialogQuery($organizationId: ID!) {
|
||||
organization: node(id: $organizationId) {
|
||||
id
|
||||
... on Organization {
|
||||
...LinkedSnapshotsDialogFragment
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const snapshotsFragment = graphql`
|
||||
fragment LinkedSnapshotsDialogFragment on Organization
|
||||
@refetchable(queryName: "LinkedSnapshotsDialogQuery_fragment")
|
||||
@argumentDefinitions(
|
||||
first: { type: "Int", defaultValue: 20 }
|
||||
order: { type: "SnapshotOrder", defaultValue: null }
|
||||
after: { type: "CursorKey", defaultValue: null }
|
||||
before: { type: "CursorKey", defaultValue: null }
|
||||
last: { type: "Int", defaultValue: null }
|
||||
) {
|
||||
snapshots(
|
||||
first: $first
|
||||
after: $after
|
||||
last: $last
|
||||
before: $before
|
||||
orderBy: $order
|
||||
) @connection(key: "LinkedSnapshotsDialogQuery_snapshots") {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
name
|
||||
description
|
||||
type
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
type Props = {
|
||||
children: ReactNode;
|
||||
disabled?: boolean;
|
||||
linkedSnapshots?: { id: string }[];
|
||||
onLink: (snapshotId: string) => void;
|
||||
onUnlink: (snapshotId: string) => void;
|
||||
};
|
||||
|
||||
export function LinkedSnapshotsDialog({ children, ...props }: Props) {
|
||||
const { __ } = useTranslate();
|
||||
|
||||
return (
|
||||
<Dialog trigger={children} title={__("Link snapshots")}>
|
||||
<DialogContent>
|
||||
<Suspense fallback={<Spinner centered />}>
|
||||
<LinkedSnapshotsDialogContent {...props} />
|
||||
</Suspense>
|
||||
</DialogContent>
|
||||
<DialogFooter exitLabel={__("Close")} />
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
function LinkedSnapshotsDialogContent(props: Omit<Props, "children">) {
|
||||
const organizationId = useOrganizationId();
|
||||
const query = useLazyLoadQuery<LinkedSnapshotsDialogQuery>(snapshotsQuery, {
|
||||
organizationId,
|
||||
});
|
||||
const { data, loadNext, hasNext, isLoadingNext } = usePaginationFragment<
|
||||
LinkedSnapshotsDialogQuery,
|
||||
LinkedSnapshotsDialogFragment$key>(
|
||||
snapshotsFragment,
|
||||
query.organization
|
||||
);
|
||||
|
||||
const { __ } = useTranslate();
|
||||
const [search, setSearch] = useState("");
|
||||
const snapshots = data.snapshots?.edges?.map((edge) => edge.node) ?? [];
|
||||
const linkedIds = useMemo(() => {
|
||||
return new Set(props.linkedSnapshots?.map((s) => s.id) ?? []);
|
||||
}, [props.linkedSnapshots]);
|
||||
|
||||
const filteredSnapshots = useMemo(() => {
|
||||
return snapshots.filter((snapshot) =>
|
||||
snapshot.name.toLowerCase().includes(search.toLowerCase())
|
||||
);
|
||||
}, [snapshots, search]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<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 snapshots...")}
|
||||
onValueChange={setSearch}
|
||||
/>
|
||||
</div>
|
||||
<div className="divide-y divide-border-low">
|
||||
{filteredSnapshots.map((snapshot) => (
|
||||
<SnapshotRow
|
||||
key={snapshot.id}
|
||||
snapshot={snapshot}
|
||||
linkedSnapshots={linkedIds}
|
||||
onLink={props.onLink}
|
||||
onUnlink={props.onUnlink}
|
||||
disabled={props.disabled}
|
||||
/>
|
||||
))}
|
||||
{hasNext && (
|
||||
<InfiniteScrollTrigger
|
||||
loading={isLoadingNext}
|
||||
onView={() => loadNext(20)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
type Snapshot = NodeOf<LinkedSnapshotsDialogFragment$data["snapshots"]>;
|
||||
|
||||
type RowProps = {
|
||||
snapshot: Snapshot;
|
||||
linkedSnapshots: Set<string>;
|
||||
disabled?: boolean;
|
||||
onLink: (snapshotId: string) => void;
|
||||
onUnlink: (snapshotId: string) => void;
|
||||
};
|
||||
|
||||
function SnapshotRow(props: RowProps) {
|
||||
const { __, dateFormat } = useTranslate();
|
||||
|
||||
const isLinked = props.linkedSnapshots.has(props.snapshot.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"
|
||||
onClick={() => onClick(props.snapshot.id)}
|
||||
>
|
||||
<div className="flex-1 flex items-center gap-4">
|
||||
<div className="font-medium min-w-0 flex-shrink-0">
|
||||
{props.snapshot.name}
|
||||
</div>
|
||||
<Badge variant="neutral" className="flex-shrink-0 ml-6">
|
||||
{getSnapshotTypeLabel(__, props.snapshot.type)}
|
||||
</Badge>
|
||||
<div className="text-sm text-txt-secondary min-w-0 flex-1 text-left">
|
||||
{props.snapshot.description || __("No description")}
|
||||
</div>
|
||||
<div className="text-sm text-txt-tertiary flex-shrink-0">
|
||||
{dateFormat(props.snapshot.createdAt, { year: "numeric", month: "short", day: "numeric" })}
|
||||
</div>
|
||||
</div>
|
||||
<Button
|
||||
disabled={props.disabled}
|
||||
variant={isLinked ? "secondary" : "primary"}
|
||||
asChild
|
||||
>
|
||||
<span>
|
||||
<IconComponent size={16} /> {isLinked ? __("Unlink") : __("Link")}
|
||||
</span>
|
||||
</Button>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
75
apps/console/src/components/snapshots/__generated__/LinkedSnapshotsCardFragment.graphql.ts
generated
Normal file
75
apps/console/src/components/snapshots/__generated__/LinkedSnapshotsCardFragment.graphql.ts
generated
Normal file
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* @generated SignedSource<<e9fde8de02cc2e3ec97ce64b67818bfe>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
|
||||
import { ReaderFragment } from 'relay-runtime';
|
||||
export type SnapshotsType = "ASSETS" | "COMPLIANCE_REGISTRIES" | "DATA" | "NON_CONFORMITY_REGISTRIES" | "RISKS" | "VENDORS";
|
||||
import { FragmentRefs } from "relay-runtime";
|
||||
export type LinkedSnapshotsCardFragment$data = {
|
||||
readonly createdAt: any;
|
||||
readonly description: string | null | undefined;
|
||||
readonly id: string;
|
||||
readonly name: string;
|
||||
readonly type: SnapshotsType;
|
||||
readonly " $fragmentType": "LinkedSnapshotsCardFragment";
|
||||
};
|
||||
export type LinkedSnapshotsCardFragment$key = {
|
||||
readonly " $data"?: LinkedSnapshotsCardFragment$data;
|
||||
readonly " $fragmentSpreads": FragmentRefs<"LinkedSnapshotsCardFragment">;
|
||||
};
|
||||
|
||||
const node: ReaderFragment = {
|
||||
"argumentDefinitions": [],
|
||||
"kind": "Fragment",
|
||||
"metadata": null,
|
||||
"name": "LinkedSnapshotsCardFragment",
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "id",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "name",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "description",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "type",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "createdAt",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"type": "Snapshot",
|
||||
"abstractKey": null
|
||||
};
|
||||
|
||||
(node as any).hash = "b9b682f8e57082c98d8b0460155757fb";
|
||||
|
||||
export default node;
|
||||
239
apps/console/src/components/snapshots/__generated__/LinkedSnapshotsDialogFragment.graphql.ts
generated
Normal file
239
apps/console/src/components/snapshots/__generated__/LinkedSnapshotsDialogFragment.graphql.ts
generated
Normal file
@@ -0,0 +1,239 @@
|
||||
/**
|
||||
* @generated SignedSource<<b68d2b7e020579736ca058b633352dee>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
|
||||
import { ReaderFragment } from 'relay-runtime';
|
||||
export type SnapshotsType = "ASSETS" | "COMPLIANCE_REGISTRIES" | "DATA" | "NON_CONFORMITY_REGISTRIES" | "RISKS" | "VENDORS";
|
||||
import { FragmentRefs } from "relay-runtime";
|
||||
export type LinkedSnapshotsDialogFragment$data = {
|
||||
readonly id: string;
|
||||
readonly snapshots: {
|
||||
readonly edges: ReadonlyArray<{
|
||||
readonly node: {
|
||||
readonly createdAt: any;
|
||||
readonly description: string | null | undefined;
|
||||
readonly id: string;
|
||||
readonly name: string;
|
||||
readonly type: SnapshotsType;
|
||||
};
|
||||
}>;
|
||||
};
|
||||
readonly " $fragmentType": "LinkedSnapshotsDialogFragment";
|
||||
};
|
||||
export type LinkedSnapshotsDialogFragment$key = {
|
||||
readonly " $data"?: LinkedSnapshotsDialogFragment$data;
|
||||
readonly " $fragmentSpreads": FragmentRefs<"LinkedSnapshotsDialogFragment">;
|
||||
};
|
||||
|
||||
import LinkedSnapshotsDialogQuery_fragment_graphql from './LinkedSnapshotsDialogQuery_fragment.graphql';
|
||||
|
||||
const node: ReaderFragment = (function(){
|
||||
var v0 = [
|
||||
"snapshots"
|
||||
],
|
||||
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": 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": LinkedSnapshotsDialogQuery_fragment_graphql,
|
||||
"identifierInfo": {
|
||||
"identifierField": "id",
|
||||
"identifierQueryVariableName": "id"
|
||||
}
|
||||
}
|
||||
},
|
||||
"name": "LinkedSnapshotsDialogFragment",
|
||||
"selections": [
|
||||
{
|
||||
"alias": "snapshots",
|
||||
"args": [
|
||||
{
|
||||
"kind": "Variable",
|
||||
"name": "orderBy",
|
||||
"variableName": "order"
|
||||
}
|
||||
],
|
||||
"concreteType": "SnapshotConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "__LinkedSnapshotsDialogQuery_snapshots_connection",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "SnapshotEdge",
|
||||
"kind": "LinkedField",
|
||||
"name": "edges",
|
||||
"plural": true,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Snapshot",
|
||||
"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": "description",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "type",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "createdAt",
|
||||
"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 = "bdc77ee756ac59c099caa8765403cd22";
|
||||
|
||||
export default node;
|
||||
259
apps/console/src/components/snapshots/__generated__/LinkedSnapshotsDialogQuery.graphql.ts
generated
Normal file
259
apps/console/src/components/snapshots/__generated__/LinkedSnapshotsDialogQuery.graphql.ts
generated
Normal file
@@ -0,0 +1,259 @@
|
||||
/**
|
||||
* @generated SignedSource<<78d7f0f48f20187e9eef7744a19d8e1e>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
|
||||
import { ConcreteRequest } from 'relay-runtime';
|
||||
import { FragmentRefs } from "relay-runtime";
|
||||
export type LinkedSnapshotsDialogQuery$variables = {
|
||||
organizationId: string;
|
||||
};
|
||||
export type LinkedSnapshotsDialogQuery$data = {
|
||||
readonly organization: {
|
||||
readonly id: string;
|
||||
readonly " $fragmentSpreads": FragmentRefs<"LinkedSnapshotsDialogFragment">;
|
||||
};
|
||||
};
|
||||
export type LinkedSnapshotsDialogQuery = {
|
||||
response: LinkedSnapshotsDialogQuery$data;
|
||||
variables: LinkedSnapshotsDialogQuery$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": 20
|
||||
}
|
||||
];
|
||||
return {
|
||||
"fragment": {
|
||||
"argumentDefinitions": (v0/*: any*/),
|
||||
"kind": "Fragment",
|
||||
"metadata": null,
|
||||
"name": "LinkedSnapshotsDialogQuery",
|
||||
"selections": [
|
||||
{
|
||||
"alias": "organization",
|
||||
"args": (v1/*: any*/),
|
||||
"concreteType": null,
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v2/*: any*/),
|
||||
{
|
||||
"kind": "InlineFragment",
|
||||
"selections": [
|
||||
{
|
||||
"args": null,
|
||||
"kind": "FragmentSpread",
|
||||
"name": "LinkedSnapshotsDialogFragment"
|
||||
}
|
||||
],
|
||||
"type": "Organization",
|
||||
"abstractKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"type": "Query",
|
||||
"abstractKey": null
|
||||
},
|
||||
"kind": "Request",
|
||||
"operation": {
|
||||
"argumentDefinitions": (v0/*: any*/),
|
||||
"kind": "Operation",
|
||||
"name": "LinkedSnapshotsDialogQuery",
|
||||
"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": "SnapshotConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "snapshots",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "SnapshotEdge",
|
||||
"kind": "LinkedField",
|
||||
"name": "edges",
|
||||
"plural": true,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Snapshot",
|
||||
"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": "description",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "type",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "createdAt",
|
||||
"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": "snapshots(first:20)"
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v4/*: any*/),
|
||||
"filters": [
|
||||
"orderBy"
|
||||
],
|
||||
"handle": "connection",
|
||||
"key": "LinkedSnapshotsDialogQuery_snapshots",
|
||||
"kind": "LinkedHandle",
|
||||
"name": "snapshots"
|
||||
}
|
||||
],
|
||||
"type": "Organization",
|
||||
"abstractKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "200a82b795d348f0d8a63a3b2b779d7c",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "LinkedSnapshotsDialogQuery",
|
||||
"operationKind": "query",
|
||||
"text": "query LinkedSnapshotsDialogQuery(\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n id\n ... on Organization {\n ...LinkedSnapshotsDialogFragment\n }\n }\n}\n\nfragment LinkedSnapshotsDialogFragment on Organization {\n snapshots(first: 20) {\n edges {\n node {\n id\n name\n description\n type\n createdAt\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 = "b91ff32883e1f6e83d9b43251fc83001";
|
||||
|
||||
export default node;
|
||||
332
apps/console/src/components/snapshots/__generated__/LinkedSnapshotsDialogQuery_fragment.graphql.ts
generated
Normal file
332
apps/console/src/components/snapshots/__generated__/LinkedSnapshotsDialogQuery_fragment.graphql.ts
generated
Normal file
@@ -0,0 +1,332 @@
|
||||
/**
|
||||
* @generated SignedSource<<da66b640f5bf710bb086e806a82b03e6>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
|
||||
import { ConcreteRequest } from 'relay-runtime';
|
||||
import { FragmentRefs } from "relay-runtime";
|
||||
export type OrderDirection = "ASC" | "DESC";
|
||||
export type SnapshotOrderField = "CREATED_AT" | "NAME" | "TYPE";
|
||||
export type SnapshotOrder = {
|
||||
direction: OrderDirection;
|
||||
field: SnapshotOrderField;
|
||||
};
|
||||
export type LinkedSnapshotsDialogQuery_fragment$variables = {
|
||||
after?: any | null | undefined;
|
||||
before?: any | null | undefined;
|
||||
first?: number | null | undefined;
|
||||
id: string;
|
||||
last?: number | null | undefined;
|
||||
order?: SnapshotOrder | null | undefined;
|
||||
};
|
||||
export type LinkedSnapshotsDialogQuery_fragment$data = {
|
||||
readonly node: {
|
||||
readonly " $fragmentSpreads": FragmentRefs<"LinkedSnapshotsDialogFragment">;
|
||||
};
|
||||
};
|
||||
export type LinkedSnapshotsDialogQuery_fragment = {
|
||||
response: LinkedSnapshotsDialogQuery_fragment$data;
|
||||
variables: LinkedSnapshotsDialogQuery_fragment$variables;
|
||||
};
|
||||
|
||||
const node: ConcreteRequest = (function(){
|
||||
var v0 = {
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "after"
|
||||
},
|
||||
v1 = {
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "before"
|
||||
},
|
||||
v2 = {
|
||||
"defaultValue": 20,
|
||||
"kind": "LocalArgument",
|
||||
"name": "first"
|
||||
},
|
||||
v3 = {
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "id"
|
||||
},
|
||||
v4 = {
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "last"
|
||||
},
|
||||
v5 = {
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "order"
|
||||
},
|
||||
v6 = [
|
||||
{
|
||||
"kind": "Variable",
|
||||
"name": "id",
|
||||
"variableName": "id"
|
||||
}
|
||||
],
|
||||
v7 = {
|
||||
"kind": "Variable",
|
||||
"name": "after",
|
||||
"variableName": "after"
|
||||
},
|
||||
v8 = {
|
||||
"kind": "Variable",
|
||||
"name": "before",
|
||||
"variableName": "before"
|
||||
},
|
||||
v9 = {
|
||||
"kind": "Variable",
|
||||
"name": "first",
|
||||
"variableName": "first"
|
||||
},
|
||||
v10 = {
|
||||
"kind": "Variable",
|
||||
"name": "last",
|
||||
"variableName": "last"
|
||||
},
|
||||
v11 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "__typename",
|
||||
"storageKey": null
|
||||
},
|
||||
v12 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "id",
|
||||
"storageKey": null
|
||||
},
|
||||
v13 = [
|
||||
(v7/*: any*/),
|
||||
(v8/*: any*/),
|
||||
(v9/*: any*/),
|
||||
(v10/*: any*/),
|
||||
{
|
||||
"kind": "Variable",
|
||||
"name": "orderBy",
|
||||
"variableName": "order"
|
||||
}
|
||||
];
|
||||
return {
|
||||
"fragment": {
|
||||
"argumentDefinitions": [
|
||||
(v0/*: any*/),
|
||||
(v1/*: any*/),
|
||||
(v2/*: any*/),
|
||||
(v3/*: any*/),
|
||||
(v4/*: any*/),
|
||||
(v5/*: any*/)
|
||||
],
|
||||
"kind": "Fragment",
|
||||
"metadata": null,
|
||||
"name": "LinkedSnapshotsDialogQuery_fragment",
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v6/*: any*/),
|
||||
"concreteType": null,
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"args": [
|
||||
(v7/*: any*/),
|
||||
(v8/*: any*/),
|
||||
(v9/*: any*/),
|
||||
(v10/*: any*/),
|
||||
{
|
||||
"kind": "Variable",
|
||||
"name": "order",
|
||||
"variableName": "order"
|
||||
}
|
||||
],
|
||||
"kind": "FragmentSpread",
|
||||
"name": "LinkedSnapshotsDialogFragment"
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"type": "Query",
|
||||
"abstractKey": null
|
||||
},
|
||||
"kind": "Request",
|
||||
"operation": {
|
||||
"argumentDefinitions": [
|
||||
(v0/*: any*/),
|
||||
(v1/*: any*/),
|
||||
(v2/*: any*/),
|
||||
(v4/*: any*/),
|
||||
(v5/*: any*/),
|
||||
(v3/*: any*/)
|
||||
],
|
||||
"kind": "Operation",
|
||||
"name": "LinkedSnapshotsDialogQuery_fragment",
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v6/*: any*/),
|
||||
"concreteType": null,
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v11/*: any*/),
|
||||
(v12/*: any*/),
|
||||
{
|
||||
"kind": "InlineFragment",
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v13/*: any*/),
|
||||
"concreteType": "SnapshotConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "snapshots",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "SnapshotEdge",
|
||||
"kind": "LinkedField",
|
||||
"name": "edges",
|
||||
"plural": true,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Snapshot",
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v12/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "name",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "description",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "type",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "createdAt",
|
||||
"storageKey": null
|
||||
},
|
||||
(v11/*: 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": (v13/*: any*/),
|
||||
"filters": [
|
||||
"orderBy"
|
||||
],
|
||||
"handle": "connection",
|
||||
"key": "LinkedSnapshotsDialogQuery_snapshots",
|
||||
"kind": "LinkedHandle",
|
||||
"name": "snapshots"
|
||||
}
|
||||
],
|
||||
"type": "Organization",
|
||||
"abstractKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "e4c40c765a5b6ef4ba63a6343c76e6e0",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "LinkedSnapshotsDialogQuery_fragment",
|
||||
"operationKind": "query",
|
||||
"text": "query LinkedSnapshotsDialogQuery_fragment(\n $after: CursorKey = null\n $before: CursorKey = null\n $first: Int = 20\n $last: Int = null\n $order: SnapshotOrder = null\n $id: ID!\n) {\n node(id: $id) {\n __typename\n ...LinkedSnapshotsDialogFragment_16fISc\n id\n }\n}\n\nfragment LinkedSnapshotsDialogFragment_16fISc on Organization {\n snapshots(first: $first, after: $after, last: $last, before: $before, orderBy: $order) {\n edges {\n node {\n id\n name\n description\n type\n createdAt\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 = "bdc77ee756ac59c099caa8765403cd22";
|
||||
|
||||
export default node;
|
||||
@@ -130,6 +130,16 @@ export const frameworkControlNodeQuery = graphql`
|
||||
}
|
||||
}
|
||||
}
|
||||
snapshots(first: 100)
|
||||
@connection(key: "FrameworkGraphControl_snapshots") {
|
||||
__id
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
...LinkedSnapshotsCardFragment
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<dec38386ca0015f6c77121c2740fa406>>
|
||||
* @generated SignedSource<<0e6281a892cbd711d75d22153d4710ea>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -48,6 +48,15 @@ export type FrameworkGraphControlNodeQuery$data = {
|
||||
};
|
||||
readonly name?: string;
|
||||
readonly sectionTitle?: string;
|
||||
readonly snapshots?: {
|
||||
readonly __id: string;
|
||||
readonly edges: ReadonlyArray<{
|
||||
readonly node: {
|
||||
readonly id: string;
|
||||
readonly " $fragmentSpreads": FragmentRefs<"LinkedSnapshotsCardFragment">;
|
||||
};
|
||||
}>;
|
||||
};
|
||||
readonly status?: ControlStatus;
|
||||
readonly " $fragmentSpreads": FragmentRefs<"FrameworkControlDialogFragment">;
|
||||
};
|
||||
@@ -343,6 +352,49 @@ return {
|
||||
(v11/*: any*/)
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": "snapshots",
|
||||
"args": null,
|
||||
"concreteType": "SnapshotConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "__FrameworkGraphControl_snapshots_connection",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "SnapshotEdge",
|
||||
"kind": "LinkedField",
|
||||
"name": "edges",
|
||||
"plural": true,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Snapshot",
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v2/*: any*/),
|
||||
{
|
||||
"args": null,
|
||||
"kind": "FragmentSpread",
|
||||
"name": "LinkedSnapshotsCardFragment"
|
||||
},
|
||||
(v8/*: any*/)
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
(v9/*: any*/)
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
(v10/*: any*/),
|
||||
(v11/*: any*/)
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"type": "Control",
|
||||
@@ -607,6 +659,63 @@ return {
|
||||
"key": "FrameworkGraphControl_audits",
|
||||
"kind": "LinkedHandle",
|
||||
"name": "audits"
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v12/*: any*/),
|
||||
"concreteType": "SnapshotConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "snapshots",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "SnapshotEdge",
|
||||
"kind": "LinkedField",
|
||||
"name": "edges",
|
||||
"plural": true,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Snapshot",
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v2/*: any*/),
|
||||
(v3/*: any*/),
|
||||
(v5/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "type",
|
||||
"storageKey": null
|
||||
},
|
||||
(v14/*: any*/),
|
||||
(v8/*: any*/)
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
(v9/*: any*/)
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
(v10/*: any*/),
|
||||
(v11/*: any*/)
|
||||
],
|
||||
"storageKey": "snapshots(first:100)"
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v12/*: any*/),
|
||||
"filters": null,
|
||||
"handle": "connection",
|
||||
"key": "FrameworkGraphControl_snapshots",
|
||||
"kind": "LinkedHandle",
|
||||
"name": "snapshots"
|
||||
}
|
||||
],
|
||||
"type": "Control",
|
||||
@@ -618,7 +727,7 @@ return {
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "20a0b80a6b0d796951c7f8c6eca41d3c",
|
||||
"cacheID": "2ce9eb2cbe052019e86b2d0baecfb6f0",
|
||||
"id": null,
|
||||
"metadata": {
|
||||
"connection": [
|
||||
@@ -648,16 +757,25 @@ return {
|
||||
"node",
|
||||
"audits"
|
||||
]
|
||||
},
|
||||
{
|
||||
"count": null,
|
||||
"cursor": null,
|
||||
"direction": "forward",
|
||||
"path": [
|
||||
"node",
|
||||
"snapshots"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"name": "FrameworkGraphControlNodeQuery",
|
||||
"operationKind": "query",
|
||||
"text": "query FrameworkGraphControlNodeQuery(\n $controlId: ID!\n) {\n node(id: $controlId) {\n __typename\n ... on Control {\n id\n name\n sectionTitle\n description\n status\n exclusionJustification\n ...FrameworkControlDialogFragment\n measures(first: 100) {\n edges {\n node {\n id\n ...LinkedMeasuresCardFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n documents(first: 100) {\n edges {\n node {\n id\n ...LinkedDocumentsCardFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n audits(first: 100) {\n edges {\n node {\n id\n ...LinkedAuditsCardFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n id\n }\n}\n\nfragment FrameworkControlDialogFragment on Control {\n id\n name\n description\n sectionTitle\n status\n exclusionJustification\n}\n\nfragment LinkedAuditsCardFragment on Audit {\n id\n name\n createdAt\n state\n validFrom\n validUntil\n framework {\n id\n name\n }\n}\n\nfragment LinkedDocumentsCardFragment on Document {\n id\n title\n createdAt\n documentType\n versions(first: 1) {\n edges {\n node {\n id\n status\n }\n }\n }\n}\n\nfragment LinkedMeasuresCardFragment on Measure {\n id\n name\n state\n}\n"
|
||||
"text": "query FrameworkGraphControlNodeQuery(\n $controlId: ID!\n) {\n node(id: $controlId) {\n __typename\n ... on Control {\n id\n name\n sectionTitle\n description\n status\n exclusionJustification\n ...FrameworkControlDialogFragment\n measures(first: 100) {\n edges {\n node {\n id\n ...LinkedMeasuresCardFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n documents(first: 100) {\n edges {\n node {\n id\n ...LinkedDocumentsCardFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n audits(first: 100) {\n edges {\n node {\n id\n ...LinkedAuditsCardFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n snapshots(first: 100) {\n edges {\n node {\n id\n ...LinkedSnapshotsCardFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n id\n }\n}\n\nfragment FrameworkControlDialogFragment on Control {\n id\n name\n description\n sectionTitle\n status\n exclusionJustification\n}\n\nfragment LinkedAuditsCardFragment on Audit {\n id\n name\n createdAt\n state\n validFrom\n validUntil\n framework {\n id\n name\n }\n}\n\nfragment LinkedDocumentsCardFragment on Document {\n id\n title\n createdAt\n documentType\n versions(first: 1) {\n edges {\n node {\n id\n status\n }\n }\n }\n}\n\nfragment LinkedMeasuresCardFragment on Measure {\n id\n name\n state\n}\n\nfragment LinkedSnapshotsCardFragment on Snapshot {\n id\n name\n description\n type\n createdAt\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "ac5240126dfbf4882ba2b111e865045d";
|
||||
(node as any).hash = "afc4bbbce8d8b3cd57ac2bf77db58e55";
|
||||
|
||||
export default node;
|
||||
|
||||
@@ -18,6 +18,7 @@ import { useNavigate, useOutletContext } from "react-router";
|
||||
import { useOrganizationId } from "/hooks/useOrganizationId";
|
||||
import { LinkedDocumentsCard } from "/components/documents/LinkedDocumentsCard";
|
||||
import { LinkedAuditsCard } from "/components/audits/LinkedAuditsCard";
|
||||
import { LinkedSnapshotsCard } from "/components/snapshots/LinkedSnapshotsCard";
|
||||
import { FrameworkControlDialog } from "./dialogs/FrameworkControlDialog";
|
||||
import { promisifyMutation } from "@probo/helpers";
|
||||
import type { FrameworkGraphControlNodeQuery } from "/hooks/graph/__generated__/FrameworkGraphControlNodeQuery.graphql";
|
||||
@@ -105,6 +106,33 @@ const detachAuditMutation = graphql`
|
||||
}
|
||||
`;
|
||||
|
||||
const attachSnapshotMutation = graphql`
|
||||
mutation FrameworkControlPageAttachSnapshotMutation(
|
||||
$input: CreateControlSnapshotMappingInput!
|
||||
$connections: [ID!]!
|
||||
) {
|
||||
createControlSnapshotMapping(input: $input) {
|
||||
snapshotEdge @prependEdge(connections: $connections) {
|
||||
node {
|
||||
id
|
||||
...LinkedSnapshotsCardFragment
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const detachSnapshotMutation = graphql`
|
||||
mutation FrameworkControlPageDetachSnapshotMutation(
|
||||
$input: DeleteControlSnapshotMappingInput!
|
||||
$connections: [ID!]!
|
||||
) {
|
||||
deleteControlSnapshotMapping(input: $input) {
|
||||
deletedSnapshotId @deleteEdge(connections: $connections)
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const deleteControlMutation = graphql`
|
||||
mutation FrameworkControlPageDeleteControlMutation(
|
||||
$input: DeleteControlInput!
|
||||
@@ -148,6 +176,8 @@ export default function FrameworkControlPage({ queryRef }: Props) {
|
||||
);
|
||||
const [detachAudit, isDetachingAudit] = useMutation(detachAuditMutation);
|
||||
const [attachAudit, isAttachingAudit] = useMutation(attachAuditMutation);
|
||||
const [detachSnapshot, isDetachingSnapshot] = useMutation(detachSnapshotMutation);
|
||||
const [attachSnapshot, isAttachingSnapshot] = useMutation(attachSnapshotMutation);
|
||||
const [deleteControl] = useMutation(deleteControlMutation);
|
||||
|
||||
const onDelete = () => {
|
||||
@@ -216,34 +246,51 @@ export default function FrameworkControlPage({ queryRef }: Props) {
|
||||
</div>
|
||||
)}
|
||||
<div className={control.status === "EXCLUDED" ? "opacity-60" : ""}>
|
||||
<div className="text-base">{control.name}</div>
|
||||
<LinkedMeasuresCard
|
||||
variant="card"
|
||||
measures={control.measures?.edges.map((edge) => edge.node) ?? []}
|
||||
params={{ controlId: control.id }}
|
||||
connectionId={control.measures?.__id!}
|
||||
onAttach={attachMeasure}
|
||||
onDetach={detachMeasure}
|
||||
disabled={isAttachingMeasure || isDetachingMeasure}
|
||||
/>
|
||||
<LinkedDocumentsCard
|
||||
variant="card"
|
||||
documents={control.documents?.edges.map((edge) => edge.node) ?? []}
|
||||
params={{ controlId: control.id }}
|
||||
connectionId={control.documents?.__id!}
|
||||
onAttach={attachDocument}
|
||||
onDetach={detachDocument}
|
||||
disabled={isAttachingDocument || isDetachingDocument}
|
||||
/>
|
||||
<LinkedAuditsCard
|
||||
variant="card"
|
||||
audits={control.audits?.edges.map((edge) => edge.node) ?? []}
|
||||
params={{ controlId: control.id }}
|
||||
connectionId={control.audits?.__id!}
|
||||
onAttach={attachAudit}
|
||||
onDetach={detachAudit}
|
||||
disabled={isAttachingAudit || isDetachingAudit}
|
||||
/>
|
||||
<div className="text-base mb-4">{control.name}</div>
|
||||
<div className="mb-4">
|
||||
<LinkedMeasuresCard
|
||||
variant="card"
|
||||
measures={control.measures?.edges.map((edge) => edge.node) ?? []}
|
||||
params={{ controlId: control.id }}
|
||||
connectionId={control.measures?.__id!}
|
||||
onAttach={attachMeasure}
|
||||
onDetach={detachMeasure}
|
||||
disabled={isAttachingMeasure || isDetachingMeasure}
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-4">
|
||||
<LinkedDocumentsCard
|
||||
variant="card"
|
||||
documents={control.documents?.edges.map((edge) => edge.node) ?? []}
|
||||
params={{ controlId: control.id }}
|
||||
connectionId={control.documents?.__id!}
|
||||
onAttach={attachDocument}
|
||||
onDetach={detachDocument}
|
||||
disabled={isAttachingDocument || isDetachingDocument}
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-4">
|
||||
<LinkedAuditsCard
|
||||
variant="card"
|
||||
audits={control.audits?.edges.map((edge) => edge.node) ?? []}
|
||||
params={{ controlId: control.id }}
|
||||
connectionId={control.audits?.__id!}
|
||||
onAttach={attachAudit}
|
||||
onDetach={detachAudit}
|
||||
disabled={isAttachingAudit || isDetachingAudit}
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-4">
|
||||
<LinkedSnapshotsCard
|
||||
variant="card"
|
||||
snapshots={control.snapshots?.edges.map((edge) => edge.node) ?? []}
|
||||
params={{ controlId: control.id }}
|
||||
connectionId={control.snapshots?.__id!}
|
||||
onAttach={attachSnapshot}
|
||||
onDetach={detachSnapshot}
|
||||
disabled={isAttachingSnapshot || isDetachingSnapshot}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,216 @@
|
||||
/**
|
||||
* @generated SignedSource<<a4b20010a96dac4779e4b1576b947e45>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
|
||||
import { ConcreteRequest } from 'relay-runtime';
|
||||
import { FragmentRefs } from "relay-runtime";
|
||||
export type CreateControlSnapshotMappingInput = {
|
||||
controlId: string;
|
||||
snapshotId: string;
|
||||
};
|
||||
export type FrameworkControlPageAttachSnapshotMutation$variables = {
|
||||
connections: ReadonlyArray<string>;
|
||||
input: CreateControlSnapshotMappingInput;
|
||||
};
|
||||
export type FrameworkControlPageAttachSnapshotMutation$data = {
|
||||
readonly createControlSnapshotMapping: {
|
||||
readonly snapshotEdge: {
|
||||
readonly node: {
|
||||
readonly id: string;
|
||||
readonly " $fragmentSpreads": FragmentRefs<"LinkedSnapshotsCardFragment">;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
export type FrameworkControlPageAttachSnapshotMutation = {
|
||||
response: FrameworkControlPageAttachSnapshotMutation$data;
|
||||
variables: FrameworkControlPageAttachSnapshotMutation$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
|
||||
};
|
||||
return {
|
||||
"fragment": {
|
||||
"argumentDefinitions": [
|
||||
(v0/*: any*/),
|
||||
(v1/*: any*/)
|
||||
],
|
||||
"kind": "Fragment",
|
||||
"metadata": null,
|
||||
"name": "FrameworkControlPageAttachSnapshotMutation",
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v2/*: any*/),
|
||||
"concreteType": "CreateControlSnapshotMappingPayload",
|
||||
"kind": "LinkedField",
|
||||
"name": "createControlSnapshotMapping",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "SnapshotEdge",
|
||||
"kind": "LinkedField",
|
||||
"name": "snapshotEdge",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Snapshot",
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v3/*: any*/),
|
||||
{
|
||||
"args": null,
|
||||
"kind": "FragmentSpread",
|
||||
"name": "LinkedSnapshotsCardFragment"
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"type": "Mutation",
|
||||
"abstractKey": null
|
||||
},
|
||||
"kind": "Request",
|
||||
"operation": {
|
||||
"argumentDefinitions": [
|
||||
(v1/*: any*/),
|
||||
(v0/*: any*/)
|
||||
],
|
||||
"kind": "Operation",
|
||||
"name": "FrameworkControlPageAttachSnapshotMutation",
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v2/*: any*/),
|
||||
"concreteType": "CreateControlSnapshotMappingPayload",
|
||||
"kind": "LinkedField",
|
||||
"name": "createControlSnapshotMapping",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "SnapshotEdge",
|
||||
"kind": "LinkedField",
|
||||
"name": "snapshotEdge",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Snapshot",
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v3/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "name",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "description",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "type",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "createdAt",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"filters": null,
|
||||
"handle": "prependEdge",
|
||||
"key": "",
|
||||
"kind": "LinkedHandle",
|
||||
"name": "snapshotEdge",
|
||||
"handleArgs": [
|
||||
{
|
||||
"kind": "Variable",
|
||||
"name": "connections",
|
||||
"variableName": "connections"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "52c76e336bb7f38dc2d2f6620817100a",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "FrameworkControlPageAttachSnapshotMutation",
|
||||
"operationKind": "mutation",
|
||||
"text": "mutation FrameworkControlPageAttachSnapshotMutation(\n $input: CreateControlSnapshotMappingInput!\n) {\n createControlSnapshotMapping(input: $input) {\n snapshotEdge {\n node {\n id\n ...LinkedSnapshotsCardFragment\n }\n }\n }\n}\n\nfragment LinkedSnapshotsCardFragment on Snapshot {\n id\n name\n description\n type\n createdAt\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "9e8ad62cc8d9f3672e1f785c31a91624";
|
||||
|
||||
export default node;
|
||||
@@ -0,0 +1,133 @@
|
||||
/**
|
||||
* @generated SignedSource<<d4c60256aa53236cfb4c3a01f4fd35c1>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
|
||||
import { ConcreteRequest } from 'relay-runtime';
|
||||
export type DeleteControlSnapshotMappingInput = {
|
||||
controlId: string;
|
||||
snapshotId: string;
|
||||
};
|
||||
export type FrameworkControlPageDetachSnapshotMutation$variables = {
|
||||
connections: ReadonlyArray<string>;
|
||||
input: DeleteControlSnapshotMappingInput;
|
||||
};
|
||||
export type FrameworkControlPageDetachSnapshotMutation$data = {
|
||||
readonly deleteControlSnapshotMapping: {
|
||||
readonly deletedSnapshotId: string;
|
||||
};
|
||||
};
|
||||
export type FrameworkControlPageDetachSnapshotMutation = {
|
||||
response: FrameworkControlPageDetachSnapshotMutation$data;
|
||||
variables: FrameworkControlPageDetachSnapshotMutation$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": "deletedSnapshotId",
|
||||
"storageKey": null
|
||||
};
|
||||
return {
|
||||
"fragment": {
|
||||
"argumentDefinitions": [
|
||||
(v0/*: any*/),
|
||||
(v1/*: any*/)
|
||||
],
|
||||
"kind": "Fragment",
|
||||
"metadata": null,
|
||||
"name": "FrameworkControlPageDetachSnapshotMutation",
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v2/*: any*/),
|
||||
"concreteType": "DeleteControlSnapshotMappingPayload",
|
||||
"kind": "LinkedField",
|
||||
"name": "deleteControlSnapshotMapping",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v3/*: any*/)
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"type": "Mutation",
|
||||
"abstractKey": null
|
||||
},
|
||||
"kind": "Request",
|
||||
"operation": {
|
||||
"argumentDefinitions": [
|
||||
(v1/*: any*/),
|
||||
(v0/*: any*/)
|
||||
],
|
||||
"kind": "Operation",
|
||||
"name": "FrameworkControlPageDetachSnapshotMutation",
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v2/*: any*/),
|
||||
"concreteType": "DeleteControlSnapshotMappingPayload",
|
||||
"kind": "LinkedField",
|
||||
"name": "deleteControlSnapshotMapping",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v3/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"filters": null,
|
||||
"handle": "deleteEdge",
|
||||
"key": "",
|
||||
"kind": "ScalarHandle",
|
||||
"name": "deletedSnapshotId",
|
||||
"handleArgs": [
|
||||
{
|
||||
"kind": "Variable",
|
||||
"name": "connections",
|
||||
"variableName": "connections"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "610636745f2c0441c54bd0028fc52cf0",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "FrameworkControlPageDetachSnapshotMutation",
|
||||
"operationKind": "mutation",
|
||||
"text": "mutation FrameworkControlPageDetachSnapshotMutation(\n $input: DeleteControlSnapshotMappingInput!\n) {\n deleteControlSnapshotMapping(input: $input) {\n deletedSnapshotId\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "be8d40beadabe60d8c9bee4d99b885b7";
|
||||
|
||||
export default node;
|
||||
@@ -0,0 +1,39 @@
|
||||
import { useEffect } from "react";
|
||||
import { useNavigate, useParams } from "react-router";
|
||||
import { usePreloadedQuery, type PreloadedQuery } from "react-relay";
|
||||
import { snapshotNodeQuery } from "/hooks/graph/SnapshotGraph";
|
||||
import type { SnapshotGraphNodeQuery } from "/hooks/graph/__generated__/SnapshotGraphNodeQuery.graphql";
|
||||
import { useOrganizationId } from "/hooks/useOrganizationId";
|
||||
import { PageError } from "/components/PageError";
|
||||
import { getSnapshotTypeUrlPath } from "@probo/helpers";
|
||||
|
||||
type Props = {
|
||||
queryRef: PreloadedQuery<SnapshotGraphNodeQuery>;
|
||||
};
|
||||
|
||||
export default function SnapshotDetailPage({ queryRef }: Props) {
|
||||
const navigate = useNavigate();
|
||||
const organizationId = useOrganizationId();
|
||||
const { snapshotId } = useParams();
|
||||
const data = usePreloadedQuery(snapshotNodeQuery, queryRef);
|
||||
|
||||
useEffect(() => {
|
||||
if (!data.node || !data.node.type) {
|
||||
return;
|
||||
}
|
||||
|
||||
const snapshot = data.node;
|
||||
const snapshotType = snapshot.type;
|
||||
const urlPath = getSnapshotTypeUrlPath(snapshotType);
|
||||
|
||||
navigate(`/organizations/${organizationId}/snapshots/${snapshotId}${urlPath}`, {
|
||||
replace: true,
|
||||
});
|
||||
}, [data.node, navigate, organizationId, snapshotId]);
|
||||
|
||||
if (!data.node || !data.node.type) {
|
||||
return <PageError />;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -5,9 +5,10 @@ import {
|
||||
type PreloadedQuery,
|
||||
} from "react-relay";
|
||||
import { useTranslate } from "@probo/i18n";
|
||||
import { getSnapshotTypeLabel } from "@probo/helpers";
|
||||
import { getSnapshotTypeLabel, getSnapshotTypeUrlPath } from "@probo/helpers";
|
||||
import {
|
||||
ActionDropdown,
|
||||
Badge,
|
||||
Button,
|
||||
DropdownItem,
|
||||
IconPlusLarge,
|
||||
@@ -131,28 +132,15 @@ function SnapshotRow(props: SnapshotRowProps) {
|
||||
const { __, dateFormat } = useTranslate();
|
||||
const deleteSnapshot = useDeleteSnapshot(props.snapshot, props.connectionId);
|
||||
|
||||
const getSnapshotUrl = (snapshot: SnapshotRowProps["snapshot"]) => {
|
||||
const baseUrl = `/organizations/${props.organizationId}/snapshots/${snapshot.id}`;
|
||||
|
||||
switch (snapshot.type) {
|
||||
case "DATA":
|
||||
return `${baseUrl}/data`;
|
||||
case "VENDORS":
|
||||
return `${baseUrl}/vendors`;
|
||||
case "RISKS":
|
||||
return `${baseUrl}/risks`;
|
||||
case "ASSETS":
|
||||
return `${baseUrl}/assets`;
|
||||
default:
|
||||
return baseUrl;
|
||||
}
|
||||
};
|
||||
const typePath = getSnapshotTypeUrlPath(props.snapshot.type);
|
||||
|
||||
return (
|
||||
<Tr to={getSnapshotUrl(props.snapshot)}>
|
||||
<Tr to={`/organizations/${props.organizationId}/snapshots/${props.snapshot.id}${typePath}`}>
|
||||
<Td className="font-medium">{props.snapshot.name}</Td>
|
||||
<Td className="text-txt-secondary">
|
||||
{getSnapshotTypeLabel(__, props.snapshot.type)}
|
||||
<Td>
|
||||
<Badge variant="neutral">
|
||||
{getSnapshotTypeLabel(__, props.snapshot.type)}
|
||||
</Badge>
|
||||
</Td>
|
||||
<Td className="text-txt-secondary">
|
||||
{props.snapshot.description || __("No description")}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { loadQuery } from "react-relay";
|
||||
import { PageSkeleton } from "/components/skeletons/PageSkeleton";
|
||||
import { relayEnvironment } from "/providers/RelayProviders";
|
||||
import { snapshotsQuery } from "/hooks/graph/SnapshotGraph";
|
||||
import { snapshotsQuery, snapshotNodeQuery } from "/hooks/graph/SnapshotGraph";
|
||||
import type { AppRoute } from "/routes";
|
||||
import { lazy } from "@probo/react-lazy";
|
||||
|
||||
@@ -15,4 +15,13 @@ export const snapshotsRoutes = [
|
||||
() => import("/pages/organizations/snapshots/SnapshotsPage")
|
||||
),
|
||||
},
|
||||
{
|
||||
path: "snapshots/:snapshotId",
|
||||
fallback: PageSkeleton,
|
||||
queryLoader: ({ snapshotId }) =>
|
||||
loadQuery(relayEnvironment, snapshotNodeQuery, { snapshotId }),
|
||||
Component: lazy(
|
||||
() => import("/pages/organizations/snapshots/SnapshotDetailPage")
|
||||
),
|
||||
},
|
||||
] satisfies AppRoute[];
|
||||
|
||||
Reference in New Issue
Block a user