@@ -7,7 +7,7 @@ import {
|
|||||||
useQueryLoader,
|
useQueryLoader,
|
||||||
useMutation,
|
useMutation,
|
||||||
} from "react-relay";
|
} from "react-relay";
|
||||||
import { CheckCircle2, Plus } from "lucide-react";
|
import { CheckCircle2, Plus, Trash2 } from "lucide-react";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { useToast } from "@/hooks/use-toast";
|
import { useToast } from "@/hooks/use-toast";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
@@ -26,6 +26,8 @@ import { Helmet } from "react-helmet-async";
|
|||||||
import type { ControlOverviewPageQuery as ControlOverviewPageQueryType } from "./__generated__/ControlOverviewPageQuery.graphql";
|
import type { ControlOverviewPageQuery as ControlOverviewPageQueryType } from "./__generated__/ControlOverviewPageQuery.graphql";
|
||||||
import type { ControlOverviewPageUpdateTaskStateMutation as ControlOverviewPageUpdateTaskStateMutationType } from "./__generated__/ControlOverviewPageUpdateTaskStateMutation.graphql";
|
import type { ControlOverviewPageUpdateTaskStateMutation as ControlOverviewPageUpdateTaskStateMutationType } from "./__generated__/ControlOverviewPageUpdateTaskStateMutation.graphql";
|
||||||
import type { ControlOverviewPageCreateTaskMutation as ControlOverviewPageCreateTaskMutationType } from "./__generated__/ControlOverviewPageCreateTaskMutation.graphql";
|
import type { ControlOverviewPageCreateTaskMutation as ControlOverviewPageCreateTaskMutationType } from "./__generated__/ControlOverviewPageCreateTaskMutation.graphql";
|
||||||
|
// The import below will be generated after the first run
|
||||||
|
// import type { ControlOverviewPageDeleteTaskMutation as ControlOverviewPageDeleteTaskMutationType } from "./__generated__/ControlOverviewPageDeleteTaskMutation.graphql";
|
||||||
|
|
||||||
const controlOverviewPageQuery = graphql`
|
const controlOverviewPageQuery = graphql`
|
||||||
query ControlOverviewPageQuery($controlId: ID!) {
|
query ControlOverviewPageQuery($controlId: ID!) {
|
||||||
@@ -83,6 +85,17 @@ const createTaskMutation = graphql`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const deleteTaskMutation = graphql`
|
||||||
|
mutation ControlOverviewPageDeleteTaskMutation(
|
||||||
|
$input: DeleteTaskInput!
|
||||||
|
$connections: [ID!]!
|
||||||
|
) {
|
||||||
|
deleteTask(input: $input) {
|
||||||
|
deletedTaskId @deleteEdge(connections: $connections)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
function ControlOverviewPageContent({
|
function ControlOverviewPageContent({
|
||||||
queryRef,
|
queryRef,
|
||||||
}: {
|
}: {
|
||||||
@@ -99,6 +112,8 @@ function ControlOverviewPageContent({
|
|||||||
);
|
);
|
||||||
const [createTask] =
|
const [createTask] =
|
||||||
useMutation<ControlOverviewPageCreateTaskMutationType>(createTaskMutation);
|
useMutation<ControlOverviewPageCreateTaskMutationType>(createTaskMutation);
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
const [deleteTask] = useMutation<any>(deleteTaskMutation);
|
||||||
const control = data.control;
|
const control = data.control;
|
||||||
const tasks = control?.tasks?.edges.map((edge) => edge?.node) ?? [];
|
const tasks = control?.tasks?.edges.map((edge) => edge?.node) ?? [];
|
||||||
|
|
||||||
@@ -107,6 +122,13 @@ function ControlOverviewPageContent({
|
|||||||
const [newTaskName, setNewTaskName] = useState("");
|
const [newTaskName, setNewTaskName] = useState("");
|
||||||
const [newTaskDescription, setNewTaskDescription] = useState("");
|
const [newTaskDescription, setNewTaskDescription] = useState("");
|
||||||
|
|
||||||
|
// State for the delete task dialog
|
||||||
|
const [isDeleteTaskOpen, setIsDeleteTaskOpen] = useState(false);
|
||||||
|
const [taskToDelete, setTaskToDelete] = useState<{
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
} | null>(null);
|
||||||
|
|
||||||
const handleTaskClick = (taskId: string, currentState: string) => {
|
const handleTaskClick = (taskId: string, currentState: string) => {
|
||||||
const newState = currentState === "DONE" ? "TODO" : "DONE";
|
const newState = currentState === "DONE" ? "TODO" : "DONE";
|
||||||
|
|
||||||
@@ -192,6 +214,39 @@ function ControlOverviewPageContent({
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleDeleteTask = (taskId: string, taskName: string) => {
|
||||||
|
setTaskToDelete({ id: taskId, name: taskName });
|
||||||
|
setIsDeleteTaskOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const confirmDeleteTask = () => {
|
||||||
|
if (!taskToDelete) return;
|
||||||
|
|
||||||
|
deleteTask({
|
||||||
|
variables: {
|
||||||
|
connections: [`${data.control?.tasks?.__id}`],
|
||||||
|
input: {
|
||||||
|
taskId: taskToDelete.id,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
onCompleted: () => {
|
||||||
|
toast({
|
||||||
|
title: "Task deleted",
|
||||||
|
description: "Task has been deleted successfully.",
|
||||||
|
});
|
||||||
|
setIsDeleteTaskOpen(false);
|
||||||
|
setTaskToDelete(null);
|
||||||
|
},
|
||||||
|
onError: (error) => {
|
||||||
|
toast({
|
||||||
|
title: "Error deleting task",
|
||||||
|
description: error.message,
|
||||||
|
variant: "destructive",
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-white p-6 space-y-6">
|
<div className="min-h-screen bg-white p-6 space-y-6">
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
@@ -339,16 +394,16 @@ function ControlOverviewPageContent({
|
|||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-2 opacity-0 group-hover:opacity-100 transition-opacity">
|
<div className="flex items-center gap-2 opacity-0 group-hover:opacity-100 transition-opacity">
|
||||||
<div className="text-gray-400 text-sm">06.00 - 07.30</div>
|
<div className="text-gray-400 text-sm">06.00 - 07.30</div>
|
||||||
<button className="text-gray-400 hover:text-gray-600">
|
<button
|
||||||
<svg className="w-6 h-6" fill="none" viewBox="0 0 24 24">
|
className="text-gray-400 hover:text-red-600"
|
||||||
<path
|
onClick={(e) => {
|
||||||
stroke="currentColor"
|
e.stopPropagation();
|
||||||
strokeLinecap="round"
|
if (task?.id && task?.name) {
|
||||||
strokeLinejoin="round"
|
handleDeleteTask(task.id, task.name);
|
||||||
strokeWidth="2"
|
}
|
||||||
d="M12 12h.01M12 6h.01M12 18h.01"
|
}}
|
||||||
/>
|
>
|
||||||
</svg>
|
<Trash2 className="w-4 h-4" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -362,6 +417,30 @@ function ControlOverviewPageContent({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Delete Task Confirmation Dialog */}
|
||||||
|
<Dialog open={isDeleteTaskOpen} onOpenChange={setIsDeleteTaskOpen}>
|
||||||
|
<DialogContent>
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>Delete Task</DialogTitle>
|
||||||
|
<DialogDescription>
|
||||||
|
Are you sure you want to delete the task "
|
||||||
|
{taskToDelete?.name}"? This action cannot be undone.
|
||||||
|
</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
<DialogFooter>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
onClick={() => setIsDeleteTaskOpen(false)}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button variant="destructive" onClick={confirmDeleteTask}>
|
||||||
|
Delete
|
||||||
|
</Button>
|
||||||
|
</DialogFooter>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
132
apps/console/src/pages/__generated__/ControlOverviewPageDeleteTaskMutation.graphql.ts
generated
Normal file
132
apps/console/src/pages/__generated__/ControlOverviewPageDeleteTaskMutation.graphql.ts
generated
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
/**
|
||||||
|
* @generated SignedSource<<cd5744c9739535825e9922b9cb95f034>>
|
||||||
|
* @lightSyntaxTransform
|
||||||
|
* @nogrep
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
// @ts-nocheck
|
||||||
|
|
||||||
|
import { ConcreteRequest } from 'relay-runtime';
|
||||||
|
export type DeleteTaskInput = {
|
||||||
|
taskId: string;
|
||||||
|
};
|
||||||
|
export type ControlOverviewPageDeleteTaskMutation$variables = {
|
||||||
|
connections: ReadonlyArray<string>;
|
||||||
|
input: DeleteTaskInput;
|
||||||
|
};
|
||||||
|
export type ControlOverviewPageDeleteTaskMutation$data = {
|
||||||
|
readonly deleteTask: {
|
||||||
|
readonly deletedTaskId: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
export type ControlOverviewPageDeleteTaskMutation = {
|
||||||
|
response: ControlOverviewPageDeleteTaskMutation$data;
|
||||||
|
variables: ControlOverviewPageDeleteTaskMutation$variables;
|
||||||
|
};
|
||||||
|
|
||||||
|
const node: ConcreteRequest = (function(){
|
||||||
|
var v0 = {
|
||||||
|
"defaultValue": null,
|
||||||
|
"kind": "LocalArgument",
|
||||||
|
"name": "connections"
|
||||||
|
},
|
||||||
|
v1 = {
|
||||||
|
"defaultValue": null,
|
||||||
|
"kind": "LocalArgument",
|
||||||
|
"name": "input"
|
||||||
|
},
|
||||||
|
v2 = [
|
||||||
|
{
|
||||||
|
"kind": "Variable",
|
||||||
|
"name": "input",
|
||||||
|
"variableName": "input"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
v3 = {
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "deletedTaskId",
|
||||||
|
"storageKey": null
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
"fragment": {
|
||||||
|
"argumentDefinitions": [
|
||||||
|
(v0/*: any*/),
|
||||||
|
(v1/*: any*/)
|
||||||
|
],
|
||||||
|
"kind": "Fragment",
|
||||||
|
"metadata": null,
|
||||||
|
"name": "ControlOverviewPageDeleteTaskMutation",
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": (v2/*: any*/),
|
||||||
|
"concreteType": "DeleteTaskPayload",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "deleteTask",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
(v3/*: any*/)
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "Mutation",
|
||||||
|
"abstractKey": null
|
||||||
|
},
|
||||||
|
"kind": "Request",
|
||||||
|
"operation": {
|
||||||
|
"argumentDefinitions": [
|
||||||
|
(v1/*: any*/),
|
||||||
|
(v0/*: any*/)
|
||||||
|
],
|
||||||
|
"kind": "Operation",
|
||||||
|
"name": "ControlOverviewPageDeleteTaskMutation",
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": (v2/*: any*/),
|
||||||
|
"concreteType": "DeleteTaskPayload",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "deleteTask",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
(v3/*: any*/),
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"filters": null,
|
||||||
|
"handle": "deleteEdge",
|
||||||
|
"key": "",
|
||||||
|
"kind": "ScalarHandle",
|
||||||
|
"name": "deletedTaskId",
|
||||||
|
"handleArgs": [
|
||||||
|
{
|
||||||
|
"kind": "Variable",
|
||||||
|
"name": "connections",
|
||||||
|
"variableName": "connections"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"params": {
|
||||||
|
"cacheID": "06db9599a3e83354c0e865d08cdb29dd",
|
||||||
|
"id": null,
|
||||||
|
"metadata": {},
|
||||||
|
"name": "ControlOverviewPageDeleteTaskMutation",
|
||||||
|
"operationKind": "mutation",
|
||||||
|
"text": "mutation ControlOverviewPageDeleteTaskMutation(\n $input: DeleteTaskInput!\n) {\n deleteTask(input: $input) {\n deletedTaskId\n }\n}\n"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
(node as any).hash = "885a98007e48ab3175d0480c5a750e19";
|
||||||
|
|
||||||
|
export default node;
|
||||||
@@ -393,6 +393,7 @@ type Mutation {
|
|||||||
): DeleteOrganizationPayload!
|
): DeleteOrganizationPayload!
|
||||||
updateTaskState(input: UpdateTaskStateInput!): UpdateTaskStatePayload!
|
updateTaskState(input: UpdateTaskStateInput!): UpdateTaskStatePayload!
|
||||||
createTask(input: CreateTaskInput!): CreateTaskPayload!
|
createTask(input: CreateTaskInput!): CreateTaskPayload!
|
||||||
|
deleteTask(input: DeleteTaskInput!): DeleteTaskPayload!
|
||||||
}
|
}
|
||||||
|
|
||||||
input CreateVendorInput {
|
input CreateVendorInput {
|
||||||
@@ -531,3 +532,11 @@ input CreateTaskInput {
|
|||||||
type CreateTaskPayload {
|
type CreateTaskPayload {
|
||||||
taskEdge: TaskEdge!
|
taskEdge: TaskEdge!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input DeleteTaskInput {
|
||||||
|
taskId: ID!
|
||||||
|
}
|
||||||
|
|
||||||
|
type DeleteTaskPayload {
|
||||||
|
deletedTaskId: ID!
|
||||||
|
}
|
||||||
|
|||||||
@@ -121,6 +121,10 @@ type ComplexityRoot struct {
|
|||||||
DeletedPeopleID func(childComplexity int) int
|
DeletedPeopleID func(childComplexity int) int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DeleteTaskPayload struct {
|
||||||
|
DeletedTaskID func(childComplexity int) int
|
||||||
|
}
|
||||||
|
|
||||||
DeleteVendorPayload struct {
|
DeleteVendorPayload struct {
|
||||||
DeletedVendorID func(childComplexity int) int
|
DeletedVendorID func(childComplexity int) int
|
||||||
}
|
}
|
||||||
@@ -191,6 +195,7 @@ type ComplexityRoot struct {
|
|||||||
CreateVendor func(childComplexity int, input types.CreateVendorInput) int
|
CreateVendor func(childComplexity int, input types.CreateVendorInput) int
|
||||||
DeleteOrganization func(childComplexity int, input types.DeleteOrganizationInput) int
|
DeleteOrganization func(childComplexity int, input types.DeleteOrganizationInput) int
|
||||||
DeletePeople func(childComplexity int, input types.DeletePeopleInput) int
|
DeletePeople func(childComplexity int, input types.DeletePeopleInput) int
|
||||||
|
DeleteTask func(childComplexity int, input types.DeleteTaskInput) int
|
||||||
DeleteVendor func(childComplexity int, input types.DeleteVendorInput) int
|
DeleteVendor func(childComplexity int, input types.DeleteVendorInput) int
|
||||||
UpdatePeople func(childComplexity int, input types.UpdatePeopleInput) int
|
UpdatePeople func(childComplexity int, input types.UpdatePeopleInput) int
|
||||||
UpdateTaskState func(childComplexity int, input types.UpdateTaskStateInput) int
|
UpdateTaskState func(childComplexity int, input types.UpdateTaskStateInput) int
|
||||||
@@ -357,6 +362,7 @@ type MutationResolver interface {
|
|||||||
DeleteOrganization(ctx context.Context, input types.DeleteOrganizationInput) (*types.DeleteOrganizationPayload, error)
|
DeleteOrganization(ctx context.Context, input types.DeleteOrganizationInput) (*types.DeleteOrganizationPayload, error)
|
||||||
UpdateTaskState(ctx context.Context, input types.UpdateTaskStateInput) (*types.UpdateTaskStatePayload, error)
|
UpdateTaskState(ctx context.Context, input types.UpdateTaskStateInput) (*types.UpdateTaskStatePayload, error)
|
||||||
CreateTask(ctx context.Context, input types.CreateTaskInput) (*types.CreateTaskPayload, error)
|
CreateTask(ctx context.Context, input types.CreateTaskInput) (*types.CreateTaskPayload, error)
|
||||||
|
DeleteTask(ctx context.Context, input types.DeleteTaskInput) (*types.DeleteTaskPayload, error)
|
||||||
}
|
}
|
||||||
type OrganizationResolver interface {
|
type OrganizationResolver interface {
|
||||||
Frameworks(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.FrameworkConnection, error)
|
Frameworks(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.FrameworkConnection, error)
|
||||||
@@ -607,6 +613,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
|||||||
|
|
||||||
return e.complexity.DeletePeoplePayload.DeletedPeopleID(childComplexity), true
|
return e.complexity.DeletePeoplePayload.DeletedPeopleID(childComplexity), true
|
||||||
|
|
||||||
|
case "DeleteTaskPayload.deletedTaskId":
|
||||||
|
if e.complexity.DeleteTaskPayload.DeletedTaskID == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return e.complexity.DeleteTaskPayload.DeletedTaskID(childComplexity), true
|
||||||
|
|
||||||
case "DeleteVendorPayload.deletedVendorId":
|
case "DeleteVendorPayload.deletedVendorId":
|
||||||
if e.complexity.DeleteVendorPayload.DeletedVendorID == nil {
|
if e.complexity.DeleteVendorPayload.DeletedVendorID == nil {
|
||||||
break
|
break
|
||||||
@@ -920,6 +933,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
|||||||
|
|
||||||
return e.complexity.Mutation.DeletePeople(childComplexity, args["input"].(types.DeletePeopleInput)), true
|
return e.complexity.Mutation.DeletePeople(childComplexity, args["input"].(types.DeletePeopleInput)), true
|
||||||
|
|
||||||
|
case "Mutation.deleteTask":
|
||||||
|
if e.complexity.Mutation.DeleteTask == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
args, err := ec.field_Mutation_deleteTask_args(context.TODO(), rawArgs)
|
||||||
|
if err != nil {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
return e.complexity.Mutation.DeleteTask(childComplexity, args["input"].(types.DeleteTaskInput)), true
|
||||||
|
|
||||||
case "Mutation.deleteVendor":
|
case "Mutation.deleteVendor":
|
||||||
if e.complexity.Mutation.DeleteVendor == nil {
|
if e.complexity.Mutation.DeleteVendor == nil {
|
||||||
break
|
break
|
||||||
@@ -1563,6 +1588,7 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler {
|
|||||||
ec.unmarshalInputCreateVendorInput,
|
ec.unmarshalInputCreateVendorInput,
|
||||||
ec.unmarshalInputDeleteOrganizationInput,
|
ec.unmarshalInputDeleteOrganizationInput,
|
||||||
ec.unmarshalInputDeletePeopleInput,
|
ec.unmarshalInputDeletePeopleInput,
|
||||||
|
ec.unmarshalInputDeleteTaskInput,
|
||||||
ec.unmarshalInputDeleteVendorInput,
|
ec.unmarshalInputDeleteVendorInput,
|
||||||
ec.unmarshalInputUpdatePeopleInput,
|
ec.unmarshalInputUpdatePeopleInput,
|
||||||
ec.unmarshalInputUpdateTaskStateInput,
|
ec.unmarshalInputUpdateTaskStateInput,
|
||||||
@@ -2059,6 +2085,7 @@ type Mutation {
|
|||||||
): DeleteOrganizationPayload!
|
): DeleteOrganizationPayload!
|
||||||
updateTaskState(input: UpdateTaskStateInput!): UpdateTaskStatePayload!
|
updateTaskState(input: UpdateTaskStateInput!): UpdateTaskStatePayload!
|
||||||
createTask(input: CreateTaskInput!): CreateTaskPayload!
|
createTask(input: CreateTaskInput!): CreateTaskPayload!
|
||||||
|
deleteTask(input: DeleteTaskInput!): DeleteTaskPayload!
|
||||||
}
|
}
|
||||||
|
|
||||||
input CreateVendorInput {
|
input CreateVendorInput {
|
||||||
@@ -2197,6 +2224,14 @@ input CreateTaskInput {
|
|||||||
type CreateTaskPayload {
|
type CreateTaskPayload {
|
||||||
taskEdge: TaskEdge!
|
taskEdge: TaskEdge!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input DeleteTaskInput {
|
||||||
|
taskId: ID!
|
||||||
|
}
|
||||||
|
|
||||||
|
type DeleteTaskPayload {
|
||||||
|
deletedTaskId: ID!
|
||||||
|
}
|
||||||
`, BuiltIn: false},
|
`, BuiltIn: false},
|
||||||
}
|
}
|
||||||
var parsedSchema = gqlparser.MustLoadSchema(sources...)
|
var parsedSchema = gqlparser.MustLoadSchema(sources...)
|
||||||
@@ -2651,6 +2686,29 @@ func (ec *executionContext) field_Mutation_deletePeople_argsInput(
|
|||||||
return zeroVal, nil
|
return zeroVal, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) field_Mutation_deleteTask_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
|
||||||
|
var err error
|
||||||
|
args := map[string]any{}
|
||||||
|
arg0, err := ec.field_Mutation_deleteTask_argsInput(ctx, rawArgs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
args["input"] = arg0
|
||||||
|
return args, nil
|
||||||
|
}
|
||||||
|
func (ec *executionContext) field_Mutation_deleteTask_argsInput(
|
||||||
|
ctx context.Context,
|
||||||
|
rawArgs map[string]any,
|
||||||
|
) (types.DeleteTaskInput, error) {
|
||||||
|
ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("input"))
|
||||||
|
if tmp, ok := rawArgs["input"]; ok {
|
||||||
|
return ec.unmarshalNDeleteTaskInput2githubᚗcomᚋgetproboᚋproboᚋpkgᚋapiᚋconsoleᚋv1ᚋtypesᚐDeleteTaskInput(ctx, tmp)
|
||||||
|
}
|
||||||
|
|
||||||
|
var zeroVal types.DeleteTaskInput
|
||||||
|
return zeroVal, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (ec *executionContext) field_Mutation_deleteVendor_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
|
func (ec *executionContext) field_Mutation_deleteVendor_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
|
||||||
var err error
|
var err error
|
||||||
args := map[string]any{}
|
args := map[string]any{}
|
||||||
@@ -4513,6 +4571,44 @@ func (ec *executionContext) fieldContext_DeletePeoplePayload_deletedPeopleId(_ c
|
|||||||
return fc, nil
|
return fc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) _DeleteTaskPayload_deletedTaskId(ctx context.Context, field graphql.CollectedField, obj *types.DeleteTaskPayload) (ret graphql.Marshaler) {
|
||||||
|
fc, err := ec.fieldContext_DeleteTaskPayload_deletedTaskId(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.DeletedTaskID, 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.(gid.GID)
|
||||||
|
fc.Result = res
|
||||||
|
return ec.marshalNID2githubᚗcomᚋgetproboᚋproboᚋpkgᚋgidᚐGID(ctx, field.Selections, res)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) fieldContext_DeleteTaskPayload_deletedTaskId(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||||
|
fc = &graphql.FieldContext{
|
||||||
|
Object: "DeleteTaskPayload",
|
||||||
|
Field: field,
|
||||||
|
IsMethod: false,
|
||||||
|
IsResolver: false,
|
||||||
|
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||||
|
return nil, errors.New("field of type ID does not have child fields")
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return fc, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (ec *executionContext) _DeleteVendorPayload_deletedVendorId(ctx context.Context, field graphql.CollectedField, obj *types.DeleteVendorPayload) (ret graphql.Marshaler) {
|
func (ec *executionContext) _DeleteVendorPayload_deletedVendorId(ctx context.Context, field graphql.CollectedField, obj *types.DeleteVendorPayload) (ret graphql.Marshaler) {
|
||||||
fc, err := ec.fieldContext_DeleteVendorPayload_deletedVendorId(ctx, field)
|
fc, err := ec.fieldContext_DeleteVendorPayload_deletedVendorId(ctx, field)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -6385,6 +6481,53 @@ func (ec *executionContext) fieldContext_Mutation_createTask(ctx context.Context
|
|||||||
return fc, nil
|
return fc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) _Mutation_deleteTask(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
||||||
|
fc, err := ec.fieldContext_Mutation_deleteTask(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().DeleteTask(rctx, fc.Args["input"].(types.DeleteTaskInput))
|
||||||
|
})
|
||||||
|
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.DeleteTaskPayload)
|
||||||
|
fc.Result = res
|
||||||
|
return ec.marshalNDeleteTaskPayload2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋapiᚋconsoleᚋv1ᚋtypesᚐDeleteTaskPayload(ctx, field.Selections, res)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) fieldContext_Mutation_deleteTask(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 "deletedTaskId":
|
||||||
|
return ec.fieldContext_DeleteTaskPayload_deletedTaskId(ctx, field)
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("no field named %q was found under type DeleteTaskPayload", field.Name)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
ctx = graphql.WithFieldContext(ctx, fc)
|
||||||
|
if fc.Args, err = ec.field_Mutation_deleteTask_args(ctx, field.ArgumentMap(ec.Variables)); err != nil {
|
||||||
|
ec.Error(ctx, err)
|
||||||
|
return fc, err
|
||||||
|
}
|
||||||
|
return fc, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (ec *executionContext) _Organization_id(ctx context.Context, field graphql.CollectedField, obj *types.Organization) (ret graphql.Marshaler) {
|
func (ec *executionContext) _Organization_id(ctx context.Context, field graphql.CollectedField, obj *types.Organization) (ret graphql.Marshaler) {
|
||||||
fc, err := ec.fieldContext_Organization_id(ctx, field)
|
fc, err := ec.fieldContext_Organization_id(ctx, field)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -11533,6 +11676,33 @@ func (ec *executionContext) unmarshalInputDeletePeopleInput(ctx context.Context,
|
|||||||
return it, nil
|
return it, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) unmarshalInputDeleteTaskInput(ctx context.Context, obj any) (types.DeleteTaskInput, error) {
|
||||||
|
var it types.DeleteTaskInput
|
||||||
|
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) unmarshalInputDeleteVendorInput(ctx context.Context, obj any) (types.DeleteVendorInput, error) {
|
func (ec *executionContext) unmarshalInputDeleteVendorInput(ctx context.Context, obj any) (types.DeleteVendorInput, error) {
|
||||||
var it types.DeleteVendorInput
|
var it types.DeleteVendorInput
|
||||||
asMap := map[string]any{}
|
asMap := map[string]any{}
|
||||||
@@ -12425,6 +12595,45 @@ func (ec *executionContext) _DeletePeoplePayload(ctx context.Context, sel ast.Se
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var deleteTaskPayloadImplementors = []string{"DeleteTaskPayload"}
|
||||||
|
|
||||||
|
func (ec *executionContext) _DeleteTaskPayload(ctx context.Context, sel ast.SelectionSet, obj *types.DeleteTaskPayload) graphql.Marshaler {
|
||||||
|
fields := graphql.CollectFields(ec.OperationContext, sel, deleteTaskPayloadImplementors)
|
||||||
|
|
||||||
|
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("DeleteTaskPayload")
|
||||||
|
case "deletedTaskId":
|
||||||
|
out.Values[i] = ec._DeleteTaskPayload_deletedTaskId(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 deleteVendorPayloadImplementors = []string{"DeleteVendorPayload"}
|
var deleteVendorPayloadImplementors = []string{"DeleteVendorPayload"}
|
||||||
|
|
||||||
func (ec *executionContext) _DeleteVendorPayload(ctx context.Context, sel ast.SelectionSet, obj *types.DeleteVendorPayload) graphql.Marshaler {
|
func (ec *executionContext) _DeleteVendorPayload(ctx context.Context, sel ast.SelectionSet, obj *types.DeleteVendorPayload) graphql.Marshaler {
|
||||||
@@ -13065,6 +13274,13 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet)
|
|||||||
if out.Values[i] == graphql.Null {
|
if out.Values[i] == graphql.Null {
|
||||||
out.Invalids++
|
out.Invalids++
|
||||||
}
|
}
|
||||||
|
case "deleteTask":
|
||||||
|
out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) {
|
||||||
|
return ec._Mutation_deleteTask(ctx, field)
|
||||||
|
})
|
||||||
|
if out.Values[i] == graphql.Null {
|
||||||
|
out.Invalids++
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
panic("unknown field " + strconv.Quote(field.Name))
|
panic("unknown field " + strconv.Quote(field.Name))
|
||||||
}
|
}
|
||||||
@@ -14990,6 +15206,25 @@ func (ec *executionContext) marshalNDeletePeoplePayload2ᚖgithubᚗcomᚋgetpro
|
|||||||
return ec._DeletePeoplePayload(ctx, sel, v)
|
return ec._DeletePeoplePayload(ctx, sel, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) unmarshalNDeleteTaskInput2githubᚗcomᚋgetproboᚋproboᚋpkgᚋapiᚋconsoleᚋv1ᚋtypesᚐDeleteTaskInput(ctx context.Context, v any) (types.DeleteTaskInput, error) {
|
||||||
|
res, err := ec.unmarshalInputDeleteTaskInput(ctx, v)
|
||||||
|
return res, graphql.ErrorOnPath(ctx, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) marshalNDeleteTaskPayload2githubᚗcomᚋgetproboᚋproboᚋpkgᚋapiᚋconsoleᚋv1ᚋtypesᚐDeleteTaskPayload(ctx context.Context, sel ast.SelectionSet, v types.DeleteTaskPayload) graphql.Marshaler {
|
||||||
|
return ec._DeleteTaskPayload(ctx, sel, &v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) marshalNDeleteTaskPayload2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋapiᚋconsoleᚋv1ᚋtypesᚐDeleteTaskPayload(ctx context.Context, sel ast.SelectionSet, v *types.DeleteTaskPayload) 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._DeleteTaskPayload(ctx, sel, v)
|
||||||
|
}
|
||||||
|
|
||||||
func (ec *executionContext) unmarshalNDeleteVendorInput2githubᚗcomᚋgetproboᚋproboᚋpkgᚋapiᚋconsoleᚋv1ᚋtypesᚐDeleteVendorInput(ctx context.Context, v any) (types.DeleteVendorInput, error) {
|
func (ec *executionContext) unmarshalNDeleteVendorInput2githubᚗcomᚋgetproboᚋproboᚋpkgᚋapiᚋconsoleᚋv1ᚋtypesᚐDeleteVendorInput(ctx context.Context, v any) (types.DeleteVendorInput, error) {
|
||||||
res, err := ec.unmarshalInputDeleteVendorInput(ctx, v)
|
res, err := ec.unmarshalInputDeleteVendorInput(ctx, v)
|
||||||
return res, graphql.ErrorOnPath(ctx, err)
|
return res, graphql.ErrorOnPath(ctx, err)
|
||||||
|
|||||||
@@ -122,6 +122,14 @@ type DeletePeoplePayload struct {
|
|||||||
DeletedPeopleID gid.GID `json:"deletedPeopleId"`
|
DeletedPeopleID gid.GID `json:"deletedPeopleId"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type DeleteTaskInput struct {
|
||||||
|
TaskID gid.GID `json:"taskId"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DeleteTaskPayload struct {
|
||||||
|
DeletedTaskID gid.GID `json:"deletedTaskId"`
|
||||||
|
}
|
||||||
|
|
||||||
type DeleteVendorInput struct {
|
type DeleteVendorInput struct {
|
||||||
VendorID gid.GID `json:"vendorId"`
|
VendorID gid.GID `json:"vendorId"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -225,6 +225,18 @@ func (r *mutationResolver) CreateTask(ctx context.Context, input types.CreateTas
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeleteTask is the resolver for the deleteTask field.
|
||||||
|
func (r *mutationResolver) DeleteTask(ctx context.Context, input types.DeleteTaskInput) (*types.DeleteTaskPayload, error) {
|
||||||
|
err := r.proboSvc.DeleteTask(ctx, input.TaskID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("cannot delete task: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &types.DeleteTaskPayload{
|
||||||
|
DeletedTaskID: input.TaskID,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Frameworks is the resolver for the frameworks field.
|
// Frameworks is the resolver for the frameworks field.
|
||||||
func (r *organizationResolver) Frameworks(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.FrameworkConnection, error) {
|
func (r *organizationResolver) Frameworks(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.FrameworkConnection, error) {
|
||||||
cursor := types.NewCursor(first, after, last, before)
|
cursor := types.NewCursor(first, after, last, before)
|
||||||
|
|||||||
@@ -269,3 +269,75 @@ WHERE
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *Task) Delete(
|
||||||
|
ctx context.Context,
|
||||||
|
conn pg.Conn,
|
||||||
|
scope *Scope,
|
||||||
|
) error {
|
||||||
|
// Use a single transaction with conditional logic to handle both cases
|
||||||
|
q := `
|
||||||
|
WITH control_count AS (
|
||||||
|
SELECT COUNT(*) AS count FROM controls_tasks WHERE task_id = @task_id
|
||||||
|
),
|
||||||
|
delete_link AS (
|
||||||
|
DELETE FROM controls_tasks
|
||||||
|
WHERE task_id = @task_id AND control_id = @control_id
|
||||||
|
RETURNING task_id
|
||||||
|
),
|
||||||
|
delete_transitions AS (
|
||||||
|
DELETE FROM task_state_transitions
|
||||||
|
WHERE %s AND task_id = @task_id AND (SELECT count FROM control_count) <= 1
|
||||||
|
RETURNING task_id
|
||||||
|
),
|
||||||
|
delete_all_links AS (
|
||||||
|
DELETE FROM controls_tasks
|
||||||
|
WHERE task_id = @task_id AND (SELECT count FROM control_count) <= 1
|
||||||
|
RETURNING task_id
|
||||||
|
),
|
||||||
|
delete_task AS (
|
||||||
|
DELETE FROM tasks
|
||||||
|
WHERE %s AND id = @task_id AND (SELECT count FROM control_count) <= 1
|
||||||
|
RETURNING id
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
(SELECT count FROM control_count) AS control_count,
|
||||||
|
(SELECT COUNT(*) FROM delete_link) AS deleted_links,
|
||||||
|
(SELECT COUNT(*) FROM delete_transitions) AS deleted_transitions,
|
||||||
|
(SELECT COUNT(*) FROM delete_all_links) AS deleted_all_links,
|
||||||
|
(SELECT COUNT(*) FROM delete_task) AS deleted_tasks;
|
||||||
|
`
|
||||||
|
q = fmt.Sprintf(q, scope.SQLFragment(), scope.SQLFragment())
|
||||||
|
|
||||||
|
args := pgx.NamedArgs{
|
||||||
|
"task_id": t.ID,
|
||||||
|
"control_id": t.ControlID,
|
||||||
|
}
|
||||||
|
maps.Copy(args, scope.SQLArguments())
|
||||||
|
|
||||||
|
var controlCount, deletedLinks, deletedTransitions, deletedAllLinks, deletedTasks int
|
||||||
|
err := conn.QueryRow(ctx, q, args).Scan(
|
||||||
|
&controlCount,
|
||||||
|
&deletedLinks,
|
||||||
|
&deletedTransitions,
|
||||||
|
&deletedAllLinks,
|
||||||
|
&deletedTasks,
|
||||||
|
)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot execute delete operation: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if controlCount <= 1 {
|
||||||
|
if deletedTransitions == 0 || deletedAllLinks == 0 || deletedTasks == 0 {
|
||||||
|
return fmt.Errorf("failed to delete task completely: transitions=%d, links=%d, tasks=%d",
|
||||||
|
deletedTransitions, deletedAllLinks, deletedTasks)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if deletedLinks == 0 {
|
||||||
|
return fmt.Errorf("failed to delete control-task link")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
22
pkg/probo/delete_task.go
Normal file
22
pkg/probo/delete_task.go
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package probo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/getprobo/probo/pkg/gid"
|
||||||
|
"github.com/getprobo/probo/pkg/probo/coredata"
|
||||||
|
"go.gearno.de/kit/pg"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s Service) DeleteTask(
|
||||||
|
ctx context.Context,
|
||||||
|
taskID gid.GID,
|
||||||
|
) error {
|
||||||
|
task := coredata.Task{ID: taskID}
|
||||||
|
return s.pg.WithConn(
|
||||||
|
ctx,
|
||||||
|
func(conn pg.Conn) error {
|
||||||
|
return task.Delete(ctx, conn, s.scope)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user