Skip to content

Commit a557a2a

Browse files
committed
Added not-sub-project filter
- redesigned sub-project filter
1 parent d80d350 commit a557a2a

File tree

8 files changed

+167
-75
lines changed

8 files changed

+167
-75
lines changed

cmd/list/work_packages.go

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,17 @@ package list
22

33
import (
44
"fmt"
5-
"github.com/opf/openproject-cli/components/requests"
6-
"github.com/opf/openproject-cli/components/resources"
7-
"github.com/opf/openproject-cli/components/resources/work_packages/filters"
85
"os"
96
"regexp"
107
"strconv"
118

129
"github.com/opf/openproject-cli/components/common"
1310
"github.com/opf/openproject-cli/components/printer"
11+
"github.com/opf/openproject-cli/components/requests"
12+
"github.com/opf/openproject-cli/components/resources"
1413
"github.com/opf/openproject-cli/components/resources/projects"
1514
"github.com/opf/openproject-cli/components/resources/work_packages"
15+
"github.com/opf/openproject-cli/components/resources/work_packages/filters"
1616
"github.com/opf/openproject-cli/models"
1717
"github.com/spf13/cobra"
1818
)
@@ -24,10 +24,11 @@ var showTotal bool
2424
var statusFilter string
2525
var typeFilter string
2626
var includeSubProjects bool
27-
var subProject string
2827

