Add deadline on task
Signed-off-by: Andreas Reußner <andreas.reussner@outlook.de>
This commit is contained in:
committed by
Sacha Al Himdani
parent
02ff3b02d9
commit
fc008c27f4
@@ -109,6 +109,7 @@ import { MeasureViewRisksQuery } from "./__generated__/MeasureViewRisksQuery.gra
|
||||
import { MeasureViewDeleteMeasureMutation } from "./__generated__/MeasureViewDeleteMeasureMutation.graphql";
|
||||
import remarkGfm from "remark-gfm";
|
||||
import rehypeRaw from "rehype-raw";
|
||||
import { format, formatISO, parseISO } from "date-fns";
|
||||
|
||||
// Function to format ISO8601 duration to human-readable format
|
||||
const formatDuration = (isoDuration: string): string => {
|
||||
@@ -181,6 +182,7 @@ const measureViewQuery = graphql`
|
||||
description
|
||||
state
|
||||
timeEstimate
|
||||
deadline
|
||||
assignedTo {
|
||||
id
|
||||
fullName
|
||||
@@ -218,6 +220,7 @@ const updateTaskStateMutation = graphql`
|
||||
id
|
||||
state
|
||||
timeEstimate
|
||||
deadline
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -235,6 +238,7 @@ const createTaskMutation = graphql`
|
||||
name
|
||||
description
|
||||
timeEstimate
|
||||
deadline
|
||||
state
|
||||
assignedTo {
|
||||
id
|
||||
@@ -743,6 +747,7 @@ function MeasureViewContent({
|
||||
const [isCreateTaskOpen, setIsCreateTaskOpen] = useState(false);
|
||||
const [newTaskName, setNewTaskName] = useState("");
|
||||
const [newTaskDescription, setNewTaskDescription] = useState("");
|
||||
const [newDeadline, setNewDeadline] = useState("");
|
||||
const [timeEstimateDays, setTimeEstimateDays] = useState("");
|
||||
const [timeEstimateHours, setTimeEstimateHours] = useState("");
|
||||
const [timeEstimateMinutes, setTimeEstimateMinutes] = useState("");
|
||||
@@ -991,6 +996,7 @@ function MeasureViewContent({
|
||||
name: newTaskName,
|
||||
description: newTaskDescription,
|
||||
timeEstimate: isoTimeEstimate === "" ? null : isoTimeEstimate,
|
||||
deadline: newDeadline === "" ? null : formatISO(newDeadline),
|
||||
},
|
||||
},
|
||||
onCompleted: () => {
|
||||
@@ -1004,6 +1010,7 @@ function MeasureViewContent({
|
||||
setTimeEstimateHours("");
|
||||
setTimeEstimateMinutes("");
|
||||
setIsCreateTaskOpen(false);
|
||||
setNewDeadline("");
|
||||
},
|
||||
onError: (error) => {
|
||||
toast({
|
||||
@@ -1718,9 +1725,11 @@ function MeasureViewContent({
|
||||
|
||||
// Add state variables for tracking edit mode and duration components
|
||||
const [isEditingDuration, setIsEditingDuration] = useState(false);
|
||||
const [isEditingDeadline, setIsEditingDeadline] = useState(false);
|
||||
const [editTimeEstimateDays, setEditTimeEstimateDays] = useState("");
|
||||
const [editTimeEstimateHours, setEditTimeEstimateHours] = useState("");
|
||||
const [editTimeEstimateMinutes, setEditTimeEstimateMinutes] = useState("");
|
||||
const [editDeadline, setEditDeadline] = useState("");
|
||||
|
||||
// Function to parse ISO duration string into components for editing
|
||||
const parseISODuration = useCallback(
|
||||
@@ -1750,6 +1759,40 @@ function MeasureViewContent({
|
||||
[]
|
||||
);
|
||||
|
||||
// Function to handle saving the updated deadline
|
||||
const handleSaveDeadline = useCallback(
|
||||
(taskId: string) => {
|
||||
const newDeadline = editDeadline === "" ? null : formatISO(editDeadline);
|
||||
updateTask({
|
||||
variables: {
|
||||
input: {
|
||||
taskId,
|
||||
deadline: newDeadline,
|
||||
},
|
||||
},
|
||||
onCompleted: () => {
|
||||
setIsEditingDeadline(false);
|
||||
|
||||
// Update the selected task state if it's the current task
|
||||
if (selectedTask && selectedTask.id === taskId) {
|
||||
setSelectedTask({
|
||||
...selectedTask,
|
||||
deadline: newDeadline,
|
||||
});
|
||||
}
|
||||
},
|
||||
onError: (error) => {
|
||||
toast({
|
||||
title: "Error updating task",
|
||||
description: error.message,
|
||||
variant: "destructive",
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
[editDeadline, updateTask, toast, selectedTask, setSelectedTask]
|
||||
);
|
||||
|
||||
// Function to handle saving the updated duration
|
||||
const handleSaveDuration = useCallback(
|
||||
(taskId: string) => {
|
||||
@@ -2605,6 +2648,11 @@ function MeasureViewContent({
|
||||
{formatDuration(task.timeEstimate)}
|
||||
</div>
|
||||
)}
|
||||
{task.deadline && (
|
||||
<div className="text-sm text-secondary">
|
||||
{formatDate(task.deadline)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -3063,6 +3111,69 @@ function MeasureViewContent({
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Deadline */}
|
||||
<div>
|
||||
<h3 className="text-sm font-medium text-secondary mb-2">
|
||||
Deadline
|
||||
</h3>
|
||||
{isEditingDeadline ? (
|
||||
<div className="space-y-2">
|
||||
<div className="flex gap-2">
|
||||
<div className="flex-1">
|
||||
<Input
|
||||
type="date"
|
||||
value={editDeadline}
|
||||
onChange={(e) =>
|
||||
setEditDeadline(e.target.value)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex justify-end gap-2">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => setIsEditingDeadline(false)}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
onClick={() => handleSaveDeadline(selectedTask.id)}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
{selectedTask.deadline ? (
|
||||
<span>
|
||||
{formatDate(selectedTask.deadline)}
|
||||
</span>
|
||||
) : (
|
||||
<span className="text-secondary">
|
||||
No deadline
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="p-1 h-auto"
|
||||
onClick={() => {
|
||||
const selectedDeadline = selectedTask.deadline ? format(selectedTask.deadline, 'yyyy-MM-dd') : "";
|
||||
setEditDeadline(selectedDeadline);
|
||||
setIsEditingDeadline(true);
|
||||
}}
|
||||
>
|
||||
Edit
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Evidence section */}
|
||||
<div>
|
||||
<div className="flex items-center justify-between mb-3">
|
||||
@@ -3846,6 +3957,15 @@ function MeasureViewContent({
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid w-full items-center gap-1.5">
|
||||
<Label htmlFor="task-deadline">Deadline (optional)</Label>
|
||||
<Input
|
||||
id="task-deadline"
|
||||
type="date"
|
||||
value={newDeadline}
|
||||
onChange={(e) => setNewDeadline(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<DialogFooter className="mt-4">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<b53893b96884bbc49ad8f2dbdb22e2ea>>
|
||||
* @generated SignedSource<<d258cc7c047ea5b1e81d5ef895e63ac6>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -12,6 +12,7 @@ import { ConcreteRequest } from 'relay-runtime';
|
||||
export type TaskState = "DONE" | "TODO";
|
||||
export type CreateTaskInput = {
|
||||
assignedToId?: string | null | undefined;
|
||||
deadline?: string | null | undefined;
|
||||
description: string;
|
||||
measureId?: string | null | undefined;
|
||||
name: string;
|
||||
@@ -31,6 +32,7 @@ export type MeasureViewCreateTaskMutation$data = {
|
||||
readonly id: string;
|
||||
readonly primaryEmailAddress: string;
|
||||
} | null | undefined;
|
||||
readonly deadline: string | null | undefined;
|
||||
readonly description: string;
|
||||
readonly id: string;
|
||||
readonly name: string;
|
||||
@@ -108,6 +110,13 @@ v4 = {
|
||||
"name": "timeEstimate",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "deadline",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
@@ -213,16 +222,16 @@ return {
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "53b934e0e7a3d4abf8789ad8672687df",
|
||||
"cacheID": "8f9aeb0df92f9535d728ef27a7dee963",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "MeasureViewCreateTaskMutation",
|
||||
"operationKind": "mutation",
|
||||
"text": "mutation MeasureViewCreateTaskMutation(\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"
|
||||
"text": "mutation MeasureViewCreateTaskMutation(\n $input: CreateTaskInput!\n) {\n createTask(input: $input) {\n taskEdge {\n node {\n id\n name\n description\n timeEstimate\n deadline\n state\n assignedTo {\n id\n fullName\n primaryEmailAddress\n }\n }\n }\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "0df98f5aee4233dc4ffedcff8256891a";
|
||||
(node as any).hash = "f323b5caa0912478e715f0c409898eff";
|
||||
|
||||
export default node;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<03d8e2eca1cc7ffaf797c66ef7fa11c1>>
|
||||
* @generated SignedSource<<a6d5ebf3d09595b1da2cd16746fa1163>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -48,6 +48,7 @@ export type MeasureViewQuery$data = {
|
||||
readonly id: string;
|
||||
readonly primaryEmailAddress: string;
|
||||
} | null | undefined;
|
||||
readonly deadline: string | null | undefined;
|
||||
readonly description: string;
|
||||
readonly evidences: {
|
||||
readonly __id: string;
|
||||
@@ -261,6 +262,13 @@ v12 = {
|
||||
"storageKey": null
|
||||
},
|
||||
v13 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "deadline",
|
||||
"storageKey": null
|
||||
},
|
||||
v14 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "People",
|
||||
@@ -286,14 +294,14 @@ v13 = {
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
v14 = [
|
||||
v15 = [
|
||||
{
|
||||
"kind": "Literal",
|
||||
"name": "first",
|
||||
"value": 100
|
||||
}
|
||||
],
|
||||
v15 = [
|
||||
v16 = [
|
||||
{
|
||||
"kind": "Literal",
|
||||
"name": "first",
|
||||
@@ -363,6 +371,7 @@ return {
|
||||
(v5/*: any*/),
|
||||
(v12/*: any*/),
|
||||
(v13/*: any*/),
|
||||
(v14/*: any*/),
|
||||
{
|
||||
"alias": "evidences",
|
||||
"args": null,
|
||||
@@ -422,7 +431,7 @@ return {
|
||||
(v6/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v14/*: any*/),
|
||||
"args": (v15/*: any*/),
|
||||
"concreteType": "EvidenceConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "evidences",
|
||||
@@ -432,7 +441,7 @@ return {
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v14/*: any*/),
|
||||
"args": (v15/*: any*/),
|
||||
"filters": null,
|
||||
"handle": "connection",
|
||||
"key": "MeasureView_evidences",
|
||||
@@ -441,7 +450,7 @@ return {
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v14/*: any*/),
|
||||
"args": (v15/*: any*/),
|
||||
"concreteType": "TaskConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "tasks",
|
||||
@@ -469,9 +478,10 @@ return {
|
||||
(v5/*: any*/),
|
||||
(v12/*: any*/),
|
||||
(v13/*: any*/),
|
||||
(v14/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v15/*: any*/),
|
||||
"args": (v16/*: any*/),
|
||||
"concreteType": "EvidenceConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "evidences",
|
||||
@@ -481,7 +491,7 @@ return {
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v15/*: any*/),
|
||||
"args": (v16/*: any*/),
|
||||
"filters": null,
|
||||
"handle": "connection",
|
||||
"key": "MeasureView_task_evidences",
|
||||
@@ -503,7 +513,7 @@ return {
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v14/*: any*/),
|
||||
"args": (v15/*: any*/),
|
||||
"filters": null,
|
||||
"handle": "connection",
|
||||
"key": "MeasureView_tasks",
|
||||
@@ -520,7 +530,7 @@ return {
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "d3e4d9723d12bce8158b83eb76d05a90",
|
||||
"cacheID": "2693fa3e0141f58235566f539194fcd6",
|
||||
"id": null,
|
||||
"metadata": {
|
||||
"connection": [
|
||||
@@ -552,11 +562,11 @@ return {
|
||||
},
|
||||
"name": "MeasureViewQuery",
|
||||
"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 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"
|
||||
"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 deadline\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 = "288412cccb1f4c14b1852504e5536af1";
|
||||
(node as any).hash = "4e211c36d94ebd914b6de254dfbdf946";
|
||||
|
||||
export default node;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<1595fa9771d6baa14534b181f4a1384a>>
|
||||
* @generated SignedSource<<28c68c446adeac27a47de2b754d48d5d>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -11,6 +11,7 @@
|
||||
import { ConcreteRequest } from 'relay-runtime';
|
||||
export type TaskState = "DONE" | "TODO";
|
||||
export type UpdateTaskInput = {
|
||||
deadline?: string | null | undefined;
|
||||
description?: string | null | undefined;
|
||||
name?: string | null | undefined;
|
||||
state?: TaskState | null | undefined;
|
||||
@@ -23,6 +24,7 @@ export type MeasureViewUpdateTaskStateMutation$variables = {
|
||||
export type MeasureViewUpdateTaskStateMutation$data = {
|
||||
readonly updateTask: {
|
||||
readonly task: {
|
||||
readonly deadline: string | null | undefined;
|
||||
readonly id: string;
|
||||
readonly state: TaskState;
|
||||
readonly timeEstimate: any | null | undefined;
|
||||
@@ -85,6 +87,13 @@ v1 = [
|
||||
"kind": "ScalarField",
|
||||
"name": "timeEstimate",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "deadline",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
@@ -111,16 +120,16 @@ return {
|
||||
"selections": (v1/*: any*/)
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "f545a0b12edb8f231a1a7a7c38b6e905",
|
||||
"cacheID": "a0001fad3af2ba3fc16a1f0af4f19370",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "MeasureViewUpdateTaskStateMutation",
|
||||
"operationKind": "mutation",
|
||||
"text": "mutation MeasureViewUpdateTaskStateMutation(\n $input: UpdateTaskInput!\n) {\n updateTask(input: $input) {\n task {\n id\n state\n timeEstimate\n }\n }\n}\n"
|
||||
"text": "mutation MeasureViewUpdateTaskStateMutation(\n $input: UpdateTaskInput!\n) {\n updateTask(input: $input) {\n task {\n id\n state\n timeEstimate\n deadline\n }\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "e1d67c030523e56d6bcd595c27fcb3dc";
|
||||
(node as any).hash = "b3b0d47e0632b106b6313edbd2de38ce";
|
||||
|
||||
export default node;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Suspense, useEffect, useState } from "react";
|
||||
import {ChangeEvent, Suspense, useEffect, useState} from "react";
|
||||
import {
|
||||
useQueryLoader,
|
||||
graphql,
|
||||
@@ -47,6 +47,7 @@ import {
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
import { ListTaskViewOrganizationQuery } from "./__generated__/ListTaskViewOrganizationQuery.graphql";
|
||||
import {formatDate, parseISO} from "date-fns";
|
||||
|
||||
// Function to format ISO8601 duration to human-readable format
|
||||
const formatDuration = (isoDuration: string | null | undefined): string => {
|
||||
@@ -121,6 +122,7 @@ const createTaskMutation = graphql`
|
||||
description
|
||||
state
|
||||
timeEstimate
|
||||
deadline
|
||||
measure {
|
||||
id
|
||||
name
|
||||
@@ -164,6 +166,7 @@ const listTaskViewQuery = graphql`
|
||||
description
|
||||
state
|
||||
timeEstimate
|
||||
deadline
|
||||
measure {
|
||||
id
|
||||
name
|
||||
@@ -213,6 +216,7 @@ interface Task {
|
||||
description?: string;
|
||||
state: string;
|
||||
timeEstimate?: number | null;
|
||||
deadline?: string | null;
|
||||
assignedTo?: {
|
||||
id: string;
|
||||
fullName: string;
|
||||
@@ -273,6 +277,11 @@ function TaskCard({ task, onClick, onToggleState }: {
|
||||
{formatDuration(task.timeEstimate.toString())}
|
||||
</span>
|
||||
)}
|
||||
{task.deadline && (
|
||||
<span className="text-xs text-gray-500">
|
||||
{formatDate(task.deadline, "dd MMM yyyy")}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
{task.parent && (
|
||||
<div className="flex items-center gap-1 text-sm text-gray-500">
|
||||
@@ -346,6 +355,8 @@ function ListTaskContent({
|
||||
const [selectedMeasure, setSelectedMeasure] = useState<{id: string, name: string} | null>(null);
|
||||
const [timeEstimate, setTimeEstimate] = useState<number | null>(null);
|
||||
const [timeUnit, setTimeUnit] = useState<"minutes" | "hours" | "days" | "weeks">("hours");
|
||||
const [deadlineString, setDeadlineString] = useState<string>('');
|
||||
const [deadline, setDeadline] = useState<Date | null>(null);
|
||||
|
||||
// Create task mutation
|
||||
const [createTask, isCreatingTask] = useMutation(createTaskMutation);
|
||||
@@ -382,6 +393,19 @@ function ListTaskContent({
|
||||
}
|
||||
}, [environment, organization?.id]);
|
||||
|
||||
// Parse deadline string into Date-object
|
||||
const handleDeadlineChange = (event: ChangeEvent<HTMLInputElement>) => {
|
||||
const value = event.target.value;
|
||||
setDeadlineString(value);
|
||||
|
||||
if (value) {
|
||||
const date = parseISO(value);
|
||||
setDeadline(date);
|
||||
} else {
|
||||
setDeadline(null)
|
||||
}
|
||||
};
|
||||
|
||||
// Filter measures based on search query
|
||||
const filteredMeasures = measures.filter(measure =>
|
||||
measure.name.toLowerCase().includes(measureSearchQuery.toLowerCase()) ||
|
||||
@@ -439,6 +463,7 @@ function ListTaskContent({
|
||||
measureId: selectedMeasure?.id || null,
|
||||
assignedToId: assignee?.id,
|
||||
timeEstimate: formattedTimeEstimate,
|
||||
deadline: deadline
|
||||
},
|
||||
connections: [data.node?.tasks?.__id || ""],
|
||||
},
|
||||
@@ -462,6 +487,8 @@ function ListTaskContent({
|
||||
setTimeEstimate(null);
|
||||
setTimeUnit("hours");
|
||||
setMeasureSearchQuery("");
|
||||
setDeadlineString('');
|
||||
setDeadline(null);
|
||||
};
|
||||
|
||||
// Get initials from name
|
||||
@@ -825,6 +852,15 @@ function ListTaskContent({
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Deadline */}
|
||||
<div className="flex justify-between items-center broder-b border-[rgba(2,42,2,0.08)] py-3">
|
||||
<Label className="text-sm font-medium text-gray-500">Deadline</Label>
|
||||
<div className="flex items-center gap-1.5">
|
||||
<Input type="date" value={deadlineString} onChange={handleDeadlineChange}
|
||||
className="text-sm font-medium bg-[rgba(0,39,0,0.05)] px-[10px] py-[6px] rounded-lg"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<84a35602a155b0f1fa8504cf32c10932>>
|
||||
* @generated SignedSource<<a4c4d53df4bc73d2bdc48ef0eb38a500>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -12,6 +12,7 @@ import { ConcreteRequest } from 'relay-runtime';
|
||||
export type TaskState = "DONE" | "TODO";
|
||||
export type CreateTaskInput = {
|
||||
assignedToId?: string | null | undefined;
|
||||
deadline?: string | null | undefined;
|
||||
description: string;
|
||||
measureId?: string | null | undefined;
|
||||
name: string;
|
||||
@@ -30,6 +31,7 @@ export type ListTaskViewCreateTaskMutation$data = {
|
||||
readonly fullName: string;
|
||||
readonly id: string;
|
||||
} | null | undefined;
|
||||
readonly deadline: string | null | undefined;
|
||||
readonly description: string;
|
||||
readonly id: string;
|
||||
readonly measure: {
|
||||
@@ -119,6 +121,13 @@ v5 = {
|
||||
"name": "timeEstimate",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "deadline",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
@@ -223,16 +232,16 @@ return {
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "7b9680f637411402ff51239a43b44a14",
|
||||
"cacheID": "6fe245ddb913332138beda8377ebd88c",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "ListTaskViewCreateTaskMutation",
|
||||
"operationKind": "mutation",
|
||||
"text": "mutation ListTaskViewCreateTaskMutation(\n $input: CreateTaskInput!\n) {\n createTask(input: $input) {\n taskEdge {\n node {\n id\n name\n description\n state\n timeEstimate\n measure {\n id\n name\n }\n assignedTo {\n id\n fullName\n }\n }\n }\n }\n}\n"
|
||||
"text": "mutation ListTaskViewCreateTaskMutation(\n $input: CreateTaskInput!\n) {\n createTask(input: $input) {\n taskEdge {\n node {\n id\n name\n description\n state\n timeEstimate\n deadline\n measure {\n id\n name\n }\n assignedTo {\n id\n fullName\n }\n }\n }\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "43ccaf49d31ec84dcf3b6b3f2e3a851c";
|
||||
(node as any).hash = "934ee4a5b5bfd4c9e9c4acab49d11304";
|
||||
|
||||
export default node;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<7732676a00f7ed0f6817555b68540aca>>
|
||||
* @generated SignedSource<<14a914bdd269eb18124d002d2c61a5b9>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -25,6 +25,7 @@ export type ListTaskViewQuery$data = {
|
||||
readonly fullName: string;
|
||||
readonly id: string;
|
||||
} | null | undefined;
|
||||
readonly deadline: string | null | undefined;
|
||||
readonly description: string;
|
||||
readonly id: string;
|
||||
readonly measure: {
|
||||
@@ -120,6 +121,13 @@ v5 = [
|
||||
"name": "timeEstimate",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "deadline",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
@@ -301,7 +309,7 @@ return {
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "52b577b08c305249855293949d6e2339",
|
||||
"cacheID": "7519a481d7930f14c53c8c1a72d66f58",
|
||||
"id": null,
|
||||
"metadata": {
|
||||
"connection": [
|
||||
@@ -318,11 +326,11 @@ return {
|
||||
},
|
||||
"name": "ListTaskViewQuery",
|
||||
"operationKind": "query",
|
||||
"text": "query ListTaskViewQuery(\n $organizationId: ID!\n) {\n node(id: $organizationId) {\n __typename\n id\n ... on Organization {\n name\n tasks(first: 100) {\n edges {\n node {\n id\n name\n description\n state\n timeEstimate\n measure {\n id\n name\n }\n assignedTo {\n id\n fullName\n }\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n }\n}\n"
|
||||
"text": "query ListTaskViewQuery(\n $organizationId: ID!\n) {\n node(id: $organizationId) {\n __typename\n id\n ... on Organization {\n name\n tasks(first: 100) {\n edges {\n node {\n id\n name\n description\n state\n timeEstimate\n deadline\n measure {\n id\n name\n }\n assignedTo {\n id\n fullName\n }\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "5ca091444c547744068f2b2a83cb31df";
|
||||
(node as any).hash = "52b99d58a5b95dadd4e66bfad588d924";
|
||||
|
||||
export default node;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<7098e326d01cc6831f293726096a7275>>
|
||||
* @generated SignedSource<<c0e5d40aeab42e5f50cf93b75ddb7328>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -11,6 +11,7 @@
|
||||
import { ConcreteRequest } from 'relay-runtime';
|
||||
export type TaskState = "DONE" | "TODO";
|
||||
export type UpdateTaskInput = {
|
||||
deadline?: string | null | undefined;
|
||||
description?: string | null | undefined;
|
||||
name?: string | null | undefined;
|
||||
state?: TaskState | null | undefined;
|
||||
|
||||
1
pkg/coredata/migrations/20250603T083618Z.sql
Normal file
1
pkg/coredata/migrations/20250603T083618Z.sql
Normal file
@@ -0,0 +1 @@
|
||||
ALTER TABLE tasks ADD COLUMN deadline TIMESTAMP WITH TIME ZONE;
|
||||
@@ -38,6 +38,7 @@ type (
|
||||
ReferenceID string `db:"reference_id"`
|
||||
TimeEstimate *time.Duration `db:"time_estimate"`
|
||||
AssignedToID *gid.GID `db:"assigned_to"`
|
||||
Deadline *time.Time `db:"deadline"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
}
|
||||
@@ -71,6 +72,7 @@ SELECT
|
||||
reference_id,
|
||||
time_estimate,
|
||||
assigned_to,
|
||||
deadline,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
@@ -119,6 +121,7 @@ INSERT INTO
|
||||
state,
|
||||
time_estimate,
|
||||
assigned_to,
|
||||
deadline,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
@@ -133,6 +136,7 @@ VALUES (
|
||||
@state,
|
||||
@time_estimate,
|
||||
@assigned_to,
|
||||
@deadline,
|
||||
@created_at,
|
||||
@updated_at
|
||||
);
|
||||
@@ -149,6 +153,7 @@ VALUES (
|
||||
"state": c.State,
|
||||
"time_estimate": c.TimeEstimate,
|
||||
"assigned_to": c.AssignedToID,
|
||||
"deadline": c.Deadline,
|
||||
"created_at": c.CreatedAt,
|
||||
"updated_at": c.UpdatedAt,
|
||||
}
|
||||
@@ -174,6 +179,7 @@ INSERT INTO
|
||||
state,
|
||||
time_estimate,
|
||||
assigned_to,
|
||||
deadline,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
@@ -188,6 +194,7 @@ VALUES (
|
||||
@state,
|
||||
@time_estimate,
|
||||
@assigned_to,
|
||||
@deadline,
|
||||
@created_at,
|
||||
@updated_at
|
||||
)
|
||||
@@ -205,6 +212,7 @@ RETURNING
|
||||
state,
|
||||
time_estimate,
|
||||
assigned_to,
|
||||
deadline,
|
||||
created_at,
|
||||
updated_at
|
||||
`
|
||||
@@ -220,6 +228,7 @@ RETURNING
|
||||
"state": c.State,
|
||||
"time_estimate": c.TimeEstimate,
|
||||
"assigned_to": c.AssignedToID,
|
||||
"deadline": c.Deadline,
|
||||
"created_at": c.CreatedAt,
|
||||
"updated_at": c.UpdatedAt,
|
||||
}
|
||||
@@ -256,6 +265,7 @@ func (c *Tasks) LoadByOrganizationID(
|
||||
reference_id,
|
||||
time_estimate,
|
||||
assigned_to,
|
||||
deadline,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
@@ -304,6 +314,7 @@ SELECT
|
||||
reference_id,
|
||||
time_estimate,
|
||||
assigned_to,
|
||||
deadline,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
@@ -347,7 +358,8 @@ SET
|
||||
state = @state,
|
||||
time_estimate = @time_estimate,
|
||||
updated_at = @updated_at,
|
||||
assigned_to = @assigned_to
|
||||
assigned_to = @assigned_to,
|
||||
deadline = @deadline
|
||||
WHERE %s
|
||||
AND id = @task_id
|
||||
`
|
||||
@@ -361,6 +373,7 @@ WHERE %s
|
||||
"time_estimate": c.TimeEstimate,
|
||||
"updated_at": c.UpdatedAt,
|
||||
"assigned_to": c.AssignedToID,
|
||||
"deadline": c.Deadline,
|
||||
}
|
||||
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
@@ -38,6 +38,7 @@ type (
|
||||
Description string
|
||||
TimeEstimate *time.Duration
|
||||
AssignedToID *gid.GID
|
||||
Deadline *time.Time
|
||||
}
|
||||
|
||||
UpdateTaskRequest struct {
|
||||
@@ -46,6 +47,7 @@ type (
|
||||
Description *string
|
||||
State *coredata.TaskState
|
||||
TimeEstimate *time.Duration
|
||||
Deadline *time.Time
|
||||
}
|
||||
)
|
||||
|
||||
@@ -69,6 +71,7 @@ func (s TaskService) Create(
|
||||
Description: req.Description,
|
||||
TimeEstimate: req.TimeEstimate,
|
||||
AssignedToID: req.AssignedToID,
|
||||
Deadline: req.Deadline,
|
||||
State: coredata.TaskStateTodo,
|
||||
ReferenceID: "custom-task-" + referenceID.String(),
|
||||
CreatedAt: now,
|
||||
@@ -203,6 +206,10 @@ func (s TaskService) Update(
|
||||
task.TimeEstimate = req.TimeEstimate
|
||||
}
|
||||
|
||||
if req.Deadline != nil {
|
||||
task.Deadline = req.Deadline
|
||||
}
|
||||
|
||||
task.UpdatedAt = time.Now()
|
||||
|
||||
if err := task.Update(ctx, conn, s.svc.scope); err != nil {
|
||||
|
||||
@@ -758,6 +758,7 @@ type Task implements Node {
|
||||
description: String!
|
||||
state: TaskState!
|
||||
timeEstimate: Duration
|
||||
deadline: Datetime
|
||||
assignedTo: People @goField(forceResolver: true)
|
||||
|
||||
organization: Organization! @goField(forceResolver: true)
|
||||
@@ -1329,6 +1330,7 @@ input CreateTaskInput {
|
||||
description: String!
|
||||
timeEstimate: Duration
|
||||
assignedToId: ID
|
||||
deadline: Datetime
|
||||
}
|
||||
|
||||
input UpdateTaskInput {
|
||||
@@ -1337,6 +1339,7 @@ input UpdateTaskInput {
|
||||
description: String
|
||||
state: TaskState
|
||||
timeEstimate: Duration
|
||||
deadline: Datetime
|
||||
}
|
||||
|
||||
input DeleteTaskInput {
|
||||
|
||||
@@ -680,6 +680,7 @@ type ComplexityRoot struct {
|
||||
Task struct {
|
||||
AssignedTo func(childComplexity int) int
|
||||
CreatedAt func(childComplexity int) int
|
||||
Deadline func(childComplexity int) int
|
||||
Description func(childComplexity int) int
|
||||
Evidences func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.EvidenceOrderBy) int
|
||||
ID func(childComplexity int) int
|
||||
@@ -3834,6 +3835,13 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
|
||||
|
||||
return e.complexity.Task.CreatedAt(childComplexity), true
|
||||
|
||||
case "Task.deadline":
|
||||
if e.complexity.Task.Deadline == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.Task.Deadline(childComplexity), true
|
||||
|
||||
case "Task.description":
|
||||
if e.complexity.Task.Description == nil {
|
||||
break
|
||||
@@ -5481,6 +5489,7 @@ type Task implements Node {
|
||||
description: String!
|
||||
state: TaskState!
|
||||
timeEstimate: Duration
|
||||
deadline: Datetime
|
||||
assignedTo: People @goField(forceResolver: true)
|
||||
|
||||
organization: Organization! @goField(forceResolver: true)
|
||||
@@ -6052,6 +6061,7 @@ input CreateTaskInput {
|
||||
description: String!
|
||||
timeEstimate: Duration
|
||||
assignedToId: ID
|
||||
deadline: Datetime
|
||||
}
|
||||
|
||||
input UpdateTaskInput {
|
||||
@@ -6060,6 +6070,7 @@ input UpdateTaskInput {
|
||||
description: String
|
||||
state: TaskState
|
||||
timeEstimate: Duration
|
||||
deadline: Datetime
|
||||
}
|
||||
|
||||
input DeleteTaskInput {
|
||||
@@ -12379,6 +12390,8 @@ func (ec *executionContext) fieldContext_AssignTaskPayload_task(_ context.Contex
|
||||
return ec.fieldContext_Task_state(ctx, field)
|
||||
case "timeEstimate":
|
||||
return ec.fieldContext_Task_timeEstimate(ctx, field)
|
||||
case "deadline":
|
||||
return ec.fieldContext_Task_deadline(ctx, field)
|
||||
case "assignedTo":
|
||||
return ec.fieldContext_Task_assignedTo(ctx, field)
|
||||
case "organization":
|
||||
@@ -18910,6 +18923,8 @@ func (ec *executionContext) fieldContext_Evidence_task(_ context.Context, field
|
||||
return ec.fieldContext_Task_state(ctx, field)
|
||||
case "timeEstimate":
|
||||
return ec.fieldContext_Task_timeEstimate(ctx, field)
|
||||
case "deadline":
|
||||
return ec.fieldContext_Task_deadline(ctx, field)
|
||||
case "assignedTo":
|
||||
return ec.fieldContext_Task_assignedTo(ctx, field)
|
||||
case "organization":
|
||||
@@ -28879,6 +28894,47 @@ func (ec *executionContext) fieldContext_Task_timeEstimate(_ context.Context, fi
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Task_deadline(ctx context.Context, field graphql.CollectedField, obj *types.Task) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_Task_deadline(ctx, field)
|
||||
if err != nil {
|
||||
return graphql.Null
|
||||
}
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.Deadline, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(*time.Time)
|
||||
fc.Result = res
|
||||
return ec.marshalODatetime2ᚖtimeᚐTime(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_Task_deadline(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
fc = &graphql.FieldContext{
|
||||
Object: "Task",
|
||||
Field: field,
|
||||
IsMethod: false,
|
||||
IsResolver: false,
|
||||
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||
return nil, errors.New("field of type Datetime does not have child fields")
|
||||
},
|
||||
}
|
||||
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 {
|
||||
@@ -29431,6 +29487,8 @@ 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 "deadline":
|
||||
return ec.fieldContext_Task_deadline(ctx, field)
|
||||
case "assignedTo":
|
||||
return ec.fieldContext_Task_assignedTo(ctx, field)
|
||||
case "organization":
|
||||
@@ -29499,6 +29557,8 @@ func (ec *executionContext) fieldContext_UnassignTaskPayload_task(_ context.Cont
|
||||
return ec.fieldContext_Task_state(ctx, field)
|
||||
case "timeEstimate":
|
||||
return ec.fieldContext_Task_timeEstimate(ctx, field)
|
||||
case "deadline":
|
||||
return ec.fieldContext_Task_deadline(ctx, field)
|
||||
case "assignedTo":
|
||||
return ec.fieldContext_Task_assignedTo(ctx, field)
|
||||
case "organization":
|
||||
@@ -30193,6 +30253,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 "deadline":
|
||||
return ec.fieldContext_Task_deadline(ctx, field)
|
||||
case "assignedTo":
|
||||
return ec.fieldContext_Task_assignedTo(ctx, field)
|
||||
case "organization":
|
||||
@@ -36789,7 +36851,7 @@ func (ec *executionContext) unmarshalInputCreateTaskInput(ctx context.Context, o
|
||||
asMap[k] = v
|
||||
}
|
||||
|
||||
fieldsInOrder := [...]string{"organizationId", "measureId", "name", "description", "timeEstimate", "assignedToId"}
|
||||
fieldsInOrder := [...]string{"organizationId", "measureId", "name", "description", "timeEstimate", "assignedToId", "deadline"}
|
||||
for _, k := range fieldsInOrder {
|
||||
v, ok := asMap[k]
|
||||
if !ok {
|
||||
@@ -36838,6 +36900,13 @@ func (ec *executionContext) unmarshalInputCreateTaskInput(ctx context.Context, o
|
||||
return it, err
|
||||
}
|
||||
it.AssignedToID = data
|
||||
case "deadline":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("deadline"))
|
||||
data, err := ec.unmarshalODatetime2ᚖtimeᚐTime(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
it.Deadline = data
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38947,7 +39016,7 @@ func (ec *executionContext) unmarshalInputUpdateTaskInput(ctx context.Context, o
|
||||
asMap[k] = v
|
||||
}
|
||||
|
||||
fieldsInOrder := [...]string{"taskId", "name", "description", "state", "timeEstimate"}
|
||||
fieldsInOrder := [...]string{"taskId", "name", "description", "state", "timeEstimate", "deadline"}
|
||||
for _, k := range fieldsInOrder {
|
||||
v, ok := asMap[k]
|
||||
if !ok {
|
||||
@@ -38989,6 +39058,13 @@ func (ec *executionContext) unmarshalInputUpdateTaskInput(ctx context.Context, o
|
||||
return it, err
|
||||
}
|
||||
it.TimeEstimate = data
|
||||
case "deadline":
|
||||
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("deadline"))
|
||||
data, err := ec.unmarshalODatetime2ᚖtimeᚐTime(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
it.Deadline = data
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46022,6 +46098,8 @@ func (ec *executionContext) _Task(ctx context.Context, sel ast.SelectionSet, obj
|
||||
}
|
||||
case "timeEstimate":
|
||||
out.Values[i] = ec._Task_timeEstimate(ctx, field, obj)
|
||||
case "deadline":
|
||||
out.Values[i] = ec._Task_deadline(ctx, field, obj)
|
||||
case "assignedTo":
|
||||
field := field
|
||||
|
||||
|
||||
@@ -52,5 +52,6 @@ func NewTask(t *coredata.Task) *Task {
|
||||
TimeEstimate: t.TimeEstimate,
|
||||
CreatedAt: t.CreatedAt,
|
||||
UpdatedAt: t.UpdatedAt,
|
||||
Deadline: t.Deadline,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -313,6 +313,7 @@ type CreateTaskInput struct {
|
||||
Description string `json:"description"`
|
||||
TimeEstimate *time.Duration `json:"timeEstimate,omitempty"`
|
||||
AssignedToID *gid.GID `json:"assignedToId,omitempty"`
|
||||
Deadline *time.Time `json:"deadline,omitempty"`
|
||||
}
|
||||
|
||||
type CreateTaskPayload struct {
|
||||
@@ -934,6 +935,7 @@ type Task struct {
|
||||
Description string `json:"description"`
|
||||
State coredata.TaskState `json:"state"`
|
||||
TimeEstimate *time.Duration `json:"timeEstimate,omitempty"`
|
||||
Deadline *time.Time `json:"deadline,omitempty"`
|
||||
AssignedTo *People `json:"assignedTo,omitempty"`
|
||||
Organization *Organization `json:"organization"`
|
||||
Measure *Measure `json:"measure,omitempty"`
|
||||
@@ -1083,6 +1085,7 @@ type UpdateTaskInput struct {
|
||||
Description *string `json:"description,omitempty"`
|
||||
State *coredata.TaskState `json:"state,omitempty"`
|
||||
TimeEstimate *time.Duration `json:"timeEstimate,omitempty"`
|
||||
Deadline *time.Time `json:"deadline,omitempty"`
|
||||
}
|
||||
|
||||
type UpdateTaskPayload struct {
|
||||
|
||||
@@ -1114,6 +1114,7 @@ func (r *mutationResolver) CreateTask(ctx context.Context, input types.CreateTas
|
||||
Name: input.Name,
|
||||
Description: input.Description,
|
||||
TimeEstimate: input.TimeEstimate,
|
||||
Deadline: input.Deadline,
|
||||
})
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot create task: %w", err))
|
||||
@@ -1134,6 +1135,7 @@ func (r *mutationResolver) UpdateTask(ctx context.Context, input types.UpdateTas
|
||||
Description: input.Description,
|
||||
State: input.State,
|
||||
TimeEstimate: input.TimeEstimate,
|
||||
Deadline: input.Deadline,
|
||||
})
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot update task: %w", err))
|
||||
|
||||
Reference in New Issue
Block a user