From 6631543824d105e39a99b1da8dec3bf31b6e7185 Mon Sep 17 00:00:00 2001 From: gearnode Date: Mon, 27 Jan 2025 18:18:43 +0100 Subject: [PATCH] Add ControlState type Signed-off-by: gearnode --- pkg/api/console/v1/schema.graphql | 10 +++- pkg/api/console/v1/schema/schema.go | 26 +++++++-- pkg/api/console/v1/types/control.go | 2 +- pkg/api/console/v1/types/types.go | 50 +++++++++++++++- pkg/probo/coredata/control_state.go | 88 +++++++++++++++++++++++++++++ 5 files changed, 169 insertions(+), 7 deletions(-) create mode 100644 pkg/probo/coredata/control_state.go diff --git a/pkg/api/console/v1/schema.graphql b/pkg/api/console/v1/schema.graphql index 349af7d08..4e7b8d881 100644 --- a/pkg/api/console/v1/schema.graphql +++ b/pkg/api/console/v1/schema.graphql @@ -13,6 +13,14 @@ interface Node { id: ID! } +enum ControlState { + NotStarted + InProgress + NotApplicable + Implemented +} + + type PageInfo { hasNextPage: Boolean! hasPreviousPage: Boolean! @@ -75,7 +83,7 @@ type Control implements Node { id: ID! name: String! description: String! - state: String! + state: ControlState! tasks( first: Int diff --git a/pkg/api/console/v1/schema/schema.go b/pkg/api/console/v1/schema/schema.go index 2c6198b37..672445580 100644 --- a/pkg/api/console/v1/schema/schema.go +++ b/pkg/api/console/v1/schema/schema.go @@ -556,6 +556,14 @@ interface Node { id: ID! } +enum ControlState { + NotStarted + InProgress + NotApplicable + Implemented +} + + type PageInfo { hasNextPage: Boolean! hasPreviousPage: Boolean! @@ -618,7 +626,7 @@ type Control implements Node { id: ID! name: String! description: String! - state: String! + state: ControlState! tasks( first: Int @@ -1124,9 +1132,9 @@ func (ec *executionContext) _Control_state(ctx context.Context, field graphql.Co } return graphql.Null } - res := resTmp.(string) + res := resTmp.(types.ControlState) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalNControlState2githubᚗcomᚋgetproboᚋproboᚋpkgᚋapiᚋconsoleᚋv1ᚋtypesᚐControlState(ctx, field.Selections, res) } func (ec *executionContext) fieldContext_Control_state(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { @@ -1136,7 +1144,7 @@ func (ec *executionContext) fieldContext_Control_state(_ context.Context, field IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type String does not have child fields") + return nil, errors.New("field of type ControlState does not have child fields") }, } return fc, nil @@ -5415,6 +5423,16 @@ func (ec *executionContext) marshalNControlEdge2ᚖgithubᚗcomᚋgetproboᚋpro return ec._ControlEdge(ctx, sel, v) } +func (ec *executionContext) unmarshalNControlState2githubᚗcomᚋgetproboᚋproboᚋpkgᚋapiᚋconsoleᚋv1ᚋtypesᚐControlState(ctx context.Context, v any) (types.ControlState, error) { + var res types.ControlState + err := res.UnmarshalGQL(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNControlState2githubᚗcomᚋgetproboᚋproboᚋpkgᚋapiᚋconsoleᚋv1ᚋtypesᚐControlState(ctx context.Context, sel ast.SelectionSet, v types.ControlState) graphql.Marshaler { + return v +} + func (ec *executionContext) unmarshalNCursorKey2githubᚗcomᚋgetproboᚋproboᚋpkgᚋproboᚋcoredataᚋpageᚐCursorKey(ctx context.Context, v any) (page.CursorKey, error) { res, err := types.UnmarshalCursorKeyScalar(v) return res, graphql.ErrorOnPath(ctx, err) diff --git a/pkg/api/console/v1/types/control.go b/pkg/api/console/v1/types/control.go index b7fc06810..fdda80515 100644 --- a/pkg/api/console/v1/types/control.go +++ b/pkg/api/console/v1/types/control.go @@ -44,7 +44,7 @@ func NewControl(c *coredata.Control) *Control { ID: c.ID, Name: c.Name, Description: c.Description, - State: string(c.State), + State: ControlState(c.State.String()), CreatedAt: c.CreatedAt, UpdatedAt: c.UpdatedAt, } diff --git a/pkg/api/console/v1/types/types.go b/pkg/api/console/v1/types/types.go index 9a50fff1b..34f925665 100644 --- a/pkg/api/console/v1/types/types.go +++ b/pkg/api/console/v1/types/types.go @@ -3,6 +3,9 @@ package types import ( + "fmt" + "io" + "strconv" "time" "github.com/getprobo/probo/pkg/probo/coredata/gid" @@ -18,7 +21,7 @@ type Control struct { ID gid.GID `json:"id"` Name string `json:"name"` Description string `json:"description"` - State string `json:"state"` + State ControlState `json:"state"` Tasks *TaskConnection `json:"tasks"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` @@ -99,3 +102,48 @@ type TaskEdge struct { Cursor page.CursorKey `json:"cursor"` Node *Task `json:"node"` } + +type ControlState string + +const ( + ControlStateNotStarted ControlState = "NotStarted" + ControlStateInProgress ControlState = "InProgress" + ControlStateNotApplicable ControlState = "NotApplicable" + ControlStateImplemented ControlState = "Implemented" +) + +var AllControlState = []ControlState{ + ControlStateNotStarted, + ControlStateInProgress, + ControlStateNotApplicable, + ControlStateImplemented, +} + +func (e ControlState) IsValid() bool { + switch e { + case ControlStateNotStarted, ControlStateInProgress, ControlStateNotApplicable, ControlStateImplemented: + return true + } + return false +} + +func (e ControlState) String() string { + return string(e) +} + +func (e *ControlState) UnmarshalGQL(v any) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = ControlState(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid ControlState", str) + } + return nil +} + +func (e ControlState) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} diff --git a/pkg/probo/coredata/control_state.go b/pkg/probo/coredata/control_state.go new file mode 100644 index 000000000..c742ddce9 --- /dev/null +++ b/pkg/probo/coredata/control_state.go @@ -0,0 +1,88 @@ +// Copyright (c) 2025 Probo Inc . +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +package coredata + +import ( + "database/sql/driver" + "fmt" + + "go.gearno.de/x/panicf" +) + +type ( + ControlState uint8 +) + +const ( + ControlStateNotStarted ControlState = iota + ControlStateInProgress + ControlStateNotApplicable + ControlStateImplemented +) + +func (cs ControlState) MarshalText() ([]byte, error) { + return []byte(cs.String()), nil +} + +func (cs *ControlState) UnmarshalText(data []byte) error { + val := string(data) + + switch val { + case ControlStateNotStarted.String(): + *cs = ControlStateNotStarted + case ControlStateInProgress.String(): + *cs = ControlStateInProgress + case ControlStateNotApplicable.String(): + *cs = ControlStateNotApplicable + case ControlStateImplemented.String(): + *cs = ControlStateImplemented + default: + return fmt.Errorf("invalid ControlState value: %q", val) + } + + return nil +} + +func (cs ControlState) String() string { + var val string + + switch cs { + case ControlStateNotStarted: + val = "NOT_STARTED" + case ControlStateInProgress: + val = "IN_PROGRESS" + case ControlStateNotApplicable: + val = "NOT_APPLICABLE" + case ControlStateImplemented: + val = "IMPLEMENTED" + default: + panicf.Panic("invalid control state value: %v", cs) + } + + return val +} + +func (cs ControlState) Scan(value any) error { + val, ok := value.(string) + if !ok { + return fmt.Errorf("invalid scan source for ControlState, expected string got %T", value) + } + + return cs.UnmarshalText([]byte(val)) +} + +func (cs ControlState) Value() (driver.Value, error) { + return cs.String(), nil +}