29-
var activeFilters = []resources.Filter{
30-
filters.NewTimestampFilter(),
28+
var activeFilters = map[string]resources.Filter{
29+
"timestamp": filters.NewTimestampFilter(),
30+
"subProject": filters.NewSubProjectFilter(),
31+
"notSubProject": filters.NewNotSubProjectFilter(),
3132
}
3233

3334
var workPackagesCmd = &cobra.Command{
@@ -40,7 +41,7 @@ var workPackagesCmd = &cobra.Command{
4041

4142
func listWorkPackages(_ *cobra.Command, _ []string) {
4243
// This needs to be removed, once all filters are built the "new" way
43-
if errorText := validateCommandFlags(); len(errorText) > 0 {
44+
if errorText := validateCommandFlagComposition(); len(errorText) > 0 {
4445
printer.ErrorText(errorText)
4546
return
4647
}
@@ -62,21 +63,29 @@ func listWorkPackages(_ *cobra.Command, _ []string) {
6263
}
6364
}
6465

65-
func validateCommandFlags() (errorText string) {
66+
func validateCommandFlagComposition() (errorText string) {
6667
switch {
6768
case len(version) != 0 && projectId == 0:
6869
return "Version flag (--version) can only be used in conjunction with projectId flag (-p or --project-id)."
69-
case len(subProject) > 0 && (!includeSubProjects || projectId == 0):
70-
return "Sub project filter flag (--sub-project) can only be used in conjunction with setting the flag--include-sub-projects and setting a project with the projectId flag (-p or --project-id)."
71-
default:
72-
return ""
70+
case len(activeFilters["subProject"].Value()) > 0 || len(activeFilters["notSubProject"].Value()) > 0:
71+
if !includeSubProjects || projectId == 0 {
72+
return `Sub project filter flags (--sub-project or --not-sub-project) can only be used
73+
in conjunction with setting the flag --include-sub-projects and setting a
74+
project with the projectId flag (-p or --project-id).`
75+
}
7376
}
77+
78+
return ""
7479
}
7580

7681
func buildQuery() (requests.Query, error) {
7782
var q requests.Query
7883

7984
for _, filter := range activeFilters {
85+
if filter.Value() == filter.DefaultValue() {
86+
continue
87+
}
88+
8089
err := filter.ValidateInput()
8190
if err != nil {
8291
return requests.NewEmptyQuery(), err
@@ -109,10 +118,6 @@ func filterOptions() *map[work_packages.FilterOption]string {
109118
options[work_packages.Type] = validateFilterValue(work_packages.Type, typeFilter)
110119
}
111120

112-
if len(subProject) > 0 {
113-
options[work_packages.SubProject] = validateFilterValue(work_packages.SubProject, subProject)
114-
}
115-
116121
if len(version) > 0 {
117122
options[work_packages.Version] = validatedVersionId(version)
118123
}

cmd/list/work_packages_flags.go

Lines changed: 7 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
package list
22

3-
import (
4-
"github.com/opf/openproject-cli/components/resources"
5-
)
6-
73
func initWorkPackagesFlags() {
84
workPackagesCmd.Flags().StringVarP(
95
&assignee,
@@ -48,18 +44,6 @@ ID or a comma separated array of IDs, i.e. '7,13'. Multiple values are
4844
concatenated with a logical 'OR'. If the IDs are prefixed with an '!' the list
4945
is instead filtered to not have the specified status.`)
5046

51-
workPackagesCmd.Flags().StringVarP(
52-
&subProject,
53-
"sub-project",
54-
"",
55-
"",
56-
`Show only work packages of the specified subprojects. This filter only applies,
57-
if the flag '--include-sub-projects' is set. It then includes only the sub
58-
projects matching the filter. The value can be a single ID or a comma separated
59-
array of IDs, i.e. '7,13'. Multiple values are concatenated with a logical
60-
'OR'. If the IDs are prefixed with an '!' instead the specified sub projects
61-
are excluded.`)
62-
6347
workPackagesCmd.Flags().BoolVarP(
6448
&includeSubProjects,
6549
"include-sub-projects",
@@ -77,15 +61,12 @@ the default is false.`)
7761
"Show only the total number of work packages matching the filter options.")
7862

7963
for _, filter := range activeFilters {
80-
switch filter.(type) {
81-
case resources.StringValueFilter:
82-
workPackagesCmd.Flags().StringVarP(
83-
filter.Value(),
84-
filter.Name(),
85-
filter.ShortHand(),
86-
filter.(resources.StringValueFilter).DefaultValue(),
87-
filter.Usage(),
88-
)
89-
}
64+
workPackagesCmd.Flags().StringVarP(
65+
filter.ValuePointer(),
66+
filter.Name(),
67+
filter.ShortHand(),
68+
filter.DefaultValue(),
69+
filter.Usage(),
70+
)
9071
}
9172
}

components/resources/filters.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,12 @@ func TypeAheadFilter(input string) requests.Filter {
1111
}
1212

1313
type Filter interface {
14-
Value() *string
14+
Value() string
15+
ValuePointer() *string
1516
Name() string
1617
ShortHand() string
1718
Usage() string
1819
ValidateInput() error
1920
Query() requests.Query
20-
}
21-
22-
type StringValueFilter interface {
2321
DefaultValue() string
2422
}

components/resources/work_packages/filters.go

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,12 @@ const (
1414
Project
1515
Status
1616
Type
17-
SubProject
1817
IncludeSubProjects
1918
)
2019

2120
var InputValidationExpression = map[FilterOption]string{
22-
Status: "^(open)$|^(closed)$|^(!?[0-9,]+)$",
23-
Type: "^(!?[0-9,]+)$",
24-
SubProject: "^(!?[0-9,]+)$",
21+
Status: "^(open)$|^(closed)$|^(!?[0-9,]+)$",
22+
Type: "^(!?[0-9,]+)$",
2523
}
2624

2725
func (f FilterOption) String() string {
@@ -36,8 +34,6 @@ func (f FilterOption) String() string {
3634
return "status"
3735
case Type:
3836
return "type"
39-
case SubProject:
40-
return "sub-project"
4137
case IncludeSubProjects:
4238
return "include-sub-projects"
4339
default:
@@ -81,26 +77,6 @@ func TypeFilter(workPackageType string) requests.Filter {
8177
}
8278
}
8379

84-
func SubProjectFilter(filterValue string) requests.Filter {
85-
var operator string
86-
var values []string
87-
88-
switch {
89-
case strings.Index(filterValue, "!") == 0:
90-
operator = "!"
91-
values = strings.Split(filterValue[1:], ",")
92-
default:
93-
operator = "="
94-
values = strings.Split(filterValue, ",")
95-
}
96-
97-
return requests.Filter{
98-
Operator: operator,
99-
Name: "subprojectId",
100-
Values: values,
101-
}
102-
}
103-
10480
func StatusFilter(status string) requests.Filter {
10581
var operator string
10682
var values []string
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package filters
2+
3+
import (
4+
"fmt"
5+
"regexp"
6+
"strings"
7+
8+
"github.com/opf/openproject-cli/components/errors"
9+
"github.com/opf/openproject-cli/components/printer"
10+
"github.com/opf/openproject-cli/components/requests"
11+
)
12+
13+
type NotSubProjectFilter struct {
14+
value string
15+
}
16+
17+
func (f *NotSubProjectFilter) ValuePointer() *string {
18+
return &f.value
19+
}
20+
21+
func (f *NotSubProjectFilter) Value() string {
22+
return f.value
23+
}
24+
25+
func (f *NotSubProjectFilter) Name() string {
26+
return "not-sub-project"
27+
}
28+
29+
func (f *NotSubProjectFilter) ShortHand() string {
30+
return ""
31+
}
32+
33+
func (f *NotSubProjectFilter) Usage() string {
34+
return `Show only work packages that are not inside the specified subprojects. This
35+
filter only applies, if the flag '--include-sub-projects' is set. It then
36+
excludes all sub projects matching the filter. The value can be a single ID or
37+
a comma separated array of IDs, i.e. '7,13'.`
38+
}
39+
40+
func (f *NotSubProjectFilter) ValidateInput() error {
41+
matched, _ := regexp.Match("^([0-9,]+)$", []byte(f.value))
42+
if !matched {
43+
return errors.Custom(fmt.Sprintf("Invalid not-sub-project value %s.", printer.Yellow(f.value)))
44+
}
45+
46+
return nil
47+
}
48+
49+
func (f *NotSubProjectFilter) DefaultValue() string {
50+
return ""
51+
}
52+
53+
func (f *NotSubProjectFilter) Query() requests.Query {
54+
return requests.NewQuery(nil, []requests.Filter{
55+
{
56+
Operator: "!",
57+
Name: "subprojectId",
58+
Values: strings.Split(f.value, ","),
59+
},
60+
})
61+
}
62+
63+
func NewNotSubProjectFilter() *NotSubProjectFilter {
64+
return &NotSubProjectFilter{}
65+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package filters
2+
3+
import (
4+
"fmt"
5+
"regexp"
6+
"strings"
7+
8+
"github.com/opf/openproject-cli/components/errors"
9+
"github.com/opf/openproject-cli/components/printer"
10+
"github.com/opf/openproject-cli/components/requests"
11+
)
12+
13+
type SubProjectFilter struct {
14+
value string
15+
}
16+
17+
func (f *SubProjectFilter) ValuePointer() *string {
18+
return &f.value
19+
}
20+
21+
func (f *SubProjectFilter) Value() string {
22+
return f.value
23+
}
24+
25+
func (f *SubProjectFilter) Name() string {
26+
return "sub-project"
27+
}
28+
29+
func (f *SubProjectFilter) ShortHand() string {
30+
return ""
31+
}
32+
33+
func (f *SubProjectFilter) Usage() string {
34+
return `Show only work packages of the specified subprojects. This filter only applies,
35+
if the flag '--include-sub-projects' is set. It then includes only the sub
36+
projects matching the filter. The value can be a single ID or a comma separated
37+
array of IDs, i.e. '7,13'. Multiple values are concatenated with a logical 'OR'.`
38+
}
39+
40+
func (f *SubProjectFilter) ValidateInput() error {
41+
matched, _ := regexp.Match("^([0-9,]+)$", []byte(f.value))
42+
if !matched {
43+
return errors.Custom(fmt.Sprintf("Invalid sub-project value %s.", printer.Yellow(f.value)))
44+
}
45+
46+
return nil
47+
}
48+
49+
func (f *SubProjectFilter) DefaultValue() string {
50+
return ""
51+
}
52+
53+
func (f *SubProjectFilter) Query() requests.Query {
54+
return requests.NewQuery(nil, []requests.Filter{
55+
{
56+
Operator: "=",
57+
Name: "subprojectId",
58+
Values: strings.Split(f.value, ","),
59+
},
60+
})
61+
}
62+
63+
func NewSubProjectFilter() *SubProjectFilter {
64+
return &SubProjectFilter{}
65+
}

components/resources/work_packages/filters/timestamp.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,14 @@ type TimestampFilter struct {
1010
value string
1111
}
1212

13-
func (f *TimestampFilter) Value() *string {
13+
func (f *TimestampFilter) ValuePointer() *string {
1414
return &f.value
1515
}
1616

17+
func (f *TimestampFilter) Value() string {
18+
return f.value
19+
}
20+
1721
func (f *TimestampFilter) Name() string {
1822
return "timestamp"
1923
}

components/resources/work_packages/read.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,6 @@ func All(filterOptions *map[FilterOption]string, query requests.Query, showOnlyT
3636
filters = append(filters, StatusFilter(value))
3737
case Type:
3838
filters = append(filters, TypeFilter(value))
39-
case SubProject:
40-
filters = append(filters, SubProjectFilter(value))
4139
case Project:
4240
n, _ := strconv.ParseUint(value, 10, 64)
4341
projectId = &n

0 commit comments

Comments
 (0)