Add evidence type link
close #44 Signed-off-by: gearnode <bryan@frimin.fr>
This commit is contained in:
@@ -20,7 +20,6 @@ import {
|
||||
CheckCircle2,
|
||||
Plus,
|
||||
Trash2,
|
||||
Upload,
|
||||
FileIcon,
|
||||
Loader2,
|
||||
ChevronDown,
|
||||
@@ -34,6 +33,7 @@ import {
|
||||
UserPlus,
|
||||
UserMinus,
|
||||
User,
|
||||
Link2,
|
||||
} from "lucide-react";
|
||||
import { Card, CardContent } from "@/components/ui/card";
|
||||
import { useToast } from "@/hooks/use-toast";
|
||||
@@ -60,6 +60,9 @@ import {
|
||||
SelectTrigger,
|
||||
} from "@/components/ui/select";
|
||||
import ReactMarkdown from "react-markdown";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||
import { Label } from "@/components/ui/label";
|
||||
|
||||
import { Helmet } from "react-helmet-async";
|
||||
import type { ControlOverviewPageQuery as ControlOverviewPageQueryType } from "./__generated__/ControlOverviewPageQuery.graphql";
|
||||
@@ -72,7 +75,6 @@ import type { ControlOverviewPageAssignTaskMutation as ControlOverviewPageAssign
|
||||
import type { ControlOverviewPageUnassignTaskMutation as ControlOverviewPageUnassignTaskMutationType } from "./__generated__/ControlOverviewPageUnassignTaskMutation.graphql";
|
||||
import type { ControlOverviewPageOrganizationQuery$data } from "./__generated__/ControlOverviewPageOrganizationQuery.graphql";
|
||||
import type { ControlOverviewPageUpdateControlStateMutation as ControlOverviewPageUpdateControlStateMutationType } from "./__generated__/ControlOverviewPageUpdateControlStateMutation.graphql";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
|
||||
// Function to format ISO8601 duration to human-readable format
|
||||
const formatDuration = (isoDuration: string): string => {
|
||||
@@ -147,6 +149,8 @@ const controlOverviewPageQuery = graphql`
|
||||
filename
|
||||
size
|
||||
state
|
||||
type
|
||||
url
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
@@ -221,6 +225,8 @@ const uploadEvidenceMutation = graphql`
|
||||
filename
|
||||
fileUrl
|
||||
mimeType
|
||||
type
|
||||
url
|
||||
size
|
||||
state
|
||||
createdAt
|
||||
@@ -496,6 +502,13 @@ function ControlOverviewPageContent({
|
||||
[key: string]: string;
|
||||
}>({});
|
||||
|
||||
// Add state variables for the evidence dialog and link evidence
|
||||
const [evidenceDialogOpen, setEvidenceDialogOpen] = useState(false);
|
||||
const [linkEvidenceName, setLinkEvidenceName] = useState("");
|
||||
const [linkEvidenceUrl, setLinkEvidenceUrl] = useState("");
|
||||
const [linkEvidenceDescription, setLinkEvidenceDescription] = useState("");
|
||||
const [activeTab, setActiveTab] = useState<"file" | "link">("file");
|
||||
|
||||
const tasks = data.control.tasks?.edges.map((edge) => edge.node) || [];
|
||||
|
||||
const getEvidenceConnectionId = useCallback(
|
||||
@@ -701,10 +714,12 @@ function ControlOverviewPageContent({
|
||||
|
||||
const handleUploadEvidence = (taskId: string, taskName: string) => {
|
||||
setTaskForEvidence({ id: taskId, name: taskName });
|
||||
// Instead of opening a modal, directly trigger the file input click
|
||||
if (hiddenFileInputRef.current) {
|
||||
hiddenFileInputRef.current.click();
|
||||
}
|
||||
setEvidenceDialogOpen(true);
|
||||
// Reset form fields
|
||||
setLinkEvidenceName("");
|
||||
setLinkEvidenceUrl("");
|
||||
setLinkEvidenceDescription("");
|
||||
setActiveTab("file");
|
||||
};
|
||||
|
||||
const handleFileSelected = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
@@ -713,10 +728,10 @@ function ControlOverviewPageContent({
|
||||
|
||||
const file = e.target.files[0];
|
||||
|
||||
// Show toast for upload started
|
||||
// Show toast for add started
|
||||
toast({
|
||||
title: "Upload started",
|
||||
description: `Uploading ${file.name}...`,
|
||||
title: "Adding document",
|
||||
description: `Adding ${file.name}...`,
|
||||
variant: "default",
|
||||
});
|
||||
|
||||
@@ -728,7 +743,9 @@ function ControlOverviewPageContent({
|
||||
input: {
|
||||
taskId: taskForEvidence.id,
|
||||
name: file.name,
|
||||
type: "FILE",
|
||||
file: null,
|
||||
description: "Document evidence",
|
||||
},
|
||||
connections: evidenceConnectionId ? [evidenceConnectionId] : [],
|
||||
},
|
||||
@@ -737,8 +754,8 @@ function ControlOverviewPageContent({
|
||||
},
|
||||
onCompleted: () => {
|
||||
toast({
|
||||
title: "Evidence uploaded",
|
||||
description: "Evidence has been uploaded successfully.",
|
||||
title: "Document added",
|
||||
description: "Document evidence has been added successfully.",
|
||||
variant: "default",
|
||||
});
|
||||
setTaskForEvidence(null);
|
||||
@@ -749,7 +766,81 @@ function ControlOverviewPageContent({
|
||||
},
|
||||
onError: (error) => {
|
||||
toast({
|
||||
title: "Error uploading evidence",
|
||||
title: "Error adding document",
|
||||
description: error.message,
|
||||
variant: "destructive",
|
||||
});
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const handleLinkEvidenceSubmit = () => {
|
||||
if (!taskForEvidence) return;
|
||||
|
||||
// Validate form
|
||||
if (!linkEvidenceName.trim()) {
|
||||
toast({
|
||||
title: "Error",
|
||||
description: "Please provide a name for the evidence",
|
||||
variant: "destructive",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (!linkEvidenceUrl.trim()) {
|
||||
toast({
|
||||
title: "Error",
|
||||
description: "Please provide a URL for the evidence",
|
||||
variant: "destructive",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Description is now optional for link evidence
|
||||
// Remove the validation check for empty description
|
||||
|
||||
// Show toast for add started
|
||||
toast({
|
||||
title: "Adding link evidence",
|
||||
description: `Adding ${linkEvidenceName}...`,
|
||||
variant: "default",
|
||||
});
|
||||
|
||||
// Get the evidence connection ID for this task
|
||||
const evidenceConnectionId = getEvidenceConnectionId(taskForEvidence.id);
|
||||
|
||||
// Use a default description if none is provided
|
||||
const description =
|
||||
linkEvidenceDescription.trim() || `Link to ${linkEvidenceUrl}`;
|
||||
|
||||
uploadEvidence({
|
||||
variables: {
|
||||
input: {
|
||||
taskId: taskForEvidence.id,
|
||||
name: linkEvidenceName,
|
||||
type: "LINK",
|
||||
url: linkEvidenceUrl,
|
||||
description: description,
|
||||
file: null,
|
||||
},
|
||||
connections: evidenceConnectionId ? [evidenceConnectionId] : [],
|
||||
},
|
||||
onCompleted: () => {
|
||||
toast({
|
||||
title: "Link evidence added",
|
||||
description: "Link evidence has been added successfully.",
|
||||
variant: "default",
|
||||
});
|
||||
setTaskForEvidence(null);
|
||||
setEvidenceDialogOpen(false);
|
||||
// Reset form fields
|
||||
setLinkEvidenceName("");
|
||||
setLinkEvidenceUrl("");
|
||||
setLinkEvidenceDescription("");
|
||||
},
|
||||
onError: (error) => {
|
||||
toast({
|
||||
title: "Error adding link evidence",
|
||||
description: error.message,
|
||||
variant: "destructive",
|
||||
});
|
||||
@@ -783,10 +874,10 @@ function ControlOverviewPageContent({
|
||||
const file = files[0];
|
||||
setUploadingTaskId(taskId);
|
||||
|
||||
// Show toast for upload started
|
||||
// Show toast for add started
|
||||
toast({
|
||||
title: "Upload started",
|
||||
description: `Uploading ${file.name}...`,
|
||||
title: "Adding document",
|
||||
description: `Adding ${file.name}...`,
|
||||
variant: "default",
|
||||
});
|
||||
|
||||
@@ -798,7 +889,9 @@ function ControlOverviewPageContent({
|
||||
input: {
|
||||
taskId: taskId,
|
||||
name: file.name,
|
||||
type: "FILE",
|
||||
file: null,
|
||||
description: "Document evidence",
|
||||
},
|
||||
connections: evidenceConnectionId ? [evidenceConnectionId] : [],
|
||||
},
|
||||
@@ -808,15 +901,15 @@ function ControlOverviewPageContent({
|
||||
onCompleted: () => {
|
||||
setUploadingTaskId(null);
|
||||
toast({
|
||||
title: "Evidence uploaded",
|
||||
description: "Evidence has been uploaded successfully.",
|
||||
title: "Document added",
|
||||
description: "Document evidence has been added successfully.",
|
||||
variant: "default",
|
||||
});
|
||||
},
|
||||
onError: (error) => {
|
||||
setUploadingTaskId(null);
|
||||
toast({
|
||||
title: "Error uploading evidence",
|
||||
title: "Error adding document",
|
||||
description: error.message,
|
||||
variant: "destructive",
|
||||
});
|
||||
@@ -850,9 +943,11 @@ function ControlOverviewPageContent({
|
||||
}
|
||||
};
|
||||
|
||||
// Function to get file icon based on mime type
|
||||
const getFileIcon = (mimeType: string) => {
|
||||
if (mimeType.startsWith("image/")) {
|
||||
// Function to get file icon based on mime type and evidence type
|
||||
const getFileIcon = (mimeType: string, evidenceType: string) => {
|
||||
if (evidenceType === "LINK") {
|
||||
return <Link2 className="w-4 h-4 text-blue-600" />;
|
||||
} else if (mimeType.startsWith("image/")) {
|
||||
return <Image className="w-4 h-4 text-blue-500" />;
|
||||
} else if (mimeType.includes("pdf")) {
|
||||
return <FileText className="w-4 h-4 text-red-500" />;
|
||||
@@ -1088,7 +1183,7 @@ function ControlOverviewPageContent({
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="text-sm text-gray-500 flex items-center bg-gray-50 px-3 py-1.5 rounded-md border border-gray-200">
|
||||
<FileIcon className="w-4 h-4 mr-2 text-blue-500" />
|
||||
<span>Drag & drop files onto tasks to upload evidence</span>
|
||||
<span>Drag & drop files onto tasks to add evidence</span>
|
||||
</div>
|
||||
<Dialog
|
||||
open={isCreateTaskOpen}
|
||||
@@ -1246,9 +1341,9 @@ function ControlOverviewPageContent({
|
||||
{draggedOverTaskId === task?.id && (
|
||||
<div className="absolute inset-0 flex items-center justify-center rounded-md z-10 bg-blue-50 bg-opacity-90 backdrop-blur-sm border-2 border-dashed border-blue-400">
|
||||
<div className="flex items-center gap-2 text-blue-600 bg-white p-5 rounded-lg shadow-md">
|
||||
<Upload className="w-4 h-4 text-blue-500" />
|
||||
<FileText className="w-4 h-4 text-blue-500" />
|
||||
<p className="text-sm font-medium text-center">
|
||||
Drop file to upload evidence
|
||||
Drop file to add as evidence
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1258,7 +1353,7 @@ function ControlOverviewPageContent({
|
||||
<div className="absolute inset-0 flex items-center justify-center bg-white bg-opacity-95 rounded-md z-10 backdrop-blur-sm">
|
||||
<div className="flex flex-col items-center gap-3 text-blue-600">
|
||||
<Loader2 className="w-10 h-10 animate-spin text-blue-500" />
|
||||
<p className="font-medium">Uploading evidence...</p>
|
||||
<p className="font-medium">Adding document...</p>
|
||||
<p className="text-sm text-gray-500">Please wait</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1491,8 +1586,9 @@ function ControlOverviewPageContent({
|
||||
handleUploadEvidence(task.id, task.name);
|
||||
}
|
||||
}}
|
||||
title="Add Evidence"
|
||||
>
|
||||
<Upload className="w-4 h-4" />
|
||||
<FileText className="w-4 h-4" />
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
@@ -1547,17 +1643,31 @@ function ControlOverviewPageContent({
|
||||
>
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="bg-white p-2 rounded-md border border-gray-200">
|
||||
{getFileIcon(evidence.mimeType)}
|
||||
{getFileIcon(
|
||||
evidence.mimeType,
|
||||
evidence.type
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
<div className="text-sm font-medium text-gray-800">
|
||||
{evidence.filename}
|
||||
</div>
|
||||
<div className="text-xs text-gray-500 flex items-center gap-2 mt-0.5">
|
||||
<span className="font-medium text-gray-600">
|
||||
{formatFileSize(evidence.size)}
|
||||
</span>
|
||||
<span>•</span>
|
||||
{evidence.type === "FILE" ? (
|
||||
<>
|
||||
<span className="font-medium text-gray-600">
|
||||
{formatFileSize(evidence.size)}
|
||||
</span>
|
||||
<span>•</span>
|
||||
</>
|
||||
) : evidence.url ? (
|
||||
<>
|
||||
<span className="font-medium text-blue-600 truncate max-w-[200px]">
|
||||
{evidence.url}
|
||||
</span>
|
||||
<span>•</span>
|
||||
</>
|
||||
) : null}
|
||||
<span>
|
||||
{formatDate(evidence.createdAt)}
|
||||
</span>
|
||||
@@ -1565,38 +1675,45 @@ function ControlOverviewPageContent({
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-1">
|
||||
{evidence.mimeType.startsWith("image/") ? (
|
||||
<button
|
||||
onClick={() =>
|
||||
handlePreviewEvidence(evidence)
|
||||
}
|
||||
className="p-1.5 rounded-full hover:bg-white hover:shadow-sm transition-all"
|
||||
title="Preview Image"
|
||||
>
|
||||
<Eye className="w-4 h-4 text-blue-600" />
|
||||
</button>
|
||||
) : (
|
||||
{evidence.type === "FILE" ? (
|
||||
<>
|
||||
{evidence.mimeType.startsWith("image/") ? (
|
||||
<button
|
||||
onClick={() =>
|
||||
handlePreviewEvidence(evidence)
|
||||
}
|
||||
className="p-1.5 rounded-full hover:bg-white hover:shadow-sm transition-all"
|
||||
title="Preview Image"
|
||||
>
|
||||
<Eye className="w-4 h-4 text-blue-600" />
|
||||
</button>
|
||||
) : (
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
handlePreviewEvidence(evidence);
|
||||
}}
|
||||
className="p-1.5 rounded-full hover:bg-white hover:shadow-sm transition-all"
|
||||
title="Download"
|
||||
>
|
||||
<Download className="w-4 h-4 text-blue-600" />
|
||||
</button>
|
||||
)}
|
||||
</>
|
||||
) : evidence.url ? (
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
handlePreviewEvidence(evidence);
|
||||
if (evidence.url) {
|
||||
window.open(evidence.url, "_blank");
|
||||
}
|
||||
}}
|
||||
className="p-1.5 rounded-full hover:bg-white hover:shadow-sm transition-all"
|
||||
title="Download"
|
||||
title="Open Link"
|
||||
>
|
||||
<Download className="w-4 h-4 text-blue-600" />
|
||||
<Link2 className="w-4 h-4 text-blue-600" />
|
||||
</button>
|
||||
)}
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
handlePreviewEvidence(evidence);
|
||||
}}
|
||||
className="p-1.5 rounded-full hover:bg-white hover:shadow-sm transition-all"
|
||||
title="Download"
|
||||
>
|
||||
<Download className="w-4 h-4 text-blue-600" />
|
||||
</button>
|
||||
) : null}
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
@@ -1632,6 +1749,99 @@ function ControlOverviewPageContent({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Evidence Add Dialog */}
|
||||
<Dialog open={evidenceDialogOpen} onOpenChange={setEvidenceDialogOpen}>
|
||||
<DialogContent className="sm:max-w-[525px]">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Add Evidence</DialogTitle>
|
||||
<DialogDescription>
|
||||
Choose the type of evidence you want to add to this task.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<Tabs
|
||||
value={activeTab}
|
||||
onValueChange={(value: string) =>
|
||||
setActiveTab(value as "file" | "link")
|
||||
}
|
||||
>
|
||||
<TabsList className="grid w-full grid-cols-2">
|
||||
<TabsTrigger value="file">Document</TabsTrigger>
|
||||
<TabsTrigger value="link">Link</TabsTrigger>
|
||||
</TabsList>
|
||||
|
||||
<TabsContent value="file" className="space-y-4">
|
||||
<div className="space-y-4 pt-4">
|
||||
<p>Select a document to add as evidence.</p>
|
||||
<Button
|
||||
onClick={() => {
|
||||
if (hiddenFileInputRef.current) {
|
||||
hiddenFileInputRef.current.click();
|
||||
setEvidenceDialogOpen(false);
|
||||
}
|
||||
}}
|
||||
className="w-full"
|
||||
>
|
||||
Select Document
|
||||
</Button>
|
||||
</div>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="link" className="space-y-4 pt-4">
|
||||
<div className="space-y-4">
|
||||
<div className="grid w-full items-center gap-1.5">
|
||||
<Label htmlFor="evidence-name">Name</Label>
|
||||
<Input
|
||||
id="evidence-name"
|
||||
value={linkEvidenceName}
|
||||
onChange={(e) => setLinkEvidenceName(e.target.value)}
|
||||
placeholder="Name for this evidence"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="grid w-full items-center gap-1.5">
|
||||
<Label htmlFor="evidence-url">URL</Label>
|
||||
<Input
|
||||
id="evidence-url"
|
||||
value={linkEvidenceUrl}
|
||||
onChange={(e) => setLinkEvidenceUrl(e.target.value)}
|
||||
placeholder="https://example.com"
|
||||
type="url"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="grid w-full items-center gap-1.5">
|
||||
<Label htmlFor="evidence-description">
|
||||
Description (optional)
|
||||
</Label>
|
||||
<Textarea
|
||||
id="evidence-description"
|
||||
value={linkEvidenceDescription}
|
||||
onChange={(e) =>
|
||||
setLinkEvidenceDescription(e.target.value)
|
||||
}
|
||||
placeholder="Describe this evidence (optional)"
|
||||
className="min-h-[100px]"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
|
||||
<DialogFooter>
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => setEvidenceDialogOpen(false)}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
{activeTab === "link" && (
|
||||
<Button onClick={handleLinkEvidenceSubmit}>Add Link</Button>
|
||||
)}
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
{/* Hidden file input for direct uploads */}
|
||||
<input
|
||||
type="file"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<4cf4f895bdcd936c74cb70f562210df7>>
|
||||
* @generated SignedSource<<5fff8009247229346c3cda94359f2129>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -14,7 +14,7 @@ export type ControlOverviewPageGetEvidenceFileUrlQuery$variables = {
|
||||
};
|
||||
export type ControlOverviewPageGetEvidenceFileUrlQuery$data = {
|
||||
readonly node: {
|
||||
readonly fileUrl?: string;
|
||||
readonly fileUrl?: string | null | undefined;
|
||||
readonly id?: string;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<084485ae03f7089bfdee310d631b01eb>>
|
||||
* @generated SignedSource<<e273ee54aacd3db274341d21b33809b2>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -12,6 +12,7 @@ import { ConcreteRequest } from 'relay-runtime';
|
||||
export type ControlImportance = "ADVANCED" | "MANDATORY" | "PREFERRED";
|
||||
export type ControlState = "IMPLEMENTED" | "IN_PROGRESS" | "NOT_APPLICABLE" | "NOT_STARTED";
|
||||
export type EvidenceState = "EXPIRED" | "INVALID" | "VALID";
|
||||
export type EvidenceType = "FILE" | "LINK";
|
||||
export type TaskState = "DONE" | "TODO";
|
||||
export type ControlOverviewPageQuery$variables = {
|
||||
controlId: string;
|
||||
@@ -44,6 +45,8 @@ export type ControlOverviewPageQuery$data = {
|
||||
readonly mimeType: string;
|
||||
readonly size: number;
|
||||
readonly state: EvidenceState;
|
||||
readonly type: EvidenceType;
|
||||
readonly url: string | null | undefined;
|
||||
};
|
||||
}>;
|
||||
};
|
||||
@@ -251,6 +254,20 @@ v15 = [
|
||||
"storageKey": null
|
||||
},
|
||||
(v5/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "type",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "url",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
@@ -480,7 +497,7 @@ return {
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "4bcea497959829f998cdab71797c8675",
|
||||
"cacheID": "6f419912ad357b36c51113ef7672ad51",
|
||||
"id": null,
|
||||
"metadata": {
|
||||
"connection": [
|
||||
@@ -503,11 +520,11 @@ return {
|
||||
},
|
||||
"name": "ControlOverviewPageQuery",
|
||||
"operationKind": "query",
|
||||
"text": "query ControlOverviewPageQuery(\n $controlId: ID!\n) {\n control: node(id: $controlId) {\n __typename\n id\n ... on Control {\n name\n description\n state\n importance\n category\n version\n tasks(first: 100) {\n edges {\n node {\n id\n name\n description\n state\n timeEstimate\n version\n assignedTo {\n id\n fullName\n primaryEmailAddress\n }\n evidences(first: 50) {\n edges {\n node {\n id\n mimeType\n filename\n size\n state\n createdAt\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n }\n}\n"
|
||||
"text": "query ControlOverviewPageQuery(\n $controlId: ID!\n) {\n control: node(id: $controlId) {\n __typename\n id\n ... on Control {\n name\n description\n state\n importance\n category\n version\n tasks(first: 100) {\n edges {\n node {\n id\n name\n description\n state\n timeEstimate\n version\n assignedTo {\n id\n fullName\n primaryEmailAddress\n }\n evidences(first: 50) {\n edges {\n node {\n id\n mimeType\n filename\n size\n state\n type\n url\n createdAt\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "4710a9799b3daf286afdd430f026e6c2";
|
||||
(node as any).hash = "59a0c6e5a414410be244c7a62bba7696";
|
||||
|
||||
export default node;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<313084c3c2422d51df42fe4d6b848d49>>
|
||||
* @generated SignedSource<<6726ce2446381674b1992ece913fd680>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -10,10 +10,14 @@
|
||||
|
||||
import { ConcreteRequest } from 'relay-runtime';
|
||||
export type EvidenceState = "EXPIRED" | "INVALID" | "VALID";
|
||||
export type EvidenceType = "FILE" | "LINK";
|
||||
export type UploadEvidenceInput = {
|
||||
file: any;
|
||||
description: string;
|
||||
file?: any | null | undefined;
|
||||
name: string;
|
||||
taskId: string;
|
||||
type: EvidenceType;
|
||||
url?: string | null | undefined;
|
||||
};
|
||||
export type ControlOverviewPageUploadEvidenceMutation$variables = {
|
||||
connections: ReadonlyArray<string>;
|
||||
@@ -24,12 +28,14 @@ export type ControlOverviewPageUploadEvidenceMutation$data = {
|
||||
readonly evidenceEdge: {
|
||||
readonly node: {
|
||||
readonly createdAt: string;
|
||||
readonly fileUrl: string;
|
||||
readonly fileUrl: string | null | undefined;
|
||||
readonly filename: string;
|
||||
readonly id: string;
|
||||
readonly mimeType: string;
|
||||
readonly size: number;
|
||||
readonly state: EvidenceState;
|
||||
readonly type: EvidenceType;
|
||||
readonly url: string | null | undefined;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -101,6 +107,20 @@ v3 = {
|
||||
"name": "mimeType",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "type",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "url",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
@@ -194,16 +214,16 @@ return {
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "5edaf64bde176530d9952e3e8aeb15af",
|
||||
"cacheID": "de3681706266cd453ddccb5fe2900ea8",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "ControlOverviewPageUploadEvidenceMutation",
|
||||
"operationKind": "mutation",
|
||||
"text": "mutation ControlOverviewPageUploadEvidenceMutation(\n $input: UploadEvidenceInput!\n) {\n uploadEvidence(input: $input) {\n evidenceEdge {\n node {\n id\n filename\n fileUrl\n mimeType\n size\n state\n createdAt\n }\n }\n }\n}\n"
|
||||
"text": "mutation ControlOverviewPageUploadEvidenceMutation(\n $input: UploadEvidenceInput!\n) {\n uploadEvidence(input: $input) {\n evidenceEdge {\n node {\n id\n filename\n fileUrl\n mimeType\n type\n url\n size\n state\n createdAt\n }\n }\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "51f35fe735a747ddaeb0f0cfa298f7e2";
|
||||
(node as any).hash = "396146017c07e06dc709199a0b5ad012";
|
||||
|
||||
export default node;
|
||||
|
||||
Reference in New Issue
Block a user