Move evidence to measure level

Signed-off-by: Bryan Frimin <bryan@getprobo.com>
This commit is contained in:
Bryan Frimin
2025-05-03 16:57:51 -07:00
parent 5b65109387
commit 3bfb3ba485
14 changed files with 4568 additions and 1633 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
/** /**
* @generated SignedSource<<63dbc912431a9ea23a2ce515ba95af86>> * @generated SignedSource<<03d8e2eca1cc7ffaf797c66ef7fa11c1>>
* @lightSyntaxTransform * @lightSyntaxTransform
* @nogrep * @nogrep
*/ */
@@ -20,6 +20,22 @@ export type MeasureViewQuery$data = {
readonly measure: { readonly measure: {
readonly category?: string; readonly category?: string;
readonly description?: string; readonly description?: string;
readonly evidences?: {
readonly __id: string;
readonly edges: ReadonlyArray<{
readonly node: {
readonly createdAt: string;
readonly description: string;
readonly filename: string;
readonly id: string;
readonly mimeType: string;
readonly size: number;
readonly state: EvidenceState;
readonly type: EvidenceType;
readonly url: string | null | undefined;
};
}>;
};
readonly id: string; readonly id: string;
readonly name?: string; readonly name?: string;
readonly state?: MeasureState; readonly state?: MeasureState;
@@ -114,53 +130,20 @@ v6 = {
"storageKey": null "storageKey": null
}, },
v7 = { v7 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "timeEstimate",
"storageKey": null
},
v8 = {
"alias": null,
"args": null,
"concreteType": "People",
"kind": "LinkedField",
"name": "assignedTo",
"plural": false,
"selections": [
(v2/*: any*/),
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "fullName",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "primaryEmailAddress",
"storageKey": null
}
],
"storageKey": null
},
v9 = {
"alias": null, "alias": null,
"args": null, "args": null,
"kind": "ScalarField", "kind": "ScalarField",
"name": "__typename", "name": "__typename",
"storageKey": null "storageKey": null
}, },
v10 = { v8 = {
"alias": null, "alias": null,
"args": null, "args": null,
"kind": "ScalarField", "kind": "ScalarField",
"name": "cursor", "name": "cursor",
"storageKey": null "storageKey": null
}, },
v11 = { v9 = {
"alias": null, "alias": null,
"args": null, "args": null,
"concreteType": "PageInfo", "concreteType": "PageInfo",
@@ -185,7 +168,7 @@ v11 = {
], ],
"storageKey": null "storageKey": null
}, },
v12 = { v10 = {
"kind": "ClientExtension", "kind": "ClientExtension",
"selections": [ "selections": [
{ {
@@ -197,7 +180,7 @@ v12 = {
} }
] ]
}, },
v13 = [ v11 = [
{ {
"alias": null, "alias": null,
"args": null, "args": null,
@@ -259,17 +242,50 @@ v13 = [
"storageKey": null "storageKey": null
}, },
(v4/*: any*/), (v4/*: any*/),
(v9/*: any*/) (v7/*: any*/)
], ],
"storageKey": null "storageKey": null
}, },
(v10/*: any*/) (v8/*: any*/)
], ],
"storageKey": null "storageKey": null
}, },
(v11/*: any*/), (v9/*: any*/),
(v12/*: any*/) (v10/*: any*/)
], ],
v12 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "timeEstimate",
"storageKey": null
},
v13 = {
"alias": null,
"args": null,
"concreteType": "People",
"kind": "LinkedField",
"name": "assignedTo",
"plural": false,
"selections": [
(v2/*: any*/),
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "fullName",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "primaryEmailAddress",
"storageKey": null
}
],
"storageKey": null
},
v14 = [ v14 = [
{ {
"kind": "Literal", "kind": "Literal",
@@ -307,6 +323,16 @@ return {
(v4/*: any*/), (v4/*: any*/),
(v5/*: any*/), (v5/*: any*/),
(v6/*: any*/), (v6/*: any*/),
{
"alias": "evidences",
"args": null,
"concreteType": "EvidenceConnection",
"kind": "LinkedField",
"name": "__MeasureView_evidences_connection",
"plural": false,
"selections": (v11/*: any*/),
"storageKey": null
},
{ {
"alias": "tasks", "alias": "tasks",
"args": null, "args": null,
@@ -335,28 +361,28 @@ return {
(v3/*: any*/), (v3/*: any*/),
(v4/*: any*/), (v4/*: any*/),
(v5/*: any*/), (v5/*: any*/),
(v7/*: any*/), (v12/*: any*/),
(v8/*: any*/), (v13/*: any*/),
{ {
"alias": "evidences", "alias": "evidences",
"args": null, "args": null,
"concreteType": "EvidenceConnection", "concreteType": "EvidenceConnection",
"kind": "LinkedField", "kind": "LinkedField",
"name": "__MeasureView_evidences_connection", "name": "__MeasureView_task_evidences_connection",
"plural": false, "plural": false,
"selections": (v13/*: any*/), "selections": (v11/*: any*/),
"storageKey": null "storageKey": null
}, },
(v9/*: any*/) (v7/*: any*/)
], ],
"storageKey": null "storageKey": null
}, },
(v10/*: any*/) (v8/*: any*/)
], ],
"storageKey": null "storageKey": null
}, },
(v11/*: any*/), (v9/*: any*/),
(v12/*: any*/) (v10/*: any*/)
], ],
"storageKey": null "storageKey": null
} }
@@ -385,7 +411,7 @@ return {
"name": "node", "name": "node",
"plural": false, "plural": false,
"selections": [ "selections": [
(v9/*: any*/), (v7/*: any*/),
(v2/*: any*/), (v2/*: any*/),
{ {
"kind": "InlineFragment", "kind": "InlineFragment",
@@ -394,6 +420,25 @@ return {
(v4/*: any*/), (v4/*: any*/),
(v5/*: any*/), (v5/*: any*/),
(v6/*: any*/), (v6/*: any*/),
{
"alias": null,
"args": (v14/*: any*/),
"concreteType": "EvidenceConnection",
"kind": "LinkedField",
"name": "evidences",
"plural": false,
"selections": (v11/*: any*/),
"storageKey": "evidences(first:100)"
},
{
"alias": null,
"args": (v14/*: any*/),
"filters": null,
"handle": "connection",
"key": "MeasureView_evidences",
"kind": "LinkedHandle",
"name": "evidences"
},
{ {
"alias": null, "alias": null,
"args": (v14/*: any*/), "args": (v14/*: any*/),
@@ -422,8 +467,8 @@ return {
(v3/*: any*/), (v3/*: any*/),
(v4/*: any*/), (v4/*: any*/),
(v5/*: any*/), (v5/*: any*/),
(v7/*: any*/), (v12/*: any*/),
(v8/*: any*/), (v13/*: any*/),
{ {
"alias": null, "alias": null,
"args": (v15/*: any*/), "args": (v15/*: any*/),
@@ -431,7 +476,7 @@ return {
"kind": "LinkedField", "kind": "LinkedField",
"name": "evidences", "name": "evidences",
"plural": false, "plural": false,
"selections": (v13/*: any*/), "selections": (v11/*: any*/),
"storageKey": "evidences(first:50)" "storageKey": "evidences(first:50)"
}, },
{ {
@@ -439,20 +484,20 @@ return {
"args": (v15/*: any*/), "args": (v15/*: any*/),
"filters": null, "filters": null,
"handle": "connection", "handle": "connection",
"key": "MeasureView_evidences", "key": "MeasureView_task_evidences",
"kind": "LinkedHandle", "kind": "LinkedHandle",
"name": "evidences" "name": "evidences"
}, },
(v9/*: any*/) (v7/*: any*/)
], ],
"storageKey": null "storageKey": null
}, },
(v10/*: any*/) (v8/*: any*/)
], ],
"storageKey": null "storageKey": null
}, },
(v11/*: any*/), (v9/*: any*/),
(v12/*: any*/) (v10/*: any*/)
], ],
"storageKey": "tasks(first:100)" "storageKey": "tasks(first:100)"
}, },
@@ -475,10 +520,19 @@ return {
] ]
}, },
"params": { "params": {
"cacheID": "9c4b0f0032102448259ea5deb2b9d57a", "cacheID": "d3e4d9723d12bce8158b83eb76d05a90",
"id": null, "id": null,
"metadata": { "metadata": {
"connection": [ "connection": [
{
"count": null,
"cursor": null,
"direction": "forward",
"path": [
"measure",
"evidences"
]
},
{ {
"count": null, "count": null,
"cursor": null, "cursor": null,
@@ -498,11 +552,11 @@ return {
}, },
"name": "MeasureViewQuery", "name": "MeasureViewQuery",
"operationKind": "query", "operationKind": "query",
"text": "query MeasureViewQuery(\n $measureId: ID!\n) {\n measure: node(id: $measureId) {\n __typename\n id\n ... on Measure {\n name\n description\n state\n category\n tasks(first: 100) {\n edges {\n node {\n id\n name\n description\n state\n timeEstimate\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 description\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 MeasureViewQuery(\n $measureId: ID!\n) {\n measure: node(id: $measureId) {\n __typename\n id\n ... on Measure {\n name\n description\n state\n category\n evidences(first: 100) {\n edges {\n node {\n id\n mimeType\n filename\n size\n state\n type\n url\n createdAt\n description\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n tasks(first: 100) {\n edges {\n node {\n id\n name\n description\n state\n timeEstimate\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 description\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 = "0de1c02cbaf76feae0ecdbd93f530fa7"; (node as any).hash = "288412cccb1f4c14b1852504e5536af1";
export default node; export default node;

View File

@@ -1,5 +1,5 @@
/** /**
* @generated SignedSource<<e5042f900955d846dd86ad6b78d60518>> * @generated SignedSource<<2f767da45cb75ea7cc61932efa7bf802>>
* @lightSyntaxTransform * @lightSyntaxTransform
* @nogrep * @nogrep
*/ */
@@ -11,20 +11,18 @@
import { ConcreteRequest } from 'relay-runtime'; import { ConcreteRequest } from 'relay-runtime';
export type EvidenceState = "FULFILLED" | "REQUESTED"; export type EvidenceState = "FULFILLED" | "REQUESTED";
export type EvidenceType = "FILE" | "LINK"; export type EvidenceType = "FILE" | "LINK";
export type CreateEvidenceInput = { export type RequestEvidenceInput = {
description: string; description: string;
file?: any | null | undefined;
name: string; name: string;
taskId: string; taskId: string;
type: EvidenceType; type: EvidenceType;
url?: string | null | undefined;
}; };
export type MeasureViewCreateEvidenceMutation$variables = { export type MeasureViewRequestEvidenceMutation$variables = {
connections: ReadonlyArray<string>; connections: ReadonlyArray<string>;
input: CreateEvidenceInput; input: RequestEvidenceInput;
}; };
export type MeasureViewCreateEvidenceMutation$data = { export type MeasureViewRequestEvidenceMutation$data = {
readonly createEvidence: { readonly requestEvidence: {
readonly evidenceEdge: { readonly evidenceEdge: {
readonly node: { readonly node: {
readonly createdAt: string; readonly createdAt: string;
@@ -41,9 +39,9 @@ export type MeasureViewCreateEvidenceMutation$data = {
}; };
}; };
}; };
export type MeasureViewCreateEvidenceMutation = { export type MeasureViewRequestEvidenceMutation = {
response: MeasureViewCreateEvidenceMutation$data; response: MeasureViewRequestEvidenceMutation$data;
variables: MeasureViewCreateEvidenceMutation$variables; variables: MeasureViewRequestEvidenceMutation$variables;
}; };
const node: ConcreteRequest = (function(){ const node: ConcreteRequest = (function(){
@@ -164,14 +162,14 @@ return {
], ],
"kind": "Fragment", "kind": "Fragment",
"metadata": null, "metadata": null,
"name": "MeasureViewCreateEvidenceMutation", "name": "MeasureViewRequestEvidenceMutation",
"selections": [ "selections": [
{ {
"alias": null, "alias": null,
"args": (v2/*: any*/), "args": (v2/*: any*/),
"concreteType": "CreateEvidencePayload", "concreteType": "RequestEvidencePayload",
"kind": "LinkedField", "kind": "LinkedField",
"name": "createEvidence", "name": "requestEvidence",
"plural": false, "plural": false,
"selections": [ "selections": [
(v3/*: any*/) (v3/*: any*/)
@@ -189,14 +187,14 @@ return {
(v0/*: any*/) (v0/*: any*/)
], ],
"kind": "Operation", "kind": "Operation",
"name": "MeasureViewCreateEvidenceMutation", "name": "MeasureViewRequestEvidenceMutation",
"selections": [ "selections": [
{ {
"alias": null, "alias": null,
"args": (v2/*: any*/), "args": (v2/*: any*/),
"concreteType": "CreateEvidencePayload", "concreteType": "RequestEvidencePayload",
"kind": "LinkedField", "kind": "LinkedField",
"name": "createEvidence", "name": "requestEvidence",
"plural": false, "plural": false,
"selections": [ "selections": [
(v3/*: any*/), (v3/*: any*/),
@@ -222,16 +220,16 @@ return {
] ]
}, },
"params": { "params": {
"cacheID": "25b9947aa09d7b4c60886f149b06cc6e", "cacheID": "69f2291555b3826b1b29fea6d2380e04",
"id": null, "id": null,
"metadata": {}, "metadata": {},
"name": "MeasureViewCreateEvidenceMutation", "name": "MeasureViewRequestEvidenceMutation",
"operationKind": "mutation", "operationKind": "mutation",
"text": "mutation MeasureViewCreateEvidenceMutation(\n $input: CreateEvidenceInput!\n) {\n createEvidence(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 description\n }\n }\n }\n}\n" "text": "mutation MeasureViewRequestEvidenceMutation(\n $input: RequestEvidenceInput!\n) {\n requestEvidence(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 description\n }\n }\n }\n}\n"
} }
}; };
})(); })();
(node as any).hash = "bc59ec67230776eeb60a389a8360b0af"; (node as any).hash = "7921deec93c923a9cd14969dad6ecfd7";
export default node; export default node;

View File

@@ -0,0 +1,233 @@
/**
* @generated SignedSource<<97ff04190e08df7c9b3288e067787348>>
* @lightSyntaxTransform
* @nogrep
*/
/* tslint:disable */
/* eslint-disable */
// @ts-nocheck
import { ConcreteRequest } from 'relay-runtime';
export type EvidenceState = "FULFILLED" | "REQUESTED";
export type EvidenceType = "FILE" | "LINK";
export type UploadMeasureEvidenceInput = {
file: any;
measureId: string;
};
export type MeasureViewUploadMeasureEvidenceMutation$variables = {
connections: ReadonlyArray<string>;
input: UploadMeasureEvidenceInput;
};
export type MeasureViewUploadMeasureEvidenceMutation$data = {
readonly uploadMeasureEvidence: {
readonly evidenceEdge: {
readonly node: {
readonly createdAt: string;
readonly description: 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;
};
};
};
};
export type MeasureViewUploadMeasureEvidenceMutation = {
response: MeasureViewUploadMeasureEvidenceMutation$data;
variables: MeasureViewUploadMeasureEvidenceMutation$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,
"concreteType": "EvidenceEdge",
"kind": "LinkedField",
"name": "evidenceEdge",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"concreteType": "Evidence",
"kind": "LinkedField",
"name": "node",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "id",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "filename",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "fileUrl",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"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,
"kind": "ScalarField",
"name": "size",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "state",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "createdAt",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "description",
"storageKey": null
}
],
"storageKey": null
}
],
"storageKey": null
};
return {
"fragment": {
"argumentDefinitions": [
(v0/*: any*/),
(v1/*: any*/)
],
"kind": "Fragment",
"metadata": null,
"name": "MeasureViewUploadMeasureEvidenceMutation",
"selections": [
{
"alias": null,
"args": (v2/*: any*/),
"concreteType": "UploadMeasureEvidencePayload",
"kind": "LinkedField",
"name": "uploadMeasureEvidence",
"plural": false,
"selections": [
(v3/*: any*/)
],
"storageKey": null
}
],
"type": "Mutation",
"abstractKey": null
},
"kind": "Request",
"operation": {
"argumentDefinitions": [
(v1/*: any*/),
(v0/*: any*/)
],
"kind": "Operation",
"name": "MeasureViewUploadMeasureEvidenceMutation",
"selections": [
{
"alias": null,
"args": (v2/*: any*/),
"concreteType": "UploadMeasureEvidencePayload",
"kind": "LinkedField",
"name": "uploadMeasureEvidence",
"plural": false,
"selections": [
(v3/*: any*/),
{
"alias": null,
"args": null,
"filters": null,
"handle": "appendEdge",
"key": "",
"kind": "LinkedHandle",
"name": "evidenceEdge",
"handleArgs": [
{
"kind": "Variable",
"name": "connections",
"variableName": "connections"
}
]
}
],
"storageKey": null
}
]
},
"params": {
"cacheID": "2f033ec4a33f6d9c980702630822c8ca",
"id": null,
"metadata": {},
"name": "MeasureViewUploadMeasureEvidenceMutation",
"operationKind": "mutation",
"text": "mutation MeasureViewUploadMeasureEvidenceMutation(\n $input: UploadMeasureEvidenceInput!\n) {\n uploadMeasureEvidence(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 description\n }\n }\n }\n}\n"
}
};
})();
(node as any).hash = "af05defd4ec39b5d3f17aebce2a84c65";
export default node;

View File

@@ -0,0 +1,233 @@
/**
* @generated SignedSource<<4539152ef13af3aca3a79891c5b81a79>>
* @lightSyntaxTransform
* @nogrep
*/
/* tslint:disable */
/* eslint-disable */
// @ts-nocheck
import { ConcreteRequest } from 'relay-runtime';
export type EvidenceState = "FULFILLED" | "REQUESTED";
export type EvidenceType = "FILE" | "LINK";
export type UploadTaskEvidenceInput = {
file: any;
taskId: string;
};
export type MeasureViewUploadTaskEvidenceMutation$variables = {
connections: ReadonlyArray<string>;
input: UploadTaskEvidenceInput;
};
export type MeasureViewUploadTaskEvidenceMutation$data = {
readonly uploadTaskEvidence: {
readonly evidenceEdge: {
readonly node: {
readonly createdAt: string;
readonly description: 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;
};
};
};
};
export type MeasureViewUploadTaskEvidenceMutation = {
response: MeasureViewUploadTaskEvidenceMutation$data;
variables: MeasureViewUploadTaskEvidenceMutation$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,
"concreteType": "EvidenceEdge",
"kind": "LinkedField",
"name": "evidenceEdge",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"concreteType": "Evidence",
"kind": "LinkedField",
"name": "node",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "id",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "filename",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "fileUrl",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"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,
"kind": "ScalarField",
"name": "size",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "state",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "createdAt",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "description",
"storageKey": null
}
],
"storageKey": null
}
],
"storageKey": null
};
return {
"fragment": {
"argumentDefinitions": [
(v0/*: any*/),
(v1/*: any*/)
],
"kind": "Fragment",
"metadata": null,
"name": "MeasureViewUploadTaskEvidenceMutation",
"selections": [
{
"alias": null,
"args": (v2/*: any*/),
"concreteType": "UploadTaskEvidencePayload",
"kind": "LinkedField",
"name": "uploadTaskEvidence",
"plural": false,
"selections": [
(v3/*: any*/)
],
"storageKey": null
}
],
"type": "Mutation",
"abstractKey": null
},
"kind": "Request",
"operation": {
"argumentDefinitions": [
(v1/*: any*/),
(v0/*: any*/)
],
"kind": "Operation",
"name": "MeasureViewUploadTaskEvidenceMutation",
"selections": [
{
"alias": null,
"args": (v2/*: any*/),
"concreteType": "UploadTaskEvidencePayload",
"kind": "LinkedField",
"name": "uploadTaskEvidence",
"plural": false,
"selections": [
(v3/*: any*/),
{
"alias": null,
"args": null,
"filters": null,
"handle": "appendEdge",
"key": "",
"kind": "LinkedHandle",
"name": "evidenceEdge",
"handleArgs": [
{
"kind": "Variable",
"name": "connections",
"variableName": "connections"
}
]
}
],
"storageKey": null
}
]
},
"params": {
"cacheID": "2c18eec6e7e3d428ad6fbdf4c52ccf94",
"id": null,
"metadata": {},
"name": "MeasureViewUploadTaskEvidenceMutation",
"operationKind": "mutation",
"text": "mutation MeasureViewUploadTaskEvidenceMutation(\n $input: UploadTaskEvidenceInput!\n) {\n uploadTaskEvidence(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 description\n }\n }\n }\n}\n"
}
};
})();
(node as any).hash = "3649fc872c9f58d4ffd0181b0316c812";
export default node;

View File

@@ -29,7 +29,8 @@ import (
type ( type (
Evidence struct { Evidence struct {
ID gid.GID `db:"id"` ID gid.GID `db:"id"`
TaskID gid.GID `db:"task_id"` MeasureID gid.GID `db:"measure_id"`
TaskID *gid.GID `db:"task_id"`
State EvidenceState `db:"state"` State EvidenceState `db:"state"`
ReferenceID string `db:"reference_id"` ReferenceID string `db:"reference_id"`
Type EvidenceType `db:"type"` Type EvidenceType `db:"type"`
@@ -65,6 +66,7 @@ INSERT INTO
evidences ( evidences (
tenant_id, tenant_id,
id, id,
measure_id,
task_id, task_id,
reference_id, reference_id,
object_key, object_key,
@@ -81,6 +83,7 @@ INSERT INTO
VALUES ( VALUES (
@tenant_id, @tenant_id,
@evidence_id, @evidence_id,
@measure_id,
@task_id, @task_id,
@reference_id, @reference_id,
@object_key, @object_key,
@@ -104,6 +107,7 @@ WHERE evidences.state = 'REQUESTED';
args := pgx.StrictNamedArgs{ args := pgx.StrictNamedArgs{
"tenant_id": scope.GetTenantID(), "tenant_id": scope.GetTenantID(),
"evidence_id": e.ID, "evidence_id": e.ID,
"measure_id": e.MeasureID,
"task_id": e.TaskID, "task_id": e.TaskID,
"reference_id": e.ReferenceID, "reference_id": e.ReferenceID,
"object_key": e.ObjectKey, "object_key": e.ObjectKey,
@@ -131,6 +135,7 @@ INSERT INTO
evidences ( evidences (
tenant_id, tenant_id,
id, id,
measure_id,
task_id, task_id,
reference_id, reference_id,
object_key, object_key,
@@ -147,6 +152,7 @@ INSERT INTO
VALUES ( VALUES (
@tenant_id, @tenant_id,
@evidence_id, @evidence_id,
@measure_id,
@task_id, @task_id,
@reference_id, @reference_id,
@object_key, @object_key,
@@ -165,6 +171,7 @@ VALUES (
args := pgx.StrictNamedArgs{ args := pgx.StrictNamedArgs{
"tenant_id": scope.GetTenantID(), "tenant_id": scope.GetTenantID(),
"evidence_id": e.ID, "evidence_id": e.ID,
"measure_id": e.MeasureID,
"task_id": e.TaskID, "task_id": e.TaskID,
"reference_id": e.ReferenceID, "reference_id": e.ReferenceID,
"object_key": e.ObjectKey, "object_key": e.ObjectKey,
@@ -192,6 +199,7 @@ func (e *Evidence) LoadByID(
SELECT SELECT
id, id,
task_id, task_id,
measure_id,
reference_id, reference_id,
state, state,
type, type,
@@ -231,6 +239,58 @@ LIMIT 1;
return nil return nil
} }
func (e *Evidences) LoadByMeasureID(
ctx context.Context,
conn pg.Conn,
scope Scoper,
measureID gid.GID,
cursor *page.Cursor[EvidenceOrderField],
) error {
q := `
SELECT
id,
measure_id,
task_id,
reference_id,
state,
type,
object_key,
mime_type,
size,
filename,
url,
description,
created_at,
updated_at
FROM
evidences
WHERE
%s
AND measure_id = @measure_id
AND %s
`
q = fmt.Sprintf(q, scope.SQLFragment(), cursor.SQLFragment())
args := pgx.StrictNamedArgs{"measure_id": measureID}
maps.Copy(args, scope.SQLArguments())
maps.Copy(args, cursor.SQLArguments())
rows, err := conn.Query(ctx, q, args)
if err != nil {
return fmt.Errorf("cannot query evidence: %w", err)
}
evidences, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[Evidence])
if err != nil {
return fmt.Errorf("cannot collect evidence: %w", err)
}
*e = evidences
return nil
}
func (e *Evidences) LoadByTaskID( func (e *Evidences) LoadByTaskID(
ctx context.Context, ctx context.Context,
conn pg.Conn, conn pg.Conn,
@@ -241,6 +301,7 @@ func (e *Evidences) LoadByTaskID(
q := ` q := `
SELECT SELECT
id, id,
measure_id,
task_id, task_id,
reference_id, reference_id,
state, state,

View File

@@ -0,0 +1,9 @@
ALTER TABLE evidences ALTER COLUMN task_id DROP NOT NULL;
ALTER TABLE evidences ADD COLUMN measure_id TEXT REFERENCES measures(id);
UPDATE evidences e
SET measure_id = t.measure_id
FROM tasks t
WHERE e.task_id = t.id AND e.measure_id IS NULL;
ALTER TABLE evidences ALTER COLUMN measure_id SET NOT NULL;

View File

@@ -37,8 +37,16 @@ type (
svc *TenantService svc *TenantService
} }
File struct {
Content io.Reader
Filename string
Size int64
ContentType string
}
RequestEvidenceRequest struct { RequestEvidenceRequest struct {
TaskID gid.GID MeasureID *gid.GID
TaskID *gid.GID
Type coredata.EvidenceType Type coredata.EvidenceType
Name string Name string
Description string Description string
@@ -51,13 +59,14 @@ type (
Filename *string Filename *string
} }
CreateEvidenceRequest struct { UploadTaskEvidenceRequest struct {
TaskID gid.GID TaskID gid.GID
Name string File File
Type coredata.EvidenceType }
File io.Reader
URL string UploadMeasureEvidenceRequest struct {
Description string MeasureID gid.GID
File File
} }
) )
@@ -90,7 +99,6 @@ func (s EvidenceService) Request(
evidence := &coredata.Evidence{ evidence := &coredata.Evidence{
ID: evidenceID, ID: evidenceID,
TaskID: req.TaskID,
State: coredata.EvidenceStateRequested, State: coredata.EvidenceStateRequested,
Type: req.Type, Type: req.Type,
Filename: req.Name, Filename: req.Name,
@@ -99,9 +107,23 @@ func (s EvidenceService) Request(
UpdatedAt: now, UpdatedAt: now,
} }
err := s.svc.pg.WithConn( err := s.svc.pg.WithTx(
ctx, ctx,
func(conn pg.Conn) error { func(conn pg.Conn) error {
task := &coredata.Task{}
if req.TaskID != nil {
if err := task.LoadByID(ctx, conn, s.svc.scope, *req.TaskID); err != nil {
return fmt.Errorf("cannot load task: %w", err)
}
evidence.TaskID = req.TaskID
evidence.MeasureID = task.MeasureID
} else if req.MeasureID != nil {
evidence.MeasureID = *req.MeasureID
} else {
return fmt.Errorf("measure id or task id is required")
}
return evidence.Insert(ctx, conn, s.svc.scope) return evidence.Insert(ctx, conn, s.svc.scope)
}, },
) )
@@ -183,9 +205,9 @@ func (s EvidenceService) Fulfill(
return evidence, nil return evidence, nil
} }
func (s EvidenceService) Create( func (s EvidenceService) UploadTaskEvidence(
ctx context.Context, ctx context.Context,
req CreateEvidenceRequest, req UploadTaskEvidenceRequest,
) (*coredata.Evidence, error) { ) (*coredata.Evidence, error) {
now := time.Now() now := time.Now()
evidenceID := gid.New(s.svc.scope.GetTenantID(), coredata.EvidenceEntityType) evidenceID := gid.New(s.svc.scope.GetTenantID(), coredata.EvidenceEntityType)
@@ -197,66 +219,130 @@ func (s EvidenceService) Create(
evidence := &coredata.Evidence{ evidence := &coredata.Evidence{
ID: evidenceID, ID: evidenceID,
TaskID: req.TaskID, TaskID: &req.TaskID,
State: coredata.EvidenceStateFulfilled, State: coredata.EvidenceStateFulfilled,
ReferenceID: "custom-evidence-" + referenceID.String(), ReferenceID: "custom-evidence-" + referenceID.String(),
Type: req.Type, Type: coredata.EvidenceTypeFile,
Filename: req.Name, Filename: req.File.Filename,
URL: req.URL,
Description: req.Description,
CreatedAt: now, CreatedAt: now,
UpdatedAt: now, UpdatedAt: now,
} }
if req.Type == coredata.EvidenceTypeFile { // TODO validate content type
contentType := "application/octet-stream" if req.File.ContentType == "" {
if req.Name != "" { req.File.ContentType = "application/octet-stream"
if detectedType := mime.TypeByExtension(filepath.Ext(req.Name)); detectedType != "" {
contentType = detectedType
}
}
objectKey, err := uuid.NewV7()
if err != nil {
return nil, fmt.Errorf("cannot generate object key: %w", err)
}
_, err = s.svc.s3.PutObject(ctx, &s3.PutObjectInput{
Bucket: aws.String(s.svc.bucket),
Key: aws.String(objectKey.String()),
Body: req.File,
ContentType: aws.String(contentType),
})
if err != nil {
return nil, fmt.Errorf("cannot upload file to S3: %w", err)
}
headOutput, err := s.svc.s3.HeadObject(ctx, &s3.HeadObjectInput{
Bucket: aws.String(s.svc.bucket),
Key: aws.String(objectKey.String()),
})
if err != nil {
return nil, fmt.Errorf("cannot get object metadata: %w", err)
}
evidence.ObjectKey = objectKey.String()
evidence.MimeType = contentType
evidence.Size = uint64(*headOutput.ContentLength)
} else if req.Type == coredata.EvidenceTypeLink {
evidence.MimeType = "text/uri-list"
evidence.Size = uint64(len(req.URL))
evidence.ObjectKey = ""
} }
task := &coredata.Task{} objectKey, err := uuid.NewV7()
if err != nil {
return nil, fmt.Errorf("cannot generate object key: %w", err)
}
_, err = s.svc.s3.PutObject(
ctx,
&s3.PutObjectInput{
Bucket: aws.String(s.svc.bucket),
Key: aws.String(objectKey.String()),
Body: req.File.Content,
ContentType: aws.String(req.File.ContentType),
},
)
if err != nil {
return nil, fmt.Errorf("cannot upload file to S3: %w", err)
}
evidence.ObjectKey = objectKey.String()
evidence.MimeType = req.File.ContentType
evidence.Size = uint64(req.File.Size)
err = s.svc.pg.WithTx( err = s.svc.pg.WithTx(
ctx, ctx,
func(conn pg.Conn) error { func(conn pg.Conn) error {
task := &coredata.Task{}
if err := task.LoadByID(ctx, conn, s.svc.scope, req.TaskID); err != nil { if err := task.LoadByID(ctx, conn, s.svc.scope, req.TaskID); err != nil {
return fmt.Errorf("cannot load task %q: %w", req.TaskID, err) return fmt.Errorf("cannot load task %q: %w", req.TaskID, err)
} }
evidence.MeasureID = task.MeasureID
if err := evidence.Insert(ctx, conn, s.svc.scope); err != nil {
return fmt.Errorf("cannot insert evidence: %w", err)
}
return nil
},
)
if err != nil {
// TODO try do delete file from s3 if it's a file type
return nil, err
}
return evidence, nil
}
func (s EvidenceService) UploadMeasureEvidence(
ctx context.Context,
req UploadMeasureEvidenceRequest,
) (*coredata.Evidence, error) {
now := time.Now()
evidenceID := gid.New(s.svc.scope.GetTenantID(), coredata.EvidenceEntityType)
referenceID, err := uuid.NewV4()
if err != nil {
return nil, fmt.Errorf("cannot generate reference id: %w", err)
}
evidence := &coredata.Evidence{
ID: evidenceID,
MeasureID: req.MeasureID,
State: coredata.EvidenceStateFulfilled,
ReferenceID: "custom-evidence-" + referenceID.String(),
Type: coredata.EvidenceTypeFile,
Filename: req.File.Filename,
CreatedAt: now,
UpdatedAt: now,
}
// TODO validate content type
if req.File.ContentType == "" {
req.File.ContentType = "application/octet-stream"
}
objectKey, err := uuid.NewV7()
if err != nil {
return nil, fmt.Errorf("cannot generate object key: %w", err)
}
_, err = s.svc.s3.PutObject(
ctx,
&s3.PutObjectInput{
Bucket: aws.String(s.svc.bucket),
Key: aws.String(objectKey.String()),
Body: req.File.Content,
ContentType: aws.String(req.File.ContentType),
},
)
if err != nil {
return nil, fmt.Errorf("cannot upload file to S3: %w", err)
}
evidence.ObjectKey = objectKey.String()
evidence.MimeType = req.File.ContentType
evidence.Size = uint64(req.File.Size)
err = s.svc.pg.WithTx(
ctx,
func(conn pg.Conn) error {
measure := &coredata.Measure{}
if err := measure.LoadByID(ctx, conn, s.svc.scope, req.MeasureID); err != nil {
return fmt.Errorf("cannot load measure %q: %w", req.MeasureID, err)
}
evidence.MeasureID = req.MeasureID
if err := evidence.Insert(ctx, conn, s.svc.scope); err != nil { if err := evidence.Insert(ctx, conn, s.svc.scope); err != nil {
return fmt.Errorf("cannot insert evidence: %w", err) return fmt.Errorf("cannot insert evidence: %w", err)
} }
@@ -310,6 +396,33 @@ func (s EvidenceService) GenerateFileURL(
return &presignedReq.URL, nil return &presignedReq.URL, nil
} }
func (s EvidenceService) ListForMeasureID(
ctx context.Context,
measureID gid.GID,
cursor *page.Cursor[coredata.EvidenceOrderField],
) (*page.Page[*coredata.Evidence, coredata.EvidenceOrderField], error) {
var evidences coredata.Evidences
err := s.svc.pg.WithConn(
ctx,
func(conn pg.Conn) error {
return evidences.LoadByMeasureID(
ctx,
conn,
s.svc.scope,
measureID,
cursor,
)
},
)
if err != nil {
return nil, err
}
return page.NewPage(evidences, cursor), nil
}
func (s EvidenceService) ListForTaskID( func (s EvidenceService) ListForTaskID(
ctx context.Context, ctx context.Context,
taskID gid.GID, taskID gid.GID,

View File

@@ -188,7 +188,7 @@ func (s MeasureService) Import(
evidence := &coredata.Evidence{ evidence := &coredata.Evidence{
State: coredata.EvidenceStateRequested, State: coredata.EvidenceStateRequested,
ID: evidenceID, ID: evidenceID,
TaskID: task.ID, TaskID: &task.ID,
ReferenceID: req.Measures[i].Tasks[j].RequestedEvidences[k].ReferenceID, ReferenceID: req.Measures[i].Tasks[j].RequestedEvidences[k].ReferenceID,
Type: req.Measures[i].Tasks[j].RequestedEvidences[k].Type, Type: req.Measures[i].Tasks[j].RequestedEvidences[k].Type,
Description: req.Measures[i].Tasks[j].RequestedEvidences[k].Name, Description: req.Measures[i].Tasks[j].RequestedEvidences[k].Name,

View File

@@ -596,6 +596,14 @@ type Measure implements Node {
description: String! description: String!
state: MeasureState! state: MeasureState!
evidences(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: EvidenceOrder
): EvidenceConnection! @goField(forceResolver: true)
tasks( tasks(
first: Int first: Int
after: CursorKey after: CursorKey
@@ -987,8 +995,9 @@ type Mutation {
# Evidence mutations # Evidence mutations
requestEvidence(input: RequestEvidenceInput!): RequestEvidencePayload! requestEvidence(input: RequestEvidenceInput!): RequestEvidencePayload!
fulfillEvidence(input: FulfillEvidenceInput!): FulfillEvidencePayload! fulfillEvidence(input: FulfillEvidenceInput!): FulfillEvidencePayload!
createEvidence(input: CreateEvidenceInput!): CreateEvidencePayload!
deleteEvidence(input: DeleteEvidenceInput!): DeleteEvidencePayload! deleteEvidence(input: DeleteEvidenceInput!): DeleteEvidencePayload!
uploadTaskEvidence(input: UploadTaskEvidenceInput!): UploadTaskEvidencePayload!
uploadMeasureEvidence(input: UploadMeasureEvidenceInput!): UploadMeasureEvidencePayload!
# Vendor Compliance Report mutations # Vendor Compliance Report mutations
uploadVendorComplianceReport( uploadVendorComplianceReport(
@@ -1651,4 +1660,22 @@ input SendSigningNotificationsInput {
type SendSigningNotificationsPayload { type SendSigningNotificationsPayload {
success: Boolean! success: Boolean!
} }
type UploadTaskEvidencePayload {
evidenceEdge: EvidenceEdge!
}
type UploadMeasureEvidencePayload {
evidenceEdge: EvidenceEdge!
}
input UploadTaskEvidenceInput {
taskId: ID!
file: Upload!
}
input UploadMeasureEvidenceInput {
measureId: ID!
file: Upload!
}

File diff suppressed because it is too large Load Diff

View File

@@ -473,6 +473,7 @@ type Measure struct {
Name string `json:"name"` Name string `json:"name"`
Description string `json:"description"` Description string `json:"description"`
State coredata.MeasureState `json:"state"` State coredata.MeasureState `json:"state"`
Evidences *EvidenceConnection `json:"evidences"`
Tasks *TaskConnection `json:"tasks"` Tasks *TaskConnection `json:"tasks"`
Risks *RiskConnection `json:"risks"` Risks *RiskConnection `json:"risks"`
Controls *ControlConnection `json:"controls"` Controls *ControlConnection `json:"controls"`
@@ -886,6 +887,24 @@ type UpdateVendorPayload struct {
Vendor *Vendor `json:"vendor"` Vendor *Vendor `json:"vendor"`
} }
type UploadMeasureEvidenceInput struct {
MeasureID gid.GID `json:"measureId"`
File graphql.Upload `json:"file"`
}
type UploadMeasureEvidencePayload struct {
EvidenceEdge *EvidenceEdge `json:"evidenceEdge"`
}
type UploadTaskEvidenceInput struct {
TaskID gid.GID `json:"taskId"`
File graphql.Upload `json:"file"`
}
type UploadTaskEvidencePayload struct {
EvidenceEdge *EvidenceEdge `json:"evidenceEdge"`
}
type UploadVendorComplianceReportInput struct { type UploadVendorComplianceReportInput struct {
VendorID gid.GID `json:"vendorId"` VendorID gid.GID `json:"vendorId"`
ReportDate time.Time `json:"reportDate"` ReportDate time.Time `json:"reportDate"`

View File

@@ -112,6 +112,31 @@ func (r *frameworkResolver) Controls(ctx context.Context, obj *types.Framework,
return types.NewControlConnection(page), nil return types.NewControlConnection(page), nil
} }
// Evidences is the resolver for the evidences field.
func (r *measureResolver) Evidences(ctx context.Context, obj *types.Measure, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.EvidenceOrderBy) (*types.EvidenceConnection, error) {
svc := GetTenantService(ctx, r.proboSvc, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.EvidenceOrderField]{
Field: coredata.EvidenceOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.EvidenceOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
page, err := svc.Evidences.ListForMeasureID(ctx, obj.ID, cursor)
if err != nil {
return nil, fmt.Errorf("cannot list measure evidences: %w", err)
}
return types.NewEvidenceConnection(page), nil
}
// Tasks is the resolver for the tasks field. // Tasks is the resolver for the tasks field.
func (r *measureResolver) Tasks(ctx context.Context, obj *types.Measure, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.TaskOrderBy) (*types.TaskConnection, error) { func (r *measureResolver) Tasks(ctx context.Context, obj *types.Measure, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.TaskOrderBy) (*types.TaskConnection, error) {
svc := GetTenantService(ctx, r.proboSvc, obj.ID.TenantID()) svc := GetTenantService(ctx, r.proboSvc, obj.ID.TenantID())
@@ -875,7 +900,7 @@ func (r *mutationResolver) RequestEvidence(ctx context.Context, input types.Requ
evidence, err := svc.Evidences.Request( evidence, err := svc.Evidences.Request(
ctx, ctx,
probo.RequestEvidenceRequest{ probo.RequestEvidenceRequest{
TaskID: input.TaskID, TaskID: &input.TaskID,
Name: input.Name, Name: input.Name,
Type: input.Type, Type: input.Type,
Description: input.Description, Description: input.Description,
@@ -917,39 +942,6 @@ func (r *mutationResolver) FulfillEvidence(ctx context.Context, input types.Fulf
}, nil }, nil
} }
// CreateEvidence is the resolver for the createEvidence field.
func (r *mutationResolver) CreateEvidence(ctx context.Context, input types.CreateEvidenceInput) (*types.CreateEvidencePayload, error) {
svc := GetTenantService(ctx, r.proboSvc, input.TaskID.TenantID())
req := probo.CreateEvidenceRequest{
TaskID: input.TaskID,
Name: input.Name,
Type: input.Type,
Description: input.Description,
}
if input.Type == coredata.EvidenceTypeFile {
if input.File == nil {
return nil, fmt.Errorf("file is required for FILE type evidence")
}
req.File = input.File.File
} else if input.Type == coredata.EvidenceTypeLink {
if input.URL == nil || *input.URL == "" {
return nil, fmt.Errorf("URL is required for LINK type evidence")
}
req.URL = *input.URL
}
evidence, err := svc.Evidences.Create(ctx, req)
if err != nil {
panic(fmt.Errorf("failed to create evidence: %w", err))
}
return &types.CreateEvidencePayload{
EvidenceEdge: types.NewEvidenceEdge(evidence, coredata.EvidenceOrderFieldCreatedAt),
}, nil
}
// DeleteEvidence is the resolver for the deleteEvidence field. // DeleteEvidence is the resolver for the deleteEvidence field.
func (r *mutationResolver) DeleteEvidence(ctx context.Context, input types.DeleteEvidenceInput) (*types.DeleteEvidencePayload, error) { func (r *mutationResolver) DeleteEvidence(ctx context.Context, input types.DeleteEvidenceInput) (*types.DeleteEvidencePayload, error) {
svc := GetTenantService(ctx, r.proboSvc, input.EvidenceID.TenantID()) svc := GetTenantService(ctx, r.proboSvc, input.EvidenceID.TenantID())
@@ -964,6 +956,56 @@ func (r *mutationResolver) DeleteEvidence(ctx context.Context, input types.Delet
}, nil }, nil
} }
// UploadTaskEvidence is the resolver for the uploadTaskEvidence field.
func (r *mutationResolver) UploadTaskEvidence(ctx context.Context, input types.UploadTaskEvidenceInput) (*types.UploadTaskEvidencePayload, error) {
svc := GetTenantService(ctx, r.proboSvc, input.TaskID.TenantID())
evidence, err := svc.Evidences.UploadTaskEvidence(
ctx,
probo.UploadTaskEvidenceRequest{
TaskID: input.TaskID,
File: probo.File{
Content: input.File.File,
Filename: input.File.Filename,
Size: input.File.Size,
ContentType: input.File.ContentType,
},
},
)
if err != nil {
panic(fmt.Errorf("cannot upload task evidence: %w", err))
}
return &types.UploadTaskEvidencePayload{
EvidenceEdge: types.NewEvidenceEdge(evidence, coredata.EvidenceOrderFieldCreatedAt),
}, nil
}
// UploadMeasureEvidence is the resolver for the uploadMeasureEvidence field.
func (r *mutationResolver) UploadMeasureEvidence(ctx context.Context, input types.UploadMeasureEvidenceInput) (*types.UploadMeasureEvidencePayload, error) {
svc := GetTenantService(ctx, r.proboSvc, input.MeasureID.TenantID())
evidence, err := svc.Evidences.UploadMeasureEvidence(
ctx,
probo.UploadMeasureEvidenceRequest{
MeasureID: input.MeasureID,
File: probo.File{
Content: input.File.File,
Filename: input.File.Filename,
Size: input.File.Size,
ContentType: input.File.ContentType,
},
},
)
if err != nil {
panic(fmt.Errorf("cannot upload measure evidence: %w", err))
}
return &types.UploadMeasureEvidencePayload{
EvidenceEdge: types.NewEvidenceEdge(evidence, coredata.EvidenceOrderFieldCreatedAt),
}, nil
}
// UploadVendorComplianceReport is the resolver for the uploadVendorComplianceReport field. // UploadVendorComplianceReport is the resolver for the uploadVendorComplianceReport field.
func (r *mutationResolver) UploadVendorComplianceReport(ctx context.Context, input types.UploadVendorComplianceReportInput) (*types.UploadVendorComplianceReportPayload, error) { func (r *mutationResolver) UploadVendorComplianceReport(ctx context.Context, input types.UploadVendorComplianceReportInput) (*types.UploadVendorComplianceReportPayload, error) {
svc := GetTenantService(ctx, r.proboSvc, input.VendorID.TenantID()) svc := GetTenantService(ctx, r.proboSvc, input.VendorID.TenantID())