From 7efae811139d1b842920c38e407d15304b95a1c7 Mon Sep 17 00:00:00 2001 From: gearnode Date: Wed, 19 Mar 2025 13:08:27 +0100 Subject: [PATCH] Make task time estimate optional close #38 Signed-off-by: gearnode --- .../console/src/pages/ControlOverviewPage.tsx | 3 +- ...lOverviewPageCreateTaskMutation.graphql.ts | 6 ++-- .../ControlOverviewPageQuery.graphql.ts | 4 +-- pkg/coredata/migrations/20240319T121300Z.sql | 1 + pkg/coredata/task.go | 22 ++++++------- pkg/probo/framework_service.go | 8 ++++- pkg/probo/task_service.go | 2 +- pkg/server/api/console/v1/schema.graphql | 4 +-- pkg/server/api/console/v1/schema/schema.go | 31 +++---------------- pkg/server/api/console/v1/types/types.go | 12 +++---- 10 files changed, 39 insertions(+), 54 deletions(-) create mode 100644 pkg/coredata/migrations/20240319T121300Z.sql diff --git a/apps/console/src/pages/ControlOverviewPage.tsx b/apps/console/src/pages/ControlOverviewPage.tsx index c6e0633ae..896d215ca 100644 --- a/apps/console/src/pages/ControlOverviewPage.tsx +++ b/apps/console/src/pages/ControlOverviewPage.tsx @@ -625,7 +625,6 @@ function ControlOverviewPageContent({ }); return; } - // Convert the time estimate components to ISO 8601 format const isoTimeEstimate = convertToISODuration(); @@ -636,7 +635,7 @@ function ControlOverviewPageContent({ controlId: data.control.id, name: newTaskName, description: newTaskDescription, - timeEstimate: isoTimeEstimate, + timeEstimate: isoTimeEstimate === "" ? null : isoTimeEstimate, }, }, onCompleted: () => { diff --git a/apps/console/src/pages/__generated__/ControlOverviewPageCreateTaskMutation.graphql.ts b/apps/console/src/pages/__generated__/ControlOverviewPageCreateTaskMutation.graphql.ts index fc1f8e951..7618839d1 100644 --- a/apps/console/src/pages/__generated__/ControlOverviewPageCreateTaskMutation.graphql.ts +++ b/apps/console/src/pages/__generated__/ControlOverviewPageCreateTaskMutation.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<> + * @generated SignedSource<<318d80720efe2f6e610353e3a640d786>> * @lightSyntaxTransform * @nogrep */ @@ -15,7 +15,7 @@ export type CreateTaskInput = { controlId: string; description: string; name: string; - timeEstimate: any; + timeEstimate?: any | null | undefined; }; export type ControlOverviewPageCreateTaskMutation$variables = { connections: ReadonlyArray; @@ -34,7 +34,7 @@ export type ControlOverviewPageCreateTaskMutation$data = { readonly id: string; readonly name: string; readonly state: TaskState; - readonly timeEstimate: any; + readonly timeEstimate: any | null | undefined; readonly version: number; }; }; diff --git a/apps/console/src/pages/__generated__/ControlOverviewPageQuery.graphql.ts b/apps/console/src/pages/__generated__/ControlOverviewPageQuery.graphql.ts index 99688bcc1..cffb30850 100644 --- a/apps/console/src/pages/__generated__/ControlOverviewPageQuery.graphql.ts +++ b/apps/console/src/pages/__generated__/ControlOverviewPageQuery.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<84b34aa7e582728a8386d1fe1ef3fb58>> + * @generated SignedSource<<084485ae03f7089bfdee310d631b01eb>> * @lightSyntaxTransform * @nogrep */ @@ -50,7 +50,7 @@ export type ControlOverviewPageQuery$data = { readonly id: string; readonly name: string; readonly state: TaskState; - readonly timeEstimate: any; + readonly timeEstimate: any | null | undefined; readonly version: number; }; }>; diff --git a/pkg/coredata/migrations/20240319T121300Z.sql b/pkg/coredata/migrations/20240319T121300Z.sql new file mode 100644 index 000000000..696a8cfdc --- /dev/null +++ b/pkg/coredata/migrations/20240319T121300Z.sql @@ -0,0 +1 @@ +ALTER TABLE tasks ALTER COLUMN time_estimate DROP NOT NULL; \ No newline at end of file diff --git a/pkg/coredata/task.go b/pkg/coredata/task.go index 79744c95d..e3cb9d892 100644 --- a/pkg/coredata/task.go +++ b/pkg/coredata/task.go @@ -29,17 +29,17 @@ import ( type ( Task struct { - ID gid.GID `db:"id"` - ControlID gid.GID `db:"control_id"` - Name string `db:"name"` - Description string `db:"description"` - State TaskState `db:"state"` - ContentRef string `db:"content_ref"` - 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"` + ID gid.GID `db:"id"` + ControlID gid.GID `db:"control_id"` + Name string `db:"name"` + Description string `db:"description"` + State TaskState `db:"state"` + ContentRef string `db:"content_ref"` + 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"` } Tasks []*Task diff --git a/pkg/probo/framework_service.go b/pkg/probo/framework_service.go index 12c419162..0bbb63244 100644 --- a/pkg/probo/framework_service.go +++ b/pkg/probo/framework_service.go @@ -19,6 +19,7 @@ import ( "fmt" "time" + "gearno.de/ref" "github.com/getprobo/probo/pkg/coredata" "github.com/getprobo/probo/pkg/gid" "github.com/getprobo/probo/pkg/page" @@ -241,16 +242,21 @@ func (s FrameworkService) Import( return nil, fmt.Errorf("cannot create global id: %w", err) } + var timeEstimate *time.Duration + if task.TimeEstimate > 0 { + timeEstimate = ref.Ref(time.Duration(task.TimeEstimate) * time.Second) + } + importedTasks = append(importedTasks, &coredata.Task{ ID: taskID, ControlID: controlID, Name: task.Name, - TimeEstimate: time.Duration(task.TimeEstimate) * time.Second, State: coredata.TaskStateTodo, Description: task.Description, ContentRef: "", CreatedAt: now, UpdatedAt: now, + TimeEstimate: timeEstimate, }) } } diff --git a/pkg/probo/task_service.go b/pkg/probo/task_service.go index a448c26c8..9bebdcd25 100644 --- a/pkg/probo/task_service.go +++ b/pkg/probo/task_service.go @@ -35,7 +35,7 @@ type ( Name string ContentRef string Description string - TimeEstimate time.Duration + TimeEstimate *time.Duration AssignedTo *gid.GID } diff --git a/pkg/server/api/console/v1/schema.graphql b/pkg/server/api/console/v1/schema.graphql index afc5589f9..833ebaf4b 100644 --- a/pkg/server/api/console/v1/schema.graphql +++ b/pkg/server/api/console/v1/schema.graphql @@ -386,7 +386,7 @@ type Task implements Node { name: String! description: String! state: TaskState! - timeEstimate: Duration! + timeEstimate: Duration assignedTo: People @goField(forceResolver: true) evidences( @@ -633,7 +633,7 @@ input CreateTaskInput { controlId: ID! name: String! description: String! - timeEstimate: Duration! + timeEstimate: Duration assignedToId: ID } diff --git a/pkg/server/api/console/v1/schema/schema.go b/pkg/server/api/console/v1/schema/schema.go index 84a3d7a93..e8c51af6e 100644 --- a/pkg/server/api/console/v1/schema/schema.go +++ b/pkg/server/api/console/v1/schema/schema.go @@ -2477,7 +2477,7 @@ type Task implements Node { name: String! description: String! state: TaskState! - timeEstimate: Duration! + timeEstimate: Duration assignedTo: People @goField(forceResolver: true) evidences( @@ -2724,7 +2724,7 @@ input CreateTaskInput { controlId: ID! name: String! description: String! - timeEstimate: Duration! + timeEstimate: Duration assignedToId: ID } @@ -10441,14 +10441,11 @@ func (ec *executionContext) _Task_timeEstimate(ctx context.Context, field graphq return graphql.Null } if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } return graphql.Null } - res := resTmp.(time.Duration) + res := resTmp.(*time.Duration) fc.Result = res - return ec.marshalNDuration2timeᚐDuration(ctx, field.Selections, res) + return ec.marshalODuration2ᚖtimeᚐDuration(ctx, field.Selections, res) } func (ec *executionContext) fieldContext_Task_timeEstimate(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { @@ -14606,7 +14603,7 @@ func (ec *executionContext) unmarshalInputCreateTaskInput(ctx context.Context, o it.Description = data case "timeEstimate": ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("timeEstimate")) - data, err := ec.unmarshalNDuration2timeᚐDuration(ctx, v) + data, err := ec.unmarshalODuration2ᚖtimeᚐDuration(ctx, v) if err != nil { return it, err } @@ -18246,9 +18243,6 @@ func (ec *executionContext) _Task(ctx context.Context, sel ast.SelectionSet, obj } case "timeEstimate": out.Values[i] = ec._Task_timeEstimate(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&out.Invalids, 1) - } case "assignedTo": field := field @@ -19990,21 +19984,6 @@ func (ec *executionContext) marshalNDeleteVendorPayload2ᚖgithubᚗcomᚋgetpro return ec._DeleteVendorPayload(ctx, sel, v) } -func (ec *executionContext) unmarshalNDuration2timeᚐDuration(ctx context.Context, v any) (time.Duration, error) { - res, err := graphql.UnmarshalDuration(v) - return res, graphql.ErrorOnPath(ctx, err) -} - -func (ec *executionContext) marshalNDuration2timeᚐDuration(ctx context.Context, sel ast.SelectionSet, v time.Duration) graphql.Marshaler { - res := graphql.MarshalDuration(v) - if res == graphql.Null { - if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { - ec.Errorf(ctx, "the requested element is null which the schema does not allow") - } - } - return res -} - func (ec *executionContext) marshalNEvidence2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐEvidence(ctx context.Context, sel ast.SelectionSet, v *types.Evidence) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { diff --git a/pkg/server/api/console/v1/types/types.go b/pkg/server/api/console/v1/types/types.go index 4f1810efe..d112b8bbd 100644 --- a/pkg/server/api/console/v1/types/types.go +++ b/pkg/server/api/console/v1/types/types.go @@ -118,11 +118,11 @@ type CreatePolicyPayload struct { } type CreateTaskInput struct { - ControlID gid.GID `json:"controlId"` - Name string `json:"name"` - Description string `json:"description"` - TimeEstimate time.Duration `json:"timeEstimate"` - AssignedToID *gid.GID `json:"assignedToId,omitempty"` + ControlID gid.GID `json:"controlId"` + Name string `json:"name"` + Description string `json:"description"` + TimeEstimate *time.Duration `json:"timeEstimate,omitempty"` + AssignedToID *gid.GID `json:"assignedToId,omitempty"` } type CreateTaskPayload struct { @@ -373,7 +373,7 @@ type Task struct { Name string `json:"name"` Description string `json:"description"` State coredata.TaskState `json:"state"` - TimeEstimate time.Duration `json:"timeEstimate"` + TimeEstimate *time.Duration `json:"timeEstimate,omitempty"` AssignedTo *People `json:"assignedTo,omitempty"` Evidences *EvidenceConnection `json:"evidences"` CreatedAt time.Time `json:"createdAt"`