From 34fcf37295d0ed423684a73d55e1b9937b76d939 Mon Sep 17 00:00:00 2001 From: Eric Schubert Date: Thu, 23 May 2024 14:20:39 +0200 Subject: [PATCH] Added list status command to get a list of all status --- cmd/list/list.go | 3 +- cmd/list/status.go | 22 +++++++ cmd/list/work_packages.go | 6 +- components/paths/paths.go | 4 ++ components/printer/status.go | 26 ++++++++ components/printer/status_test.go | 74 ++++++++++++++++++++++ components/resources/projects/functions.go | 6 +- components/resources/status/functions.go | 20 ++++++ dtos/status.go | 46 ++++++++++++++ models/status.go | 11 ++++ 10 files changed, 211 insertions(+), 7 deletions(-) create mode 100644 cmd/list/status.go create mode 100644 components/printer/status.go create mode 100644 components/printer/status_test.go create mode 100644 components/resources/status/functions.go create mode 100644 dtos/status.go create mode 100644 models/status.go diff --git a/cmd/list/list.go b/cmd/list/list.go index f997985..2e607ef 100644 --- a/cmd/list/list.go +++ b/cmd/list/list.go @@ -41,7 +41,7 @@ func init() { "Show only work packages having the specified version") workPackagesCmd.Flags().StringVarP( - &status, + &statusFilter, "status", "s", "", @@ -63,5 +63,6 @@ status.`) notificationsCmd, workPackagesCmd, activitiesCmd, + statusCmd, ) } diff --git a/cmd/list/status.go b/cmd/list/status.go new file mode 100644 index 0000000..cf9df8f --- /dev/null +++ b/cmd/list/status.go @@ -0,0 +1,22 @@ +package list + +import ( + "github.com/opf/openproject-cli/components/printer" + "github.com/opf/openproject-cli/components/resources/status" + "github.com/spf13/cobra" +) + +var statusCmd = &cobra.Command{ + Use: "status", + Short: "Lists status", + Long: "Get a list of all status of the instance.", + Run: listStatus, +} + +func listStatus(_ *cobra.Command, _ []string) { + if all, err := status.All(); err == nil { + printer.StatusList(all) + } else { + printer.Error(err) + } +} diff --git a/cmd/list/work_packages.go b/cmd/list/work_packages.go index 7e730bc..036efff 100644 --- a/cmd/list/work_packages.go +++ b/cmd/list/work_packages.go @@ -18,7 +18,7 @@ var assignee string var projectId uint64 var version string var showTotal bool -var status string +var statusFilter string var workPackagesCmd = &cobra.Command{ Use: "workpackages", @@ -56,8 +56,8 @@ func filterOptions() *map[work_packages.FilterOption]string { options[work_packages.Assignee] = assignee } - if len(status) > 0 { - options[work_packages.Status] = validateStatusFilterValue(status) + if len(statusFilter) > 0 { + options[work_packages.Status] = validateStatusFilterValue(statusFilter) } if len(version) > 0 { diff --git a/components/paths/paths.go b/components/paths/paths.go index ddde3b1..e3f90e4 100644 --- a/components/paths/paths.go +++ b/components/paths/paths.go @@ -30,6 +30,10 @@ func Root() string { return "/api/v3" } +func Status() string { + return Root() + "/statuses" +} + func User(id uint64) string { return Users() + fmt.Sprintf("/%d", id) } diff --git a/components/printer/status.go b/components/printer/status.go new file mode 100644 index 0000000..7eb5477 --- /dev/null +++ b/components/printer/status.go @@ -0,0 +1,26 @@ +package printer + +import ( + "fmt" + "github.com/opf/openproject-cli/models" +) + +func StatusList(statuss []*models.Status) { + for _, p := range statuss { + printStatus(p) + } +} + +func Status(status *models.Status) { + printStatus(status) +} + +func printStatus(status *models.Status) { + var defaultSuffix string + + id := fmt.Sprintf("#%d", status.Id) + if status.IsDefault { + defaultSuffix = fmt.Sprintf(" (%s)", Yellow("default")) + } + activePrinter.Printf("%s %s%s\n", Red(id), Cyan(status.Name), defaultSuffix) +} diff --git a/components/printer/status_test.go b/components/printer/status_test.go new file mode 100644 index 0000000..76c4258 --- /dev/null +++ b/components/printer/status_test.go @@ -0,0 +1,74 @@ +package printer_test + +import ( + "fmt" + "strconv" + "testing" + + "github.com/opf/openproject-cli/components/common" + "github.com/opf/openproject-cli/components/printer" + "github.com/opf/openproject-cli/models" +) + +func TestStatus_Default(t *testing.T) { + testingPrinter.Reset() + + status := models.Status{ + Id: 42, + Name: "My Default", + IsDefault: true, + } + + expected := fmt.Sprintf("%s %s (%s)\n", printer.Red("#42"), printer.Cyan("My Default"), printer.Yellow("default")) + + printer.Status(&status) + + if testingPrinter.Result != expected { + t.Errorf("Expected %s, but got %s", expected, testingPrinter.Result) + } +} + +func TestStatus_NoDefault(t *testing.T) { + testingPrinter.Reset() + + status := models.Status{ + Id: 42, + Name: "Another Status", + IsDefault: false, + } + + expected := fmt.Sprintf("%s %s\n", printer.Red("#42"), printer.Cyan("Another Status")) + + printer.Status(&status) + + if testingPrinter.Result != expected { + t.Errorf("Expected %s, but got %s", expected, testingPrinter.Result) + } +} + +func TestStatusList(t *testing.T) { + testingPrinter.Reset() + + status := []*models.Status{ + {Id: 42, Name: "First"}, + {Id: 45, Name: "Second"}, + {Id: 123, Name: "Third", IsDefault: true}, + } + + expected := common.Reduce[*models.Status, string]( + status[:len(status)-1], + func(result string, status *models.Status) string { + idString := "#" + strconv.FormatUint(status.Id, 10) + + return result + fmt.Sprintf("%s %s\n", printer.Red(idString), printer.Cyan(status.Name)) + }, + "") + + expected += fmt.Sprintf("%s %s (%s)\n", printer.Red("#123"), printer.Cyan("Third"), printer.Yellow("default")) + + printer.StatusList(status) + + if testingPrinter.Result != expected { + t.Errorf("Expected %s, but got %s", expected, testingPrinter.Result) + } +} diff --git a/components/resources/projects/functions.go b/components/resources/projects/functions.go index 116b101..a34a4ab 100644 --- a/components/resources/projects/functions.go +++ b/components/resources/projects/functions.go @@ -9,7 +9,8 @@ import ( ) func All() ([]*models.Project, error) { - response, err := requests.Get(paths.Projects(), nil) + query := requests.NewPagedQuery(-1, nil) + response, err := requests.Get(paths.Projects(), &query) if err != nil { return nil, err } @@ -19,8 +20,7 @@ func All() ([]*models.Project, error) { } func Lookup(id uint64) (*models.Project, error) { - query := requests.NewPagedQuery(-1, nil) - response, err := requests.Get(paths.Project(id), &query) + response, err := requests.Get(paths.Project(id), nil) if err != nil { return nil, err } diff --git a/components/resources/status/functions.go b/components/resources/status/functions.go new file mode 100644 index 0000000..5ef2290 --- /dev/null +++ b/components/resources/status/functions.go @@ -0,0 +1,20 @@ +package status + +import ( + "github.com/opf/openproject-cli/components/parser" + "github.com/opf/openproject-cli/components/paths" + "github.com/opf/openproject-cli/components/requests" + "github.com/opf/openproject-cli/dtos" + "github.com/opf/openproject-cli/models" +) + +func All() ([]*models.Status, error) { + query := requests.NewPagedQuery(-1, nil) + response, err := requests.Get(paths.Status(), &query) + if err != nil { + return nil, err + } + + element := parser.Parse[dtos.StatusCollectionDto](response) + return element.Convert(), nil +} diff --git a/dtos/status.go b/dtos/status.go new file mode 100644 index 0000000..ed7f711 --- /dev/null +++ b/dtos/status.go @@ -0,0 +1,46 @@ +package dtos + +import "github.com/opf/openproject-cli/models" + +type statusDto struct { + Id uint64 `json:"id"` + Name string `json:"name"` + Color string `json:"color"` + IsDefault bool `json:"isDefault"` + IsClosed bool `json:"isClosed"` + IsReadonly bool `json:"isReadonly"` + Position uint64 `json:"position"` +} + +type statusElements struct { + Elements []*statusDto `json:"elements"` +} + +type StatusCollectionDto struct { + Embedded *statusElements `json:"_embedded"` + Type string `json:"_type"` +} + +/////////////// MODEL CONVERSION /////////////// + +func (dto *StatusCollectionDto) Convert() []*models.Status { + var projects = make([]*models.Status, len(dto.Embedded.Elements)) + + for idx, p := range dto.Embedded.Elements { + projects[idx] = p.Convert() + } + + return projects +} + +func (dto *statusDto) Convert() *models.Status { + return &models.Status{ + Id: dto.Id, + Name: dto.Name, + Color: dto.Color, + IsDefault: dto.IsDefault, + IsClosed: dto.IsClosed, + IsReadonly: dto.IsReadonly, + Position: dto.Position, + } +} diff --git a/models/status.go b/models/status.go new file mode 100644 index 0000000..833c238 --- /dev/null +++ b/models/status.go @@ -0,0 +1,11 @@ +package models + +type Status struct { + Id uint64 + Name string + Color string + IsDefault bool + IsClosed bool + IsReadonly bool + Position uint64 +}