Add assigned people to a task

Signed-off-by: gearnode <bryan@frimin.fr>
This commit is contained in:
gearnode
2025-03-13 10:08:31 +01:00
parent 376edd927d
commit 8cbe08d136
15 changed files with 1881 additions and 61 deletions

View File

@@ -31,6 +31,9 @@ import {
FileText,
Image,
X,
UserPlus,
UserMinus,
User,
} from "lucide-react";
import { Card, CardContent } from "@/components/ui/card";
import { useToast } from "@/hooks/use-toast";
@@ -46,6 +49,11 @@ import {
DialogTrigger,
} from "@/components/ui/dialog";
import { Label } from "@/components/ui/label";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover";
import { Helmet } from "react-helmet-async";
import type { ControlOverviewPageQuery as ControlOverviewPageQueryType } from "./__generated__/ControlOverviewPageQuery.graphql";
@@ -54,6 +62,9 @@ import type { ControlOverviewPageCreateTaskMutation as ControlOverviewPageCreate
import type { ControlOverviewPageDeleteTaskMutation as ControlOverviewPageDeleteTaskMutationType } from "./__generated__/ControlOverviewPageDeleteTaskMutation.graphql";
import type { ControlOverviewPageUploadEvidenceMutation as ControlOverviewPageUploadEvidenceMutationType } from "./__generated__/ControlOverviewPageUploadEvidenceMutation.graphql";
import type { ControlOverviewPageDeleteEvidenceMutation as ControlOverviewPageDeleteEvidenceMutationType } from "./__generated__/ControlOverviewPageDeleteEvidenceMutation.graphql";
import type { ControlOverviewPageAssignTaskMutation as ControlOverviewPageAssignTaskMutationType } from "./__generated__/ControlOverviewPageAssignTaskMutation.graphql";
import type { ControlOverviewPageUnassignTaskMutation as ControlOverviewPageUnassignTaskMutationType } from "./__generated__/ControlOverviewPageUnassignTaskMutation.graphql";
import type { ControlOverviewPageOrganizationQuery$data } from "./__generated__/ControlOverviewPageOrganizationQuery.graphql";
import { Textarea } from "@/components/ui/textarea";
// Function to format ISO8601 duration to human-readable format
@@ -113,6 +124,11 @@ const controlOverviewPageQuery = graphql`
state
timeEstimate
version
assignedTo {
id
fullName
primaryEmailAddress
}
evidences(first: 50)
@connection(key: "ControlOverviewPage_evidences") {
__id
@@ -162,6 +178,11 @@ const createTaskMutation = graphql`
description
timeEstimate
state
assignedTo {
id
fullName
primaryEmailAddress
}
}
}
}
@@ -222,6 +243,57 @@ const getEvidenceFileUrlQuery = graphql`
}
`;
const assignTaskMutation = graphql`
mutation ControlOverviewPageAssignTaskMutation($input: AssignTaskInput!) {
assignTask(input: $input) {
task {
id
version
assignedTo {
id
fullName
primaryEmailAddress
}
}
}
}
`;
const unassignTaskMutation = graphql`
mutation ControlOverviewPageUnassignTaskMutation($input: UnassignTaskInput!) {
unassignTask(input: $input) {
task {
id
version
assignedTo {
id
fullName
primaryEmailAddress
}
}
}
}
`;
const organizationQuery = graphql`
query ControlOverviewPageOrganizationQuery($organizationId: ID!) {
organization: node(id: $organizationId) {
id
... on Organization {
peoples(first: 100) @connection(key: "ControlOverviewPage_peoples") {
edges {
node {
id
fullName
primaryEmailAddress
}
}
}
}
}
}
`;
function ControlOverviewPageContent({
queryRef,
}: {
@@ -236,6 +308,32 @@ function ControlOverviewPageContent({
const navigate = useNavigate();
const environment = useRelayEnvironment();
// Load organization data for people selector
const [organizationData, setOrganizationData] =
useState<ControlOverviewPageOrganizationQuery$data | null>(null);
useEffect(() => {
if (organizationId) {
fetchQuery(environment, organizationQuery, {
organizationId,
})
.toPromise()
.then((response) => {
setOrganizationData(
response as ControlOverviewPageOrganizationQuery$data
);
})
.catch((error) => {
console.error("Error fetching organization data:", error);
toast({
title: "Error",
description: "Failed to load people data",
variant: "destructive",
});
});
}
}, [organizationId, environment, toast]);
const formatImportance = (importance: string | undefined): string => {
if (!importance) return "";
@@ -304,6 +402,12 @@ function ControlOverviewPageContent({
useMutation<ControlOverviewPageDeleteEvidenceMutationType>(
deleteEvidenceMutation
);
const [assignTask] =
useMutation<ControlOverviewPageAssignTaskMutationType>(assignTaskMutation);
const [unassignTask] =
useMutation<ControlOverviewPageUnassignTaskMutationType>(
unassignTaskMutation
);
const [isCreateTaskOpen, setIsCreateTaskOpen] = useState(false);
const [newTaskName, setNewTaskName] = useState("");
@@ -354,6 +458,16 @@ function ControlOverviewPageContent({
taskId: string;
} | null>(null);
// Add state for people selector
const [peoplePopoverOpen, setPeoplePopoverOpen] = useState<{
[key: string]: boolean;
}>({});
// Add state for people search
const [peopleSearch, setPeopleSearch] = useState<{
[key: string]: string;
}>({});
const tasks = data.control.tasks?.edges.map((edge) => edge.node) || [];
const getEvidenceConnectionId = useCallback(
@@ -796,6 +910,57 @@ function ControlOverviewPageContent({
});
};
// Function to handle assigning a person to a task
const handleAssignPerson = (taskId: string, personId: string) => {
assignTask({
variables: {
input: {
taskId,
assignedToId: personId,
},
},
onCompleted: () => {
toast({
title: "Task assigned",
description: "Task has been assigned successfully.",
});
// Close the popover
setPeoplePopoverOpen((prev) => ({ ...prev, [taskId]: false }));
},
onError: (error) => {
toast({
title: "Error assigning task",
description: error.message,
variant: "destructive",
});
},
});
};
// Function to handle unassigning a person from a task
const handleUnassignPerson = (taskId: string) => {
unassignTask({
variables: {
input: {
taskId,
},
},
onCompleted: () => {
toast({
title: "Task unassigned",
description: "Task has been unassigned successfully.",
});
},
onError: (error) => {
toast({
title: "Error unassigning task",
description: error.message,
variant: "destructive",
});
},
});
};
return (
<>
<Helmet>
@@ -1015,25 +1180,21 @@ function ControlOverviewPageContent({
? "border-gray-400 bg-gray-100"
: "border-gray-300"
} ${isDraggingFile ? "opacity-50" : ""}`}
onClick={() =>
task?.id &&
task?.state &&
handleTaskClick(task.id, task.state, task.version)
}
onClick={(e) => {
e.stopPropagation();
if (task?.id && task?.state) {
handleTaskClick(task.id, task.state, task.version);
}
}}
>
{task?.state === "DONE" && (
<CheckCircle2 className="w-4 h-4 text-gray-500" />
)}
</div>
<div
className={`flex-1 flex items-center justify-between cursor-pointer ${
className={`flex-1 flex items-center justify-between ${
isDraggingFile ? "opacity-50" : ""
}`}
onClick={() =>
task?.id &&
task?.state &&
handleTaskClick(task.id, task.state, task.version)
}
>
<div>
<h3
@@ -1057,9 +1218,182 @@ function ControlOverviewPageContent({
<span>{formatDuration(task.timeEstimate)}</span>
</p>
)}
{task?.assignedTo && (
<p className="text-xs mt-1 flex items-center text-gray-600">
<User className="w-3 h-3 mr-1" />
<span>{task.assignedTo.fullName}</span>
</p>
)}
</div>
<div className="flex items-center gap-2 opacity-0 group-hover:opacity-100 transition-opacity">
{/* People Selector */}
<Popover
open={peoplePopoverOpen[task?.id || ""]}
onOpenChange={(open: boolean) => {
if (task?.id) {
setPeoplePopoverOpen((prev) => ({
...prev,
[task.id]: open,
}));
}
}}
>
<PopoverTrigger asChild>
<button
type="button"
className="text-gray-400 hover:text-blue-600"
onClick={(e) => {
e.stopPropagation();
if (task?.id) {
setPeoplePopoverOpen((prev) => ({
...prev,
[task.id]: !prev[task.id],
}));
}
}}
>
{task?.assignedTo ? (
<UserMinus className="w-4 h-4" />
) : (
<UserPlus className="w-4 h-4" />
)}
</button>
</PopoverTrigger>
<PopoverContent className="w-[250px] p-0" align="end">
{task?.assignedTo ? (
<div className="p-4 space-y-4">
<div className="flex items-center gap-2">
<User className="w-4 h-4 text-gray-500" />
<div className="text-sm">
<p className="font-medium">
{task.assignedTo.fullName}
</p>
<p className="text-xs text-gray-500">
{task.assignedTo.primaryEmailAddress}
</p>
</div>
</div>
<Button
type="button"
variant="destructive"
size="sm"
className="w-full"
onClick={(e) => {
e.stopPropagation();
if (task?.id) {
handleUnassignPerson(task.id);
}
}}
>
<UserMinus className="w-4 h-4 mr-2" />
Unassign
</Button>
</div>
) : (
<div className="max-h-[300px] overflow-y-auto">
<div className="p-2 border-b">
<input
type="text"
placeholder="Search people to assign..."
className="w-full px-3 py-2 text-sm border rounded focus:outline-none focus:ring-2 focus:ring-blue-500"
value={peopleSearch[task?.id || ""] || ""}
onChange={(e) => {
if (task?.id) {
setPeopleSearch((prev) => ({
...prev,
[task.id]: e.target.value,
}));
}
}}
/>
</div>
<div className="px-3 py-2 text-xs text-gray-500">
Click on a person to assign them to this task
</div>
<div className="py-1">
{!organizationData?.organization?.peoples?.edges?.some(
(edge) => {
if (!edge?.node) return false;
const searchTerm = (
peopleSearch[task?.id || ""] || ""
).toLowerCase();
return (
!searchTerm ||
edge.node.fullName
.toLowerCase()
.includes(searchTerm) ||
edge.node.primaryEmailAddress
.toLowerCase()
.includes(searchTerm)
);
}
) && (
<div className="py-6 text-center text-sm">
No people found.
</div>
)}
{organizationData?.organization?.peoples?.edges?.map(
(edge) => {
if (!edge?.node) return null;
const searchTerm = (
peopleSearch[task?.id || ""] || ""
).toLowerCase();
if (
searchTerm &&
!edge.node.fullName
.toLowerCase()
.includes(searchTerm) &&
!edge.node.primaryEmailAddress
.toLowerCase()
.includes(searchTerm)
) {
return null;
}
return (
<div
key={edge.node.id}
className="px-2 py-1 hover:bg-blue-50 cursor-pointer"
>
<button
type="button"
className="flex items-center w-full text-left"
onClick={() => {
if (task?.id) {
handleAssignPerson(
task.id,
edge.node.id
);
setPeoplePopoverOpen((prev) => ({
...prev,
[task.id]: false,
}));
}
}}
>
<User className="mr-2 h-4 w-4 text-blue-500 flex-shrink-0" />
<div>
<p className="font-medium">
{edge.node.fullName}
</p>
<p className="text-xs text-gray-500">
{edge.node.primaryEmailAddress}
</p>
</div>
</button>
</div>
);
}
)}
</div>
</div>
)}
</PopoverContent>
</Popover>
<button
type="button"
className="text-gray-400 hover:text-blue-600"
onClick={(e) => {
e.stopPropagation();
@@ -1071,6 +1405,7 @@ function ControlOverviewPageContent({
<Upload className="w-4 h-4" />
</button>
<button
type="button"
className="text-gray-400 hover:text-red-600"
onClick={(e) => {
e.stopPropagation();

View File

@@ -99,6 +99,10 @@ function CreatePeoplePageContent() {
organizationId!,
"PeopleSelector_organization_peoples"
),
ConnectionHandler.getConnectionID(
organizationId!,
"ControlOverviewPage_peoples"
),
],
input: {
organizationId: organizationId!,

View File

@@ -0,0 +1,146 @@
/**
* @generated SignedSource<<bd1f2132960c1cdd84906d7de58765e9>>
* @lightSyntaxTransform
* @nogrep
*/
/* tslint:disable */
/* eslint-disable */
// @ts-nocheck
import { ConcreteRequest } from 'relay-runtime';
export type AssignTaskInput = {
assignedToId: string;
taskId: string;
};
export type ControlOverviewPageAssignTaskMutation$variables = {
input: AssignTaskInput;
};
export type ControlOverviewPageAssignTaskMutation$data = {
readonly assignTask: {
readonly task: {
readonly assignedTo: {
readonly fullName: string;
readonly id: string;
readonly primaryEmailAddress: string;
} | null | undefined;
readonly id: string;
readonly version: number;
};
};
};
export type ControlOverviewPageAssignTaskMutation = {
response: ControlOverviewPageAssignTaskMutation$data;
variables: ControlOverviewPageAssignTaskMutation$variables;
};
const node: ConcreteRequest = (function(){
var v0 = [
{
"defaultValue": null,
"kind": "LocalArgument",
"name": "input"
}
],
v1 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "id",
"storageKey": null
},
v2 = [
{
"alias": null,
"args": [
{
"kind": "Variable",
"name": "input",
"variableName": "input"
}
],
"concreteType": "AssignTaskPayload",
"kind": "LinkedField",
"name": "assignTask",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"concreteType": "Task",
"kind": "LinkedField",
"name": "task",
"plural": false,
"selections": [
(v1/*: any*/),
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "version",
"storageKey": null
},
{
"alias": null,
"args": null,
"concreteType": "People",
"kind": "LinkedField",
"name": "assignedTo",
"plural": false,
"selections": [
(v1/*: any*/),
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "fullName",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "primaryEmailAddress",
"storageKey": null
}
],
"storageKey": null
}
],
"storageKey": null
}
],
"storageKey": null
}
];
return {
"fragment": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Fragment",
"metadata": null,
"name": "ControlOverviewPageAssignTaskMutation",
"selections": (v2/*: any*/),
"type": "Mutation",
"abstractKey": null
},
"kind": "Request",
"operation": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Operation",
"name": "ControlOverviewPageAssignTaskMutation",
"selections": (v2/*: any*/)
},
"params": {
"cacheID": "2a75b40af9d9853b851d153595dc1317",
"id": null,
"metadata": {},
"name": "ControlOverviewPageAssignTaskMutation",
"operationKind": "mutation",
"text": "mutation ControlOverviewPageAssignTaskMutation(\n $input: AssignTaskInput!\n) {\n assignTask(input: $input) {\n task {\n id\n version\n assignedTo {\n id\n fullName\n primaryEmailAddress\n }\n }\n }\n}\n"
}
};
})();
(node as any).hash = "02f3b1fb21bc39cea7fde9cc3945adc6";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<502600204c0e5180095f00fe3372ea5a>>
* @generated SignedSource<<1b8a07c3040e6ae6265d0b4eabc394ad>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -11,6 +11,7 @@
import { ConcreteRequest } from 'relay-runtime';
export type TaskState = "DONE" | "TODO";
export type CreateTaskInput = {
assignedToId?: string | null | undefined;
controlId: string;
description: string;
name: string;
@@ -24,6 +25,11 @@ export type ControlOverviewPageCreateTaskMutation$data = {
readonly createTask: {
readonly taskEdge: {
readonly node: {
readonly assignedTo: {
readonly fullName: string;
readonly id: string;
readonly primaryEmailAddress: string;
} | null | undefined;
readonly description: string;
readonly id: string;
readonly name: string;
@@ -57,6 +63,13 @@ v2 = [
}
],
v3 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "id",
"storageKey": null
},
v4 = {
"alias": null,
"args": null,
"concreteType": "TaskEdge",
@@ -72,13 +85,7 @@ v3 = {
"name": "node",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "id",
"storageKey": null
},
(v3/*: any*/),
{
"alias": null,
"args": null,
@@ -106,6 +113,32 @@ v3 = {
"kind": "ScalarField",
"name": "state",
"storageKey": null
},
{
"alias": null,
"args": null,
"concreteType": "People",
"kind": "LinkedField",
"name": "assignedTo",
"plural": false,
"selections": [
(v3/*: any*/),
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "fullName",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "primaryEmailAddress",
"storageKey": null
}
],
"storageKey": null
}
],
"storageKey": null
@@ -131,7 +164,7 @@ return {
"name": "createTask",
"plural": false,
"selections": [
(v3/*: any*/)
(v4/*: any*/)
],
"storageKey": null
}
@@ -156,7 +189,7 @@ return {
"name": "createTask",
"plural": false,
"selections": [
(v3/*: any*/),
(v4/*: any*/),
{
"alias": null,
"args": null,
@@ -179,16 +212,16 @@ return {
]
},
"params": {
"cacheID": "ed1842681cbb14392603c1b73e82b6f9",
"cacheID": "7e8741b4f438fecdf0d991843d0e206a",
"id": null,
"metadata": {},
"name": "ControlOverviewPageCreateTaskMutation",
"operationKind": "mutation",
"text": "mutation ControlOverviewPageCreateTaskMutation(\n $input: CreateTaskInput!\n) {\n createTask(input: $input) {\n taskEdge {\n node {\n id\n name\n description\n timeEstimate\n state\n }\n }\n }\n}\n"
"text": "mutation ControlOverviewPageCreateTaskMutation(\n $input: CreateTaskInput!\n) {\n createTask(input: $input) {\n taskEdge {\n node {\n id\n name\n description\n timeEstimate\n state\n assignedTo {\n id\n fullName\n primaryEmailAddress\n }\n }\n }\n }\n}\n"
}
};
})();
(node as any).hash = "d2e06ccdb00312c0862187a18f374d23";
(node as any).hash = "1622754b77775d1662f4cb6af68ca775";
export default node;

View File

@@ -0,0 +1,254 @@
/**
* @generated SignedSource<<50244c085e737eefef310f74fe8808a3>>
* @lightSyntaxTransform
* @nogrep
*/
/* tslint:disable */
/* eslint-disable */
// @ts-nocheck
import { ConcreteRequest } from 'relay-runtime';
export type ControlOverviewPageOrganizationQuery$variables = {
organizationId: string;
};
export type ControlOverviewPageOrganizationQuery$data = {
readonly organization: {
readonly id: string;
readonly peoples?: {
readonly edges: ReadonlyArray<{
readonly node: {
readonly fullName: string;
readonly id: string;
readonly primaryEmailAddress: string;
};
}>;
};
};
};
export type ControlOverviewPageOrganizationQuery = {
response: ControlOverviewPageOrganizationQuery$data;
variables: ControlOverviewPageOrganizationQuery$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 = [
{
"alias": null,
"args": null,
"concreteType": "PeopleEdge",
"kind": "LinkedField",
"name": "edges",
"plural": true,
"selections": [
{
"alias": null,
"args": null,
"concreteType": "People",
"kind": "LinkedField",
"name": "node",
"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
},
(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
}
],
"storageKey": null
}
],
v5 = [
{
"kind": "Literal",
"name": "first",
"value": 100
}
];
return {
"fragment": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Fragment",
"metadata": null,
"name": "ControlOverviewPageOrganizationQuery",
"selections": [
{
"alias": "organization",
"args": (v1/*: any*/),
"concreteType": null,
"kind": "LinkedField",
"name": "node",
"plural": false,
"selections": [
(v2/*: any*/),
{
"kind": "InlineFragment",
"selections": [
{
"alias": "peoples",
"args": null,
"concreteType": "PeopleConnection",
"kind": "LinkedField",
"name": "__ControlOverviewPage_peoples_connection",
"plural": false,
"selections": (v4/*: any*/),
"storageKey": null
}
],
"type": "Organization",
"abstractKey": null
}
],
"storageKey": null
}
],
"type": "Query",
"abstractKey": null
},
"kind": "Request",
"operation": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Operation",
"name": "ControlOverviewPageOrganizationQuery",
"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": (v5/*: any*/),
"concreteType": "PeopleConnection",
"kind": "LinkedField",
"name": "peoples",
"plural": false,
"selections": (v4/*: any*/),
"storageKey": "peoples(first:100)"
},
{
"alias": null,
"args": (v5/*: any*/),
"filters": null,
"handle": "connection",
"key": "ControlOverviewPage_peoples",
"kind": "LinkedHandle",
"name": "peoples"
}
],
"type": "Organization",
"abstractKey": null
}
],
"storageKey": null
}
]
},
"params": {
"cacheID": "2a407ffb628c6c0465efe741ba990440",
"id": null,
"metadata": {
"connection": [
{
"count": null,
"cursor": null,
"direction": "forward",
"path": [
"organization",
"peoples"
]
}
]
},
"name": "ControlOverviewPageOrganizationQuery",
"operationKind": "query",
"text": "query ControlOverviewPageOrganizationQuery(\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n id\n ... on Organization {\n peoples(first: 100) {\n edges {\n node {\n id\n fullName\n primaryEmailAddress\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n }\n}\n"
}
};
})();
(node as any).hash = "ba314af121e5a3d44f9001a7ada7a89a";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<1a0065809cf4bdeff6f4bb7ff087cdf7>>
* @generated SignedSource<<8f9fcd90d577e5e9f1b7ac31bbc1a14c>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -28,6 +28,11 @@ export type ControlOverviewPageQuery$data = {
readonly __id: string;
readonly edges: ReadonlyArray<{
readonly node: {
readonly assignedTo: {
readonly fullName: string;
readonly id: string;
readonly primaryEmailAddress: string;
} | null | undefined;
readonly description: string;
readonly evidences: {
readonly __id: string;
@@ -131,18 +136,44 @@ v9 = {
v10 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "__typename",
"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
},
v11 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "cursor",
"name": "__typename",
"storageKey": null
},
v12 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "cursor",
"storageKey": null
},
v13 = {
"alias": null,
"args": null,
"concreteType": "PageInfo",
@@ -167,7 +198,7 @@ v12 = {
],
"storageKey": null
},
v13 = {
v14 = {
"kind": "ClientExtension",
"selections": [
{
@@ -179,7 +210,7 @@ v13 = {
}
]
},
v14 = [
v15 = [
{
"alias": null,
"args": null,
@@ -226,25 +257,25 @@ v14 = [
"name": "createdAt",
"storageKey": null
},
(v10/*: any*/)
(v11/*: any*/)
],
"storageKey": null
},
(v11/*: any*/)
(v12/*: any*/)
],
"storageKey": null
},
(v12/*: any*/),
(v13/*: any*/)
(v13/*: any*/),
(v14/*: any*/)
],
v15 = [
v16 = [
{
"kind": "Literal",
"name": "first",
"value": 100
}
],
v16 = [
v17 = [
{
"kind": "Literal",
"name": "first",
@@ -305,6 +336,7 @@ return {
(v5/*: any*/),
(v8/*: any*/),
(v9/*: any*/),
(v10/*: any*/),
{
"alias": "evidences",
"args": null,
@@ -312,19 +344,19 @@ return {
"kind": "LinkedField",
"name": "__ControlOverviewPage_evidences_connection",
"plural": false,
"selections": (v14/*: any*/),
"selections": (v15/*: any*/),
"storageKey": null
},
(v10/*: any*/)
(v11/*: any*/)
],
"storageKey": null
},
(v11/*: any*/)
(v12/*: any*/)
],
"storageKey": null
},
(v12/*: any*/),
(v13/*: any*/)
(v13/*: any*/),
(v14/*: any*/)
],
"storageKey": null
}
@@ -353,7 +385,7 @@ return {
"name": "node",
"plural": false,
"selections": [
(v10/*: any*/),
(v11/*: any*/),
(v2/*: any*/),
{
"kind": "InlineFragment",
@@ -365,7 +397,7 @@ return {
(v7/*: any*/),
{
"alias": null,
"args": (v15/*: any*/),
"args": (v16/*: any*/),
"concreteType": "TaskConnection",
"kind": "LinkedField",
"name": "tasks",
@@ -393,41 +425,42 @@ return {
(v5/*: any*/),
(v8/*: any*/),
(v9/*: any*/),
(v10/*: any*/),
{
"alias": null,
"args": (v16/*: any*/),
"args": (v17/*: any*/),
"concreteType": "EvidenceConnection",
"kind": "LinkedField",
"name": "evidences",
"plural": false,
"selections": (v14/*: any*/),
"selections": (v15/*: any*/),
"storageKey": "evidences(first:50)"
},
{
"alias": null,
"args": (v16/*: any*/),
"args": (v17/*: any*/),
"filters": null,
"handle": "connection",
"key": "ControlOverviewPage_evidences",
"kind": "LinkedHandle",
"name": "evidences"
},
(v10/*: any*/)
(v11/*: any*/)
],
"storageKey": null
},
(v11/*: any*/)
(v12/*: any*/)
],
"storageKey": null
},
(v12/*: any*/),
(v13/*: any*/)
(v13/*: any*/),
(v14/*: any*/)
],
"storageKey": "tasks(first:100)"
},
{
"alias": null,
"args": (v15/*: any*/),
"args": (v16/*: any*/),
"filters": null,
"handle": "connection",
"key": "ControlOverviewPage_tasks",
@@ -444,7 +477,7 @@ return {
]
},
"params": {
"cacheID": "bd9679f5980ac0eed07f28e4f0cf4f27",
"cacheID": "1d26d59ea2232a213d01636e8d388919",
"id": null,
"metadata": {
"connection": [
@@ -467,11 +500,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 tasks(first: 100) {\n edges {\n node {\n id\n name\n description\n state\n timeEstimate\n version\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 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"
}
};
})();
(node as any).hash = "81d519cc3ea015284326fa7d5052b25f";
(node as any).hash = "e48b75fde2fcff42e868a0e68abd5809";
export default node;

View File

@@ -0,0 +1,145 @@
/**
* @generated SignedSource<<ec9f52c0ab13cd30148d7b2a97f59b63>>
* @lightSyntaxTransform
* @nogrep
*/
/* tslint:disable */
/* eslint-disable */
// @ts-nocheck
import { ConcreteRequest } from 'relay-runtime';
export type UnassignTaskInput = {
taskId: string;
};
export type ControlOverviewPageUnassignTaskMutation$variables = {
input: UnassignTaskInput;
};
export type ControlOverviewPageUnassignTaskMutation$data = {
readonly unassignTask: {
readonly task: {
readonly assignedTo: {
readonly fullName: string;
readonly id: string;
readonly primaryEmailAddress: string;
} | null | undefined;
readonly id: string;
readonly version: number;
};
};
};
export type ControlOverviewPageUnassignTaskMutation = {
response: ControlOverviewPageUnassignTaskMutation$data;
variables: ControlOverviewPageUnassignTaskMutation$variables;
};
const node: ConcreteRequest = (function(){
var v0 = [
{
"defaultValue": null,
"kind": "LocalArgument",
"name": "input"
}
],
v1 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "id",
"storageKey": null
},
v2 = [
{
"alias": null,
"args": [
{
"kind": "Variable",
"name": "input",
"variableName": "input"
}
],
"concreteType": "UnassignTaskPayload",
"kind": "LinkedField",
"name": "unassignTask",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"concreteType": "Task",
"kind": "LinkedField",
"name": "task",
"plural": false,
"selections": [
(v1/*: any*/),
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "version",
"storageKey": null
},
{
"alias": null,
"args": null,
"concreteType": "People",
"kind": "LinkedField",
"name": "assignedTo",
"plural": false,
"selections": [
(v1/*: any*/),
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "fullName",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "primaryEmailAddress",
"storageKey": null
}
],
"storageKey": null
}
],
"storageKey": null
}
],
"storageKey": null
}
];
return {
"fragment": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Fragment",
"metadata": null,
"name": "ControlOverviewPageUnassignTaskMutation",
"selections": (v2/*: any*/),
"type": "Mutation",
"abstractKey": null
},
"kind": "Request",
"operation": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Operation",
"name": "ControlOverviewPageUnassignTaskMutation",
"selections": (v2/*: any*/)
},
"params": {
"cacheID": "dc570710d28f3208dbaff23593819f4d",
"id": null,
"metadata": {},
"name": "ControlOverviewPageUnassignTaskMutation",
"operationKind": "mutation",
"text": "mutation ControlOverviewPageUnassignTaskMutation(\n $input: UnassignTaskInput!\n) {\n unassignTask(input: $input) {\n task {\n id\n version\n assignedTo {\n id\n fullName\n primaryEmailAddress\n }\n }\n }\n}\n"
}
};
})();
(node as any).hash = "4c809cd810a4178ab4f7a6d020338187";
export default node;

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<c6eaf570ef3d4e5a289ab266f6662546>>
* @generated SignedSource<<2e946185d02bd4e3d510d81c68cb9863>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -16,6 +16,7 @@ export type UpdateTaskInput = {
name?: string | null | undefined;
state?: TaskState | null | undefined;
taskId: string;
timeEstimate?: any | null | undefined;
};
export type ControlOverviewPageUpdateTaskStateMutation$variables = {
input: UpdateTaskInput;

View File

@@ -0,0 +1 @@
ALTER TABLE tasks ADD COLUMN assigned_to TEXT REFERENCES peoples(id);

View File

@@ -38,6 +38,7 @@ type (
CreatedAt time.Time `db:"created_at"`
UpdatedAt time.Time `db:"updated_at"`
Version int `db:"version"`
AssignedTo *gid.GID `db:"assigned_to"`
TimeEstimate time.Duration `db:"time_estimate"`
}
@@ -70,6 +71,7 @@ SELECT
description,
time_estimate,
state,
assigned_to,
content_ref,
created_at,
updated_at,
@@ -78,7 +80,7 @@ FROM
tasks
WHERE
%s
AND task_id = @task_id
AND id = @task_id
LIMIT 1;
`
@@ -119,7 +121,8 @@ INSERT INTO tasks (
updated_at,
version,
state,
time_estimate
time_estimate,
assigned_to
)
VALUES (
@tenant_id,
@@ -132,7 +135,8 @@ VALUES (
@updated_at,
@version,
@state,
@time_estimate
@time_estimate,
@assigned_to
);
`
@@ -148,6 +152,7 @@ VALUES (
"version": t.Version,
"state": t.State,
"time_estimate": t.TimeEstimate,
"assigned_to": t.AssignedTo,
}
_, err := conn.Exec(ctx, q, args)
return err
@@ -171,7 +176,8 @@ SELECT
content_ref,
created_at,
updated_at,
version
version,
assigned_to
FROM
tasks
WHERE
@@ -240,6 +246,58 @@ RETURNING
return err
}
func (t *Task) AssignTo(
ctx context.Context,
conn pg.Conn,
scope Scoper,
assignedTo gid.GID,
) error {
q := `
UPDATE tasks
SET
assigned_to = @assigned_to
WHERE
%s
AND id = @task_id
`
q = fmt.Sprintf(q, scope.SQLFragment())
args := pgx.StrictNamedArgs{
"task_id": t.ID,
"assigned_to": assignedTo,
}
maps.Copy(args, scope.SQLArguments())
_, err := conn.Exec(ctx, q, args)
return err
}
func (t *Task) Unassign(
ctx context.Context,
conn pg.Conn,
scope Scoper,
) error {
q := `
UPDATE tasks
SET
assigned_to = NULL
WHERE
%s
AND id = @task_id
`
q = fmt.Sprintf(q, scope.SQLFragment())
args := pgx.StrictNamedArgs{
"task_id": t.ID,
}
maps.Copy(args, scope.SQLArguments())
_, err := conn.Exec(ctx, q, args)
return err
}
func (t *Task) Delete(
ctx context.Context,
conn pg.Conn,

View File

@@ -36,6 +36,7 @@ type (
ContentRef string
Description string
TimeEstimate time.Duration
AssignedTo *gid.GID
}
UpdateTaskRequest struct {
@@ -67,6 +68,7 @@ func (s TaskService) Create(
State: coredata.TaskStateTodo,
Description: req.Description,
TimeEstimate: req.TimeEstimate,
AssignedTo: req.AssignedTo,
CreatedAt: now,
UpdatedAt: now,
}
@@ -93,6 +95,67 @@ func (s TaskService) Create(
return task, nil
}
func (s TaskService) Assign(
ctx context.Context,
taskID gid.GID,
assignedTo gid.GID,
) (*coredata.Task, error) {
task := &coredata.Task{ID: taskID}
err := s.svc.pg.WithTx(
ctx,
func(conn pg.Conn) error {
if err := task.LoadByID(ctx, conn, s.svc.scope, taskID); err != nil {
return fmt.Errorf("cannot load task %q: %w", taskID, err)
}
task.AssignedTo = &assignedTo
if err := task.AssignTo(ctx, conn, s.svc.scope, assignedTo); err != nil {
return fmt.Errorf("cannot assign task %q to %q: %w", taskID, assignedTo, err)
}
return nil
},
)
if err != nil {
return nil, err
}
return task, nil
}
func (s TaskService) Unassign(
ctx context.Context,
taskID gid.GID,
) (*coredata.Task, error) {
task := &coredata.Task{ID: taskID}
err := s.svc.pg.WithTx(
ctx,
func(conn pg.Conn) error {
if err := task.LoadByID(ctx, conn, s.svc.scope, taskID); err != nil {
return fmt.Errorf("cannot load task %q: %w", taskID, err)
}
task.AssignedTo = nil
if err := task.Unassign(ctx, conn, s.svc.scope); err != nil {
return fmt.Errorf("cannot unassign task %q: %w", taskID, err)
}
return nil
},
)
if err != nil {
return nil, err
}
return task, nil
}
func (s TaskService) Update(
ctx context.Context,
req UpdateTaskRequest,

View File

@@ -263,6 +263,7 @@ type Task implements Node {
description: String!
state: TaskState!
timeEstimate: Duration!
assignedTo: People @goField(forceResolver: true)
evidences(
first: Int
@@ -345,6 +346,8 @@ type Mutation {
createTask(input: CreateTaskInput!): CreateTaskPayload!
updateTask(input: UpdateTaskInput!): UpdateTaskPayload!
deleteTask(input: DeleteTaskInput!): DeleteTaskPayload!
assignTask(input: AssignTaskInput!): AssignTaskPayload!
unassignTask(input: UnassignTaskInput!): UnassignTaskPayload!
createFramework(input: CreateFrameworkInput!): CreateFrameworkPayload!
updateFramework(input: UpdateFrameworkInput!): UpdateFrameworkPayload!
@@ -488,6 +491,7 @@ input CreateTaskInput {
name: String!
description: String!
timeEstimate: Duration!
assignedToId: ID
}
type CreateTaskPayload {
@@ -646,6 +650,7 @@ input UpdateTaskInput {
name: String
description: String
state: TaskState
timeEstimate: Duration
}
type UpdateTaskPayload {
@@ -668,3 +673,20 @@ input ImportFrameworkInput {
type ImportFrameworkPayload {
frameworkEdge: FrameworkEdge!
}
input AssignTaskInput {
taskId: ID!
assignedToId: ID!
}
type AssignTaskPayload {
task: Task!
}
input UnassignTaskInput {
taskId: ID!
}
type UnassignTaskPayload {
task: Task!
}

View File

@@ -57,6 +57,10 @@ type DirectiveRoot struct {
}
type ComplexityRoot struct {
AssignTaskPayload struct {
Task func(childComplexity int) int
}
ConfirmEmailPayload struct {
Success func(childComplexity int) int
}
@@ -182,6 +186,7 @@ type ComplexityRoot struct {
}
Mutation struct {
AssignTask func(childComplexity int, input types.AssignTaskInput) int
ConfirmEmail func(childComplexity int, input types.ConfirmEmailInput) int
CreateControl func(childComplexity int, input types.CreateControlInput) int
CreateFramework func(childComplexity int, input types.CreateFrameworkInput) int
@@ -197,6 +202,7 @@ type ComplexityRoot struct {
DeleteTask func(childComplexity int, input types.DeleteTaskInput) int
DeleteVendor func(childComplexity int, input types.DeleteVendorInput) int
ImportFramework func(childComplexity int, input types.ImportFrameworkInput) int
UnassignTask func(childComplexity int, input types.UnassignTaskInput) int
UpdateControl func(childComplexity int, input types.UpdateControlInput) int
UpdateFramework func(childComplexity int, input types.UpdateFrameworkInput) int
UpdateOrganization func(childComplexity int, input types.UpdateOrganizationInput) int
@@ -290,6 +296,7 @@ type ComplexityRoot struct {
}
Task struct {
AssignedTo func(childComplexity int) int
CreatedAt func(childComplexity int) int
Description func(childComplexity int) int
Evidences func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey) int
@@ -311,6 +318,10 @@ type ComplexityRoot struct {
Node func(childComplexity int) int
}
UnassignTaskPayload struct {
Task func(childComplexity int) int
}
UpdateControlPayload struct {
Control func(childComplexity int) int
}
@@ -401,6 +412,8 @@ type MutationResolver interface {
CreateTask(ctx context.Context, input types.CreateTaskInput) (*types.CreateTaskPayload, error)
UpdateTask(ctx context.Context, input types.UpdateTaskInput) (*types.UpdateTaskPayload, error)
DeleteTask(ctx context.Context, input types.DeleteTaskInput) (*types.DeleteTaskPayload, error)
AssignTask(ctx context.Context, input types.AssignTaskInput) (*types.AssignTaskPayload, error)
UnassignTask(ctx context.Context, input types.UnassignTaskInput) (*types.UnassignTaskPayload, error)
CreateFramework(ctx context.Context, input types.CreateFrameworkInput) (*types.CreateFrameworkPayload, error)
UpdateFramework(ctx context.Context, input types.UpdateFrameworkInput) (*types.UpdateFrameworkPayload, error)
ImportFramework(ctx context.Context, input types.ImportFrameworkInput) (*types.ImportFrameworkPayload, error)
@@ -427,6 +440,7 @@ type QueryResolver interface {
Viewer(ctx context.Context) (*types.User, error)
}
type TaskResolver interface {
AssignedTo(ctx context.Context, obj *types.Task) (*types.People, error)
Evidences(ctx context.Context, obj *types.Task, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.EvidenceConnection, error)
}
type UserResolver interface {
@@ -452,6 +466,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
_ = ec
switch typeName + "." + field {
case "AssignTaskPayload.task":
if e.complexity.AssignTaskPayload.Task == nil {
break
}
return e.complexity.AssignTaskPayload.Task(childComplexity), true
case "ConfirmEmailPayload.success":
if e.complexity.ConfirmEmailPayload.Success == nil {
break
@@ -826,6 +847,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.ImportFrameworkPayload.FrameworkEdge(childComplexity), true
case "Mutation.assignTask":
if e.complexity.Mutation.AssignTask == nil {
break
}
args, err := ec.field_Mutation_assignTask_args(context.TODO(), rawArgs)
if err != nil {
return 0, false
}
return e.complexity.Mutation.AssignTask(childComplexity, args["input"].(types.AssignTaskInput)), true
case "Mutation.confirmEmail":
if e.complexity.Mutation.ConfirmEmail == nil {
break
@@ -1006,6 +1039,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.Mutation.ImportFramework(childComplexity, args["input"].(types.ImportFrameworkInput)), true
case "Mutation.unassignTask":
if e.complexity.Mutation.UnassignTask == nil {
break
}
args, err := ec.field_Mutation_unassignTask_args(context.TODO(), rawArgs)
if err != nil {
return 0, false
}
return e.complexity.Mutation.UnassignTask(childComplexity, args["input"].(types.UnassignTaskInput)), true
case "Mutation.updateControl":
if e.complexity.Mutation.UpdateControl == nil {
break
@@ -1449,6 +1494,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.Session.ID(childComplexity), true
case "Task.assignedTo":
if e.complexity.Task.AssignedTo == nil {
break
}
return e.complexity.Task.AssignedTo(childComplexity), true
case "Task.createdAt":
if e.complexity.Task.CreatedAt == nil {
break
@@ -1545,6 +1597,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.TaskEdge.Node(childComplexity), true
case "UnassignTaskPayload.task":
if e.complexity.UnassignTaskPayload.Task == nil {
break
}
return e.complexity.UnassignTaskPayload.Task(childComplexity), true
case "UpdateControlPayload.control":
if e.complexity.UpdateControlPayload.Control == nil {
break
@@ -1775,6 +1834,7 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler {
opCtx := graphql.GetOperationContext(ctx)
ec := executionContext{opCtx, e, 0, 0, make(chan graphql.DeferredResult)}
inputUnmarshalMap := graphql.BuildUnmarshalerMap(
ec.unmarshalInputAssignTaskInput,
ec.unmarshalInputConfirmEmailInput,
ec.unmarshalInputCreateControlInput,
ec.unmarshalInputCreateFrameworkInput,
@@ -1790,6 +1850,7 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler {
ec.unmarshalInputDeleteTaskInput,
ec.unmarshalInputDeleteVendorInput,
ec.unmarshalInputImportFrameworkInput,
ec.unmarshalInputUnassignTaskInput,
ec.unmarshalInputUpdateControlInput,
ec.unmarshalInputUpdateFrameworkInput,
ec.unmarshalInputUpdateOrganizationInput,
@@ -2160,6 +2221,7 @@ type Task implements Node {
description: String!
state: TaskState!
timeEstimate: Duration!
assignedTo: People @goField(forceResolver: true)
evidences(
first: Int
@@ -2242,6 +2304,8 @@ type Mutation {
createTask(input: CreateTaskInput!): CreateTaskPayload!
updateTask(input: UpdateTaskInput!): UpdateTaskPayload!
deleteTask(input: DeleteTaskInput!): DeleteTaskPayload!
assignTask(input: AssignTaskInput!): AssignTaskPayload!
unassignTask(input: UnassignTaskInput!): UnassignTaskPayload!
createFramework(input: CreateFrameworkInput!): CreateFrameworkPayload!
updateFramework(input: UpdateFrameworkInput!): UpdateFrameworkPayload!
@@ -2385,6 +2449,7 @@ input CreateTaskInput {
name: String!
description: String!
timeEstimate: Duration!
assignedToId: ID
}
type CreateTaskPayload {
@@ -2543,6 +2608,7 @@ input UpdateTaskInput {
name: String
description: String
state: TaskState
timeEstimate: Duration
}
type UpdateTaskPayload {
@@ -2565,6 +2631,23 @@ input ImportFrameworkInput {
type ImportFrameworkPayload {
frameworkEdge: FrameworkEdge!
}
input AssignTaskInput {
taskId: ID!
assignedToId: ID!
}
type AssignTaskPayload {
task: Task!
}
input UnassignTaskInput {
taskId: ID!
}
type UnassignTaskPayload {
task: Task!
}
`, BuiltIn: false},
}
var parsedSchema = gqlparser.MustLoadSchema(sources...)
@@ -2727,6 +2810,29 @@ func (ec *executionContext) field_Framework_controls_argsBefore(
return zeroVal, nil
}
func (ec *executionContext) field_Mutation_assignTask_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
var err error
args := map[string]any{}
arg0, err := ec.field_Mutation_assignTask_argsInput(ctx, rawArgs)
if err != nil {
return nil, err
}
args["input"] = arg0
return args, nil
}
func (ec *executionContext) field_Mutation_assignTask_argsInput(
ctx context.Context,
rawArgs map[string]any,
) (types.AssignTaskInput, error) {
ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("input"))
if tmp, ok := rawArgs["input"]; ok {
return ec.unmarshalNAssignTaskInput2githubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐAssignTaskInput(ctx, tmp)
}
var zeroVal types.AssignTaskInput
return zeroVal, nil
}
func (ec *executionContext) field_Mutation_confirmEmail_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
var err error
args := map[string]any{}
@@ -3072,6 +3178,29 @@ func (ec *executionContext) field_Mutation_importFramework_argsInput(
return zeroVal, nil
}
func (ec *executionContext) field_Mutation_unassignTask_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
var err error
args := map[string]any{}
arg0, err := ec.field_Mutation_unassignTask_argsInput(ctx, rawArgs)
if err != nil {
return nil, err
}
args["input"] = arg0
return args, nil
}
func (ec *executionContext) field_Mutation_unassignTask_argsInput(
ctx context.Context,
rawArgs map[string]any,
) (types.UnassignTaskInput, error) {
ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("input"))
if tmp, ok := rawArgs["input"]; ok {
return ec.unmarshalNUnassignTaskInput2githubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐUnassignTaskInput(ctx, tmp)
}
var zeroVal types.UnassignTaskInput
return zeroVal, nil
}
func (ec *executionContext) field_Mutation_updateControl_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
var err error
args := map[string]any{}
@@ -3864,6 +3993,66 @@ func (ec *executionContext) field___Type_fields_argsIncludeDeprecated(
// region **************************** field.gotpl *****************************
func (ec *executionContext) _AssignTaskPayload_task(ctx context.Context, field graphql.CollectedField, obj *types.AssignTaskPayload) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_AssignTaskPayload_task(ctx, field)
if err != nil {
return graphql.Null
}
ctx = graphql.WithFieldContext(ctx, fc)
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
ctx = rctx // use context from middleware stack in children
return obj.Task, nil
})
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
if resTmp == nil {
if !graphql.HasFieldError(ctx, fc) {
ec.Errorf(ctx, "must not be null")
}
return graphql.Null
}
res := resTmp.(*types.Task)
fc.Result = res
return ec.marshalNTask2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐTask(ctx, field.Selections, res)
}
func (ec *executionContext) fieldContext_AssignTaskPayload_task(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
fc = &graphql.FieldContext{
Object: "AssignTaskPayload",
Field: field,
IsMethod: false,
IsResolver: false,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
switch field.Name {
case "id":
return ec.fieldContext_Task_id(ctx, field)
case "version":
return ec.fieldContext_Task_version(ctx, field)
case "name":
return ec.fieldContext_Task_name(ctx, field)
case "description":
return ec.fieldContext_Task_description(ctx, field)
case "state":
return ec.fieldContext_Task_state(ctx, field)
case "timeEstimate":
return ec.fieldContext_Task_timeEstimate(ctx, field)
case "assignedTo":
return ec.fieldContext_Task_assignedTo(ctx, field)
case "evidences":
return ec.fieldContext_Task_evidences(ctx, field)
case "createdAt":
return ec.fieldContext_Task_createdAt(ctx, field)
case "updatedAt":
return ec.fieldContext_Task_updatedAt(ctx, field)
}
return nil, fmt.Errorf("no field named %q was found under type Task", field.Name)
},
}
return fc, nil
}
func (ec *executionContext) _ConfirmEmailPayload_success(ctx context.Context, field graphql.CollectedField, obj *types.ConfirmEmailPayload) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_ConfirmEmailPayload_success(ctx, field)
if err != nil {
@@ -6578,6 +6767,100 @@ func (ec *executionContext) fieldContext_Mutation_deleteTask(ctx context.Context
return fc, nil
}
func (ec *executionContext) _Mutation_assignTask(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_Mutation_assignTask(ctx, field)
if err != nil {
return graphql.Null
}
ctx = graphql.WithFieldContext(ctx, fc)
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
ctx = rctx // use context from middleware stack in children
return ec.resolvers.Mutation().AssignTask(rctx, fc.Args["input"].(types.AssignTaskInput))
})
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
if resTmp == nil {
if !graphql.HasFieldError(ctx, fc) {
ec.Errorf(ctx, "must not be null")
}
return graphql.Null
}
res := resTmp.(*types.AssignTaskPayload)
fc.Result = res
return ec.marshalNAssignTaskPayload2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐAssignTaskPayload(ctx, field.Selections, res)
}
func (ec *executionContext) fieldContext_Mutation_assignTask(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
fc = &graphql.FieldContext{
Object: "Mutation",
Field: field,
IsMethod: true,
IsResolver: true,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
switch field.Name {
case "task":
return ec.fieldContext_AssignTaskPayload_task(ctx, field)
}
return nil, fmt.Errorf("no field named %q was found under type AssignTaskPayload", field.Name)
},
}
ctx = graphql.WithFieldContext(ctx, fc)
if fc.Args, err = ec.field_Mutation_assignTask_args(ctx, field.ArgumentMap(ec.Variables)); err != nil {
ec.Error(ctx, err)
return fc, err
}
return fc, nil
}
func (ec *executionContext) _Mutation_unassignTask(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_Mutation_unassignTask(ctx, field)
if err != nil {
return graphql.Null
}
ctx = graphql.WithFieldContext(ctx, fc)
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
ctx = rctx // use context from middleware stack in children
return ec.resolvers.Mutation().UnassignTask(rctx, fc.Args["input"].(types.UnassignTaskInput))
})
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
if resTmp == nil {
if !graphql.HasFieldError(ctx, fc) {
ec.Errorf(ctx, "must not be null")
}
return graphql.Null
}
res := resTmp.(*types.UnassignTaskPayload)
fc.Result = res
return ec.marshalNUnassignTaskPayload2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐUnassignTaskPayload(ctx, field.Selections, res)
}
func (ec *executionContext) fieldContext_Mutation_unassignTask(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
fc = &graphql.FieldContext{
Object: "Mutation",
Field: field,
IsMethod: true,
IsResolver: true,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
switch field.Name {
case "task":
return ec.fieldContext_UnassignTaskPayload_task(ctx, field)
}
return nil, fmt.Errorf("no field named %q was found under type UnassignTaskPayload", field.Name)
},
}
ctx = graphql.WithFieldContext(ctx, fc)
if fc.Args, err = ec.field_Mutation_unassignTask_args(ctx, field.ArgumentMap(ec.Variables)); err != nil {
ec.Error(ctx, err)
return fc, err
}
return fc, nil
}
func (ec *executionContext) _Mutation_createFramework(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_Mutation_createFramework(ctx, field)
if err != nil {
@@ -9362,6 +9645,59 @@ func (ec *executionContext) fieldContext_Task_timeEstimate(_ context.Context, fi
return fc, nil
}
func (ec *executionContext) _Task_assignedTo(ctx context.Context, field graphql.CollectedField, obj *types.Task) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_Task_assignedTo(ctx, field)
if err != nil {
return graphql.Null
}
ctx = graphql.WithFieldContext(ctx, fc)
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
ctx = rctx // use context from middleware stack in children
return ec.resolvers.Task().AssignedTo(rctx, obj)
})
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
if resTmp == nil {
return graphql.Null
}
res := resTmp.(*types.People)
fc.Result = res
return ec.marshalOPeople2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐPeople(ctx, field.Selections, res)
}
func (ec *executionContext) fieldContext_Task_assignedTo(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
fc = &graphql.FieldContext{
Object: "Task",
Field: field,
IsMethod: true,
IsResolver: true,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
switch field.Name {
case "id":
return ec.fieldContext_People_id(ctx, field)
case "fullName":
return ec.fieldContext_People_fullName(ctx, field)
case "primaryEmailAddress":
return ec.fieldContext_People_primaryEmailAddress(ctx, field)
case "additionalEmailAddresses":
return ec.fieldContext_People_additionalEmailAddresses(ctx, field)
case "kind":
return ec.fieldContext_People_kind(ctx, field)
case "createdAt":
return ec.fieldContext_People_createdAt(ctx, field)
case "updatedAt":
return ec.fieldContext_People_updatedAt(ctx, field)
case "version":
return ec.fieldContext_People_version(ctx, field)
}
return nil, fmt.Errorf("no field named %q was found under type People", field.Name)
},
}
return fc, nil
}
func (ec *executionContext) _Task_evidences(ctx context.Context, field graphql.CollectedField, obj *types.Task) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_Task_evidences(ctx, field)
if err != nil {
@@ -9662,6 +9998,68 @@ func (ec *executionContext) fieldContext_TaskEdge_node(_ context.Context, field
return ec.fieldContext_Task_state(ctx, field)
case "timeEstimate":
return ec.fieldContext_Task_timeEstimate(ctx, field)
case "assignedTo":
return ec.fieldContext_Task_assignedTo(ctx, field)
case "evidences":
return ec.fieldContext_Task_evidences(ctx, field)
case "createdAt":
return ec.fieldContext_Task_createdAt(ctx, field)
case "updatedAt":
return ec.fieldContext_Task_updatedAt(ctx, field)
}
return nil, fmt.Errorf("no field named %q was found under type Task", field.Name)
},
}
return fc, nil
}
func (ec *executionContext) _UnassignTaskPayload_task(ctx context.Context, field graphql.CollectedField, obj *types.UnassignTaskPayload) (ret graphql.Marshaler) {
fc, err := ec.fieldContext_UnassignTaskPayload_task(ctx, field)
if err != nil {
return graphql.Null
}
ctx = graphql.WithFieldContext(ctx, fc)
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
ctx = rctx // use context from middleware stack in children
return obj.Task, nil
})
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
if resTmp == nil {
if !graphql.HasFieldError(ctx, fc) {
ec.Errorf(ctx, "must not be null")
}
return graphql.Null
}
res := resTmp.(*types.Task)
fc.Result = res
return ec.marshalNTask2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐTask(ctx, field.Selections, res)
}
func (ec *executionContext) fieldContext_UnassignTaskPayload_task(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
fc = &graphql.FieldContext{
Object: "UnassignTaskPayload",
Field: field,
IsMethod: false,
IsResolver: false,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
switch field.Name {
case "id":
return ec.fieldContext_Task_id(ctx, field)
case "version":
return ec.fieldContext_Task_version(ctx, field)
case "name":
return ec.fieldContext_Task_name(ctx, field)
case "description":
return ec.fieldContext_Task_description(ctx, field)
case "state":
return ec.fieldContext_Task_state(ctx, field)
case "timeEstimate":
return ec.fieldContext_Task_timeEstimate(ctx, field)
case "assignedTo":
return ec.fieldContext_Task_assignedTo(ctx, field)
case "evidences":
return ec.fieldContext_Task_evidences(ctx, field)
case "createdAt":
@@ -10006,6 +10404,8 @@ func (ec *executionContext) fieldContext_UpdateTaskPayload_task(_ context.Contex
return ec.fieldContext_Task_state(ctx, field)
case "timeEstimate":
return ec.fieldContext_Task_timeEstimate(ctx, field)
case "assignedTo":
return ec.fieldContext_Task_assignedTo(ctx, field)
case "evidences":
return ec.fieldContext_Task_evidences(ctx, field)
case "createdAt":
@@ -12745,6 +13145,40 @@ func (ec *executionContext) fieldContext___Type_isOneOf(_ context.Context, field
// region **************************** input.gotpl *****************************
func (ec *executionContext) unmarshalInputAssignTaskInput(ctx context.Context, obj any) (types.AssignTaskInput, error) {
var it types.AssignTaskInput
asMap := map[string]any{}
for k, v := range obj.(map[string]any) {
asMap[k] = v
}
fieldsInOrder := [...]string{"taskId", "assignedToId"}
for _, k := range fieldsInOrder {
v, ok := asMap[k]
if !ok {
continue
}
switch k {
case "taskId":
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("taskId"))
data, err := ec.unmarshalNID2githubᚗcomᚋgetproboᚋproboᚋpkgᚋgidᚐGID(ctx, v)
if err != nil {
return it, err
}
it.TaskID = data
case "assignedToId":
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("assignedToId"))
data, err := ec.unmarshalNID2githubᚗcomᚋgetproboᚋproboᚋpkgᚋgidᚐGID(ctx, v)
if err != nil {
return it, err
}
it.AssignedToID = data
}
}
return it, nil
}
func (ec *executionContext) unmarshalInputConfirmEmailInput(ctx context.Context, obj any) (types.ConfirmEmailInput, error) {
var it types.ConfirmEmailInput
asMap := map[string]any{}
@@ -13019,7 +13453,7 @@ func (ec *executionContext) unmarshalInputCreateTaskInput(ctx context.Context, o
asMap[k] = v
}
fieldsInOrder := [...]string{"controlId", "name", "description", "timeEstimate"}
fieldsInOrder := [...]string{"controlId", "name", "description", "timeEstimate", "assignedToId"}
for _, k := range fieldsInOrder {
v, ok := asMap[k]
if !ok {
@@ -13054,6 +13488,13 @@ func (ec *executionContext) unmarshalInputCreateTaskInput(ctx context.Context, o
return it, err
}
it.TimeEstimate = data
case "assignedToId":
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("assignedToId"))
data, err := ec.unmarshalOID2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋgidᚐGID(ctx, v)
if err != nil {
return it, err
}
it.AssignedToID = data
}
}
@@ -13346,6 +13787,33 @@ func (ec *executionContext) unmarshalInputImportFrameworkInput(ctx context.Conte
return it, nil
}
func (ec *executionContext) unmarshalInputUnassignTaskInput(ctx context.Context, obj any) (types.UnassignTaskInput, error) {
var it types.UnassignTaskInput
asMap := map[string]any{}
for k, v := range obj.(map[string]any) {
asMap[k] = v
}
fieldsInOrder := [...]string{"taskId"}
for _, k := range fieldsInOrder {
v, ok := asMap[k]
if !ok {
continue
}
switch k {
case "taskId":
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("taskId"))
data, err := ec.unmarshalNID2githubᚗcomᚋgetproboᚋproboᚋpkgᚋgidᚐGID(ctx, v)
if err != nil {
return it, err
}
it.TaskID = data
}
}
return it, nil
}
func (ec *executionContext) unmarshalInputUpdateControlInput(ctx context.Context, obj any) (types.UpdateControlInput, error) {
var it types.UpdateControlInput
asMap := map[string]any{}
@@ -13642,7 +14110,7 @@ func (ec *executionContext) unmarshalInputUpdateTaskInput(ctx context.Context, o
asMap[k] = v
}
fieldsInOrder := [...]string{"taskId", "expectedVersion", "name", "description", "state"}
fieldsInOrder := [...]string{"taskId", "expectedVersion", "name", "description", "state", "timeEstimate"}
for _, k := range fieldsInOrder {
v, ok := asMap[k]
if !ok {
@@ -13684,6 +14152,13 @@ func (ec *executionContext) unmarshalInputUpdateTaskInput(ctx context.Context, o
return it, err
}
it.State = data
case "timeEstimate":
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("timeEstimate"))
data, err := ec.unmarshalODuration2ᚖtimeᚐDuration(ctx, v)
if err != nil {
return it, err
}
it.TimeEstimate = data
}
}
@@ -13908,6 +14383,45 @@ func (ec *executionContext) _Node(ctx context.Context, sel ast.SelectionSet, obj
// region **************************** object.gotpl ****************************
var assignTaskPayloadImplementors = []string{"AssignTaskPayload"}
func (ec *executionContext) _AssignTaskPayload(ctx context.Context, sel ast.SelectionSet, obj *types.AssignTaskPayload) graphql.Marshaler {
fields := graphql.CollectFields(ec.OperationContext, sel, assignTaskPayloadImplementors)
out := graphql.NewFieldSet(fields)
deferred := make(map[string]*graphql.FieldSet)
for i, field := range fields {
switch field.Name {
case "__typename":
out.Values[i] = graphql.MarshalString("AssignTaskPayload")
case "task":
out.Values[i] = ec._AssignTaskPayload_task(ctx, field, obj)
if out.Values[i] == graphql.Null {
out.Invalids++
}
default:
panic("unknown field " + strconv.Quote(field.Name))
}
}
out.Dispatch(ctx)
if out.Invalids > 0 {
return graphql.Null
}
atomic.AddInt32(&ec.deferred, int32(len(deferred)))
for label, dfs := range deferred {
ec.processDeferredGroup(graphql.DeferredGroup{
Label: label,
Path: graphql.GetPath(ctx),
FieldSet: dfs,
Context: ctx,
})
}
return out
}
var confirmEmailPayloadImplementors = []string{"ConfirmEmailPayload"}
func (ec *executionContext) _ConfirmEmailPayload(ctx context.Context, sel ast.SelectionSet, obj *types.ConfirmEmailPayload) graphql.Marshaler {
@@ -15165,6 +15679,20 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet)
if out.Values[i] == graphql.Null {
out.Invalids++
}
case "assignTask":
out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) {
return ec._Mutation_assignTask(ctx, field)
})
if out.Values[i] == graphql.Null {
out.Invalids++
}
case "unassignTask":
out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) {
return ec._Mutation_unassignTask(ctx, field)
})
if out.Values[i] == graphql.Null {
out.Invalids++
}
case "createFramework":
out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) {
return ec._Mutation_createFramework(ctx, field)
@@ -16105,6 +16633,34 @@ func (ec *executionContext) _Task(ctx context.Context, sel ast.SelectionSet, obj
if out.Values[i] == graphql.Null {
atomic.AddUint32(&out.Invalids, 1)
}
case "assignedTo":
field := field
innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) {
res = ec._Task_assignedTo(ctx, field, obj)
return res
}
if field.Deferrable != nil {
dfs, ok := deferred[field.Deferrable.Label]
di := 0
if ok {
dfs.AddField(field)
di = len(dfs.Values) - 1
} else {
dfs = graphql.NewFieldSet([]graphql.CollectedField{field})
deferred[field.Deferrable.Label] = dfs
}
dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler {
return innerFunc(ctx, dfs)
})
// don't run the out.Concurrently() call below
out.Values[i] = graphql.Null
continue
}
out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) })
case "evidences":
field := field
@@ -16257,6 +16813,45 @@ func (ec *executionContext) _TaskEdge(ctx context.Context, sel ast.SelectionSet,
return out
}
var unassignTaskPayloadImplementors = []string{"UnassignTaskPayload"}
func (ec *executionContext) _UnassignTaskPayload(ctx context.Context, sel ast.SelectionSet, obj *types.UnassignTaskPayload) graphql.Marshaler {
fields := graphql.CollectFields(ec.OperationContext, sel, unassignTaskPayloadImplementors)
out := graphql.NewFieldSet(fields)
deferred := make(map[string]*graphql.FieldSet)
for i, field := range fields {
switch field.Name {
case "__typename":
out.Values[i] = graphql.MarshalString("UnassignTaskPayload")
case "task":
out.Values[i] = ec._UnassignTaskPayload_task(ctx, field, obj)
if out.Values[i] == graphql.Null {
out.Invalids++
}
default:
panic("unknown field " + strconv.Quote(field.Name))
}
}
out.Dispatch(ctx)
if out.Invalids > 0 {
return graphql.Null
}
atomic.AddInt32(&ec.deferred, int32(len(deferred)))
for label, dfs := range deferred {
ec.processDeferredGroup(graphql.DeferredGroup{
Label: label,
Path: graphql.GetPath(ctx),
FieldSet: dfs,
Context: ctx,
})
}
return out
}
var updateControlPayloadImplementors = []string{"UpdateControlPayload"}
func (ec *executionContext) _UpdateControlPayload(ctx context.Context, sel ast.SelectionSet, obj *types.UpdateControlPayload) graphql.Marshaler {
@@ -17169,6 +17764,25 @@ func (ec *executionContext) ___Type(ctx context.Context, sel ast.SelectionSet, o
// region ***************************** type.gotpl *****************************
func (ec *executionContext) unmarshalNAssignTaskInput2githubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐAssignTaskInput(ctx context.Context, v any) (types.AssignTaskInput, error) {
res, err := ec.unmarshalInputAssignTaskInput(ctx, v)
return res, graphql.ErrorOnPath(ctx, err)
}
func (ec *executionContext) marshalNAssignTaskPayload2githubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐAssignTaskPayload(ctx context.Context, sel ast.SelectionSet, v types.AssignTaskPayload) graphql.Marshaler {
return ec._AssignTaskPayload(ctx, sel, &v)
}
func (ec *executionContext) marshalNAssignTaskPayload2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐAssignTaskPayload(ctx context.Context, sel ast.SelectionSet, v *types.AssignTaskPayload) graphql.Marshaler {
if v == nil {
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
ec.Errorf(ctx, "the requested element is null which the schema does not allow")
}
return graphql.Null
}
return ec._AssignTaskPayload(ctx, sel, v)
}
func (ec *executionContext) unmarshalNBoolean2bool(ctx context.Context, v any) (bool, error) {
res, err := graphql.UnmarshalBoolean(v)
return res, graphql.ErrorOnPath(ctx, err)
@@ -18347,6 +18961,25 @@ var (
}
)
func (ec *executionContext) unmarshalNUnassignTaskInput2githubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐUnassignTaskInput(ctx context.Context, v any) (types.UnassignTaskInput, error) {
res, err := ec.unmarshalInputUnassignTaskInput(ctx, v)
return res, graphql.ErrorOnPath(ctx, err)
}
func (ec *executionContext) marshalNUnassignTaskPayload2githubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐUnassignTaskPayload(ctx context.Context, sel ast.SelectionSet, v types.UnassignTaskPayload) graphql.Marshaler {
return ec._UnassignTaskPayload(ctx, sel, &v)
}
func (ec *executionContext) marshalNUnassignTaskPayload2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐUnassignTaskPayload(ctx context.Context, sel ast.SelectionSet, v *types.UnassignTaskPayload) graphql.Marshaler {
if v == nil {
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
ec.Errorf(ctx, "the requested element is null which the schema does not allow")
}
return graphql.Null
}
return ec._UnassignTaskPayload(ctx, sel, v)
}
func (ec *executionContext) unmarshalNUpdateControlInput2githubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐUpdateControlInput(ctx context.Context, v any) (types.UpdateControlInput, error) {
res, err := ec.unmarshalInputUpdateControlInput(ctx, v)
return res, graphql.ErrorOnPath(ctx, err)
@@ -18949,6 +19582,22 @@ func (ec *executionContext) marshalODatetime2ᚖtimeᚐTime(ctx context.Context,
return res
}
func (ec *executionContext) unmarshalODuration2ᚖtimeᚐDuration(ctx context.Context, v any) (*time.Duration, error) {
if v == nil {
return nil, nil
}
res, err := graphql.UnmarshalDuration(v)
return &res, graphql.ErrorOnPath(ctx, err)
}
func (ec *executionContext) marshalODuration2ᚖtimeᚐDuration(ctx context.Context, sel ast.SelectionSet, v *time.Duration) graphql.Marshaler {
if v == nil {
return graphql.Null
}
res := graphql.MarshalDuration(*v)
return res
}
func (ec *executionContext) unmarshalOID2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋgidᚐGID(ctx context.Context, v any) (*gid.GID, error) {
if v == nil {
return nil, nil
@@ -18981,6 +19630,13 @@ func (ec *executionContext) marshalOInt2ᚖint(ctx context.Context, sel ast.Sele
return res
}
func (ec *executionContext) marshalOPeople2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐPeople(ctx context.Context, sel ast.SelectionSet, v *types.People) graphql.Marshaler {
if v == nil {
return graphql.Null
}
return ec._People(ctx, sel, v)
}
func (ec *executionContext) unmarshalOPeopleKind2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋcoredataᚐPeopleKind(ctx context.Context, v any) (*coredata.PeopleKind, error) {
if v == nil {
return nil, nil

View File

@@ -16,6 +16,15 @@ type Node interface {
GetID() gid.GID
}
type AssignTaskInput struct {
TaskID gid.GID `json:"taskId"`
AssignedToID gid.GID `json:"assignedToId"`
}
type AssignTaskPayload struct {
Task *Task `json:"task"`
}
type ConfirmEmailInput struct {
Token string `json:"token"`
}
@@ -110,6 +119,7 @@ type CreateTaskInput struct {
Name string `json:"name"`
Description string `json:"description"`
TimeEstimate time.Duration `json:"timeEstimate"`
AssignedToID *gid.GID `json:"assignedToId,omitempty"`
}
type CreateTaskPayload struct {
@@ -336,6 +346,7 @@ type Task struct {
Description string `json:"description"`
State coredata.TaskState `json:"state"`
TimeEstimate time.Duration `json:"timeEstimate"`
AssignedTo *People `json:"assignedTo,omitempty"`
Evidences *EvidenceConnection `json:"evidences"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
@@ -354,6 +365,14 @@ type TaskEdge struct {
Node *Task `json:"node"`
}
type UnassignTaskInput struct {
TaskID gid.GID `json:"taskId"`
}
type UnassignTaskPayload struct {
Task *Task `json:"task"`
}
type UpdateControlInput struct {
ID gid.GID `json:"id"`
ExpectedVersion int `json:"expectedVersion"`
@@ -422,6 +441,7 @@ type UpdateTaskInput struct {
Name *string `json:"name,omitempty"`
Description *string `json:"description,omitempty"`
State *coredata.TaskState `json:"state,omitempty"`
TimeEstimate *time.Duration `json:"timeEstimate,omitempty"`
}
type UpdateTaskPayload struct {

View File

@@ -255,6 +255,34 @@ func (r *mutationResolver) DeleteTask(ctx context.Context, input types.DeleteTas
}, nil
}
// AssignTask is the resolver for the assignTask field.
func (r *mutationResolver) AssignTask(ctx context.Context, input types.AssignTaskInput) (*types.AssignTaskPayload, error) {
svc := r.GetTenantServiceIfAuthorized(ctx, input.TaskID.TenantID())
task, err := svc.Tasks.Assign(ctx, input.TaskID, input.AssignedToID)
if err != nil {
return nil, fmt.Errorf("cannot assign task: %w", err)
}
return &types.AssignTaskPayload{
Task: types.NewTask(task),
}, nil
}
// UnassignTask is the resolver for the unassignTask field.
func (r *mutationResolver) UnassignTask(ctx context.Context, input types.UnassignTaskInput) (*types.UnassignTaskPayload, error) {
svc := r.GetTenantServiceIfAuthorized(ctx, input.TaskID.TenantID())
task, err := svc.Tasks.Unassign(ctx, input.TaskID)
if err != nil {
return nil, fmt.Errorf("cannot unassign task: %w", err)
}
return &types.UnassignTaskPayload{
Task: types.NewTask(task),
}, nil
}
// CreateFramework is the resolver for the createFramework field.
func (r *mutationResolver) CreateFramework(ctx context.Context, input types.CreateFrameworkInput) (*types.CreateFrameworkPayload, error) {
svc := r.GetTenantServiceIfAuthorized(ctx, input.OrganizationID.TenantID())
@@ -581,6 +609,27 @@ func (r *queryResolver) Viewer(ctx context.Context) (*types.User, error) {
return types.NewUser(user), nil
}
// AssignedTo is the resolver for the assignedTo field.
func (r *taskResolver) AssignedTo(ctx context.Context, obj *types.Task) (*types.People, error) {
svc := r.GetTenantServiceIfAuthorized(ctx, obj.ID.TenantID())
task, err := svc.Tasks.Get(ctx, obj.ID)
if err != nil {
return nil, fmt.Errorf("cannot get task: %w", err)
}
if task.AssignedTo == nil {
return nil, nil
}
people, err := svc.Peoples.Get(ctx, *task.AssignedTo)
if err != nil {
return nil, fmt.Errorf("cannot get assigned to: %w", err)
}
return types.NewPeople(people), nil
}
// Evidences is the resolver for the evidences field.
func (r *taskResolver) Evidences(ctx context.Context, obj *types.Task, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.EvidenceConnection, error) {
svc := r.GetTenantServiceIfAuthorized(ctx, obj.ID.TenantID())