diff --git a/internal/config/config.go b/internal/config/config.go index 97a1040..cd9662c 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -32,6 +32,7 @@ type ActionArgument struct { Type string Default string Choices []ActionArgumentChoice + Entity string } // ActionArgumentChoice represents a predefined choice for an argument. diff --git a/internal/executor/arguments.go b/internal/executor/arguments.go index a6b7380..1ce7c16 100644 --- a/internal/executor/arguments.go +++ b/internal/executor/arguments.go @@ -78,6 +78,10 @@ func typecheckActionArgument(name string, value string, action *config.Action) e } func typecheckChoice(value string, arg *config.ActionArgument) error { + if arg.Entity != "" { + return typecheckChoiceEntity(value, arg) + } + for _, choice := range arg.Choices { if value == choice.Value { return nil @@ -87,6 +91,20 @@ func typecheckChoice(value string, arg *config.ActionArgument) error { return errors.New("argument value is not one of the predefined choices") } +func typecheckChoiceEntity(value string, arg *config.ActionArgument) error { + templateChoice := arg.Choices[0].Value + + for _, ent := range sv.GetEntities(arg.Entity) { + choice := sv.ReplaceEntityVars(ent, templateChoice) + + if value == choice { + return nil + } + } + + return errors.New("argument value cannot be found in entities") +} + // TypeSafetyCheck checks argument values match a specific type. The types are // defined in typecheckRegex, and, you guessed it, uses regex to check for allowed // characters. diff --git a/internal/grpcapi/grpcApiActions.go b/internal/grpcapi/grpcApiActions.go index cde6fc9..32872aa 100644 --- a/internal/grpcapi/grpcApiActions.go +++ b/internal/grpcapi/grpcApiActions.go @@ -54,7 +54,7 @@ func buildActionEntities(entityTitle string, tpl *config.Action) []*pb.Action { } func buildEntityAction(tpl *config.Action, entityTitle string, entityIndex int) *pb.Action { - prefix := getEntityPrefix(entityTitle, entityIndex) + prefix := sv.GetEntityPrefix(entityTitle, entityIndex) virtualActionId := createPublicID(tpl, prefix) @@ -93,7 +93,7 @@ func actionCfgToPb(action *config.Action, user *acl.AuthenticatedUser) *pb.Actio Type: cfgArg.Type, Description: cfgArg.Description, DefaultValue: cfgArg.Default, - Choices: buildChoices(cfgArg.Choices), + Choices: buildChoices(cfgArg), } btn.Arguments = append(btn.Arguments, &pbArg) @@ -102,7 +102,32 @@ func actionCfgToPb(action *config.Action, user *acl.AuthenticatedUser) *pb.Actio return &btn } -func buildChoices(choices []config.ActionArgumentChoice) []*pb.ActionArgumentChoice { +func buildChoices(arg config.ActionArgument) []*pb.ActionArgumentChoice { + if arg.Entity != "" && len(arg.Choices) == 1 { + return buildChoicesEntity(arg.Choices[0], arg.Entity) + } else { + return buildChoicesSimple(arg.Choices) + } +} + +func buildChoicesEntity(firstChoice config.ActionArgumentChoice, entityTitle string) []*pb.ActionArgumentChoice { + ret := []*pb.ActionArgumentChoice{} + + entityCount := sv.GetEntityCount(entityTitle) + + for i := 0; i < entityCount; i++ { + prefix := sv.GetEntityPrefix(entityTitle, i) + + ret = append(ret, &pb.ActionArgumentChoice{ + Value: sv.ReplaceEntityVars(prefix, firstChoice.Value), + Title: sv.ReplaceEntityVars(prefix, firstChoice.Title), + }) + } + + return ret +} + +func buildChoicesSimple(choices []config.ActionArgumentChoice) []*pb.ActionArgumentChoice { ret := []*pb.ActionArgumentChoice{} for _, cfgChoice := range choices { diff --git a/internal/grpcapi/grpcApiDashboardEntities.go b/internal/grpcapi/grpcApiDashboardEntities.go index ffa728e..b20e9fe 100644 --- a/internal/grpcapi/grpcApiDashboardEntities.go +++ b/internal/grpcapi/grpcApiDashboardEntities.go @@ -4,19 +4,12 @@ import ( pb "github.com/OliveTin/OliveTin/gen/grpc" config "github.com/OliveTin/OliveTin/internal/config" sv "github.com/OliveTin/OliveTin/internal/stringvariables" - - "fmt" - "strconv" ) -func getEntityPrefix(entityTitle string, entityIndex int) string { - return "entities." + entityTitle + "." + fmt.Sprintf("%v", entityIndex) -} - func buildEntityFieldsets(entityTitle string, tpl *config.DashboardComponent) []*pb.DashboardComponent { ret := make([]*pb.DashboardComponent, 0) - entityCount, _ := strconv.Atoi(sv.Get("entities." + entityTitle + ".count")) + entityCount := sv.GetEntityCount(entityTitle) for i := 0; i < entityCount; i++ { ret = append(ret, buildEntityFieldset(tpl, entityTitle, i)) @@ -26,7 +19,7 @@ func buildEntityFieldsets(entityTitle string, tpl *config.DashboardComponent) [] } func buildEntityFieldset(tpl *config.DashboardComponent, entityTitle string, entityIndex int) *pb.DashboardComponent { - prefix := getEntityPrefix(entityTitle, entityIndex) + prefix := sv.GetEntityPrefix(entityTitle, entityIndex) return &pb.DashboardComponent{ Title: sv.ReplaceEntityVars(prefix, tpl.Title), diff --git a/internal/stringvariables/entities.go b/internal/stringvariables/entities.go index 15502b3..e24224e 100644 --- a/internal/stringvariables/entities.go +++ b/internal/stringvariables/entities.go @@ -1,7 +1,9 @@ package stringvariables import ( + "fmt" "regexp" + "strconv" "strings" // log "github.com/sirupsen/logrus" ) @@ -35,3 +37,27 @@ func RemoveKeysThatStartWith(search string) { } } } + +func GetEntities(entityTitle string) []string { + var ret []string + + count := GetEntityCount(entityTitle) + + for i := 0; i < count; i++ { + prefix := GetEntityPrefix(entityTitle, i) + + ret = append(ret, prefix) + } + + return ret +} + +func GetEntityPrefix(entityTitle string, entityIndex int) string { + return "entities." + entityTitle + "." + fmt.Sprintf("%v", entityIndex) +} + +func GetEntityCount(entityTitle string) int { + count, _ := strconv.Atoi(Get("entities." + entityTitle + ".count")) + + return count +}