Skip to content

Commit 976ec41

Browse files
authored
Stylize command output and add help to query view
Stylize command output and add help to query view
2 parents 699627b + a3173e5 commit 976ec41

File tree

8 files changed

+243
-243
lines changed

8 files changed

+243
-243
lines changed

cmd/pre.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ func PreRunDefaultProfile(cmd *cobra.Command, args []string) error {
3333
conf, err := config.ReadConfigFromFile()
3434
if err != nil {
3535
if os.IsNotExist(err) {
36-
return errors.New("No config found to run this command. Add a profile using pb profile command")
36+
return errors.New("no config found to run this command. add a profile using pb profile command")
3737
} else {
3838
return err
3939
}

cmd/profile.go

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,35 @@ import (
2525
"pb/pkg/config"
2626
"pb/pkg/model"
2727

28-
"github.com/charmbracelet/bubbles/table"
2928
tea "github.com/charmbracelet/bubbletea"
3029
"github.com/charmbracelet/lipgloss"
3130
"github.com/spf13/cobra"
3231
)
3332

33+
type ProfileListItem struct {
34+
title, url, user string
35+
}
36+
37+
func (item *ProfileListItem) Render(highlight bool) string {
38+
if highlight {
39+
render := fmt.Sprintf(
40+
"%s\n%s\n%s",
41+
selectedStyle.Render(item.title),
42+
selectedStyleAlt.Render(fmt.Sprintf("url: %s", item.url)),
43+
selectedStyleAlt.Render(fmt.Sprintf("user: %s", item.user)),
44+
)
45+
return selectedItemOuter.Render(render)
46+
} else {
47+
render := fmt.Sprintf(
48+
"%s\n%s\n%s",
49+
standardStyle.Render(item.title),
50+
standardStyleAlt.Render(fmt.Sprintf("url: %s", item.url)),
51+
standardStyleAlt.Render(fmt.Sprintf("user: %s", item.user)),
52+
)
53+
return itemOuter.Render(render)
54+
}
55+
}
56+
3457
var AddProfileCmd = &cobra.Command{
3558
Use: "add name url <username?> <password?>",
3659
Example: "add local_logs http://0.0.0.0:8000 admin admin",
@@ -163,40 +186,17 @@ var ListProfileCmd = &cobra.Command{
163186
return nil
164187
}
165188

166-
cols := []table.Column{
167-
{Title: "PROFILE", Width: 7},
168-
{Title: "URL", Width: 5},
169-
{Title: "USER", Width: 8},
189+
if len(file_config.Profiles) != 0 {
190+
println()
170191
}
171192

172-
rows := make([]table.Row, len(file_config.Profiles))
173-
row_idx := 0
174-
selected_row := 0
193+
row := 0
175194
for key, value := range file_config.Profiles {
176-
if file_config.Default_profile == key {
177-
selected_row = row_idx
178-
}
179-
180-
rows[row_idx] = table.Row{key, value.Url, value.Username}
181-
row_idx += 1
182-
183-
// update max width for table
184-
cols[0].Width = Max(cols[0].Width, len(key))
185-
cols[1].Width = Max(cols[1].Width, len(value.Url))
186-
cols[2].Width = Max(cols[2].Width, len(value.Password))
195+
item := ProfileListItem{key, value.Url, value.Username}
196+
fmt.Println(item.Render(file_config.Default_profile == key))
197+
row += 1
198+
fmt.Println()
187199
}
188-
189-
tbl := table.New(
190-
table.WithColumns(cols),
191-
table.WithRows(rows),
192-
table.WithHeight(len(rows)),
193-
table.WithStyles(listingTableStyle()),
194-
)
195-
196-
tbl.SetCursor(selected_row)
197-
198-
fmt.Println(tbl.View())
199-
200200
return nil
201201
},
202202
}

cmd/query.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,25 @@ import (
2121
"fmt"
2222
"os"
2323
"pb/pkg/model"
24+
"strconv"
2425

2526
tea "github.com/charmbracelet/bubbletea"
2627
"github.com/spf13/cobra"
2728
)
2829

2930
var QueryProfileCmd = &cobra.Command{
30-
Use: "query name",
31+
Use: "query name minutes",
32+
Example: "query local_logs 20",
3133
Short: "Open Query TUI",
32-
Args: cobra.ExactArgs(1),
34+
Args: cobra.ExactArgs(2),
3335
PreRunE: PreRunDefaultProfile,
3436
RunE: func(cmd *cobra.Command, args []string) error {
3537
stream := args[0]
36-
p := tea.NewProgram(model.NewQueryModel(DefaultProfile, stream), tea.WithAltScreen())
38+
duration, err := strconv.Atoi(args[1])
39+
if err != nil {
40+
return err
41+
}
42+
p := tea.NewProgram(model.NewQueryModel(DefaultProfile, stream, uint(duration)), tea.WithAltScreen())
3743
if _, err := p.Run(); err != nil {
3844
fmt.Printf("Alas, there's been an error: %v", err)
3945
os.Exit(1)

cmd/style.go

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,26 @@
1818
package cmd
1919

2020
import (
21-
"github.com/charmbracelet/bubbles/table"
2221
"github.com/charmbracelet/lipgloss"
2322
)
2423

2524
// styling for cli outputs
2625
var (
27-
selectedStyle = lipgloss.NewStyle().
28-
Foreground(lipgloss.AdaptiveColor{Light: "4", Dark: "11"}).Bold(true)
26+
FocusPrimary = lipgloss.AdaptiveColor{Light: "16", Dark: "226"}
27+
FocusSecondry = lipgloss.AdaptiveColor{Light: "18", Dark: "220"}
28+
29+
standardPrimary = lipgloss.AdaptiveColor{Light: "235", Dark: "255"}
30+
standardSecondry = lipgloss.AdaptiveColor{Light: "238", Dark: "254"}
31+
32+
standardStyle = lipgloss.NewStyle().Foreground(standardPrimary)
33+
standardStyleBold = lipgloss.NewStyle().Foreground(standardPrimary).Bold(true)
34+
standardStyleAlt = lipgloss.NewStyle().Foreground(standardSecondry)
35+
36+
selectedStyle = lipgloss.NewStyle().Foreground(FocusPrimary).Bold(true)
37+
selectedStyleAlt = lipgloss.NewStyle().Foreground(FocusSecondry)
38+
39+
selectedItemOuter = lipgloss.NewStyle().BorderStyle(lipgloss.NormalBorder()).BorderLeft(true).PaddingLeft(1).BorderForeground(FocusPrimary)
40+
itemOuter = lipgloss.NewStyle().PaddingLeft(1)
41+
2942
styleBold = lipgloss.NewStyle().Bold(true)
3043
)
31-
32-
func listingTableStyle() table.Styles {
33-
s := table.DefaultStyles()
34-
s.Header = s.Header.Border(lipgloss.NormalBorder(), false, false, true, false)
35-
s.Selected = selectedStyle
36-
return s
37-
}

cmd/user.go

Lines changed: 83 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,44 @@ import (
2121
"encoding/json"
2222
"fmt"
2323
"io"
24+
"net/http"
25+
"pb/pkg/config"
26+
"strings"
27+
"sync"
2428

2529
"github.com/spf13/cobra"
2630
)
2731

32+
type UserRoleData struct {
33+
Privilege string `json:"privilege"`
34+
Resource struct {
35+
Stream string `json:"stream"`
36+
Tag string `json:"tag"`
37+
} `json:"resource"`
38+
}
39+
40+
func (user *UserRoleData) Render() string {
41+
var s strings.Builder
42+
s.WriteString(standardStyle.Render(user.Privilege))
43+
44+
if user.Resource.Stream != "" {
45+
s.WriteString(" - ")
46+
s.WriteString(standardStyleAlt.Render(user.Resource.Stream))
47+
}
48+
if user.Resource.Tag != "" {
49+
s.WriteString(" ( ")
50+
s.WriteString(standardStyleAlt.Render(user.Resource.Tag))
51+
s.WriteString(" )")
52+
}
53+
54+
return s.String()
55+
}
56+
57+
type FetchUserRoleRes struct {
58+
data []UserRoleData
59+
err error
60+
}
61+
2862
var AddUserCmd = &cobra.Command{
2963
Use: "add name",
3064
Example: "add bob",
@@ -117,14 +151,38 @@ var ListUserCmd = &cobra.Command{
117151
defer resp.Body.Close()
118152

119153
if resp.StatusCode == 200 {
120-
items := []string{}
121-
err = json.Unmarshal(bytes, &items)
154+
users := []string{}
155+
err = json.Unmarshal(bytes, &users)
122156
if err != nil {
123157
return err
124158
}
125-
for _, item := range items {
126-
fmt.Println(item)
159+
160+
client = DefaultClient()
161+
role_responses := make([]FetchUserRoleRes, len(users))
162+
163+
wsg := sync.WaitGroup{}
164+
wsg.Add(len(users))
165+
for idx, user := range users {
166+
idx := idx
167+
user := user
168+
go func() {
169+
role_responses[idx] = fetchUserRoles(&client.client, &DefaultProfile, user)
170+
wsg.Done()
171+
}()
172+
}
173+
wsg.Wait()
174+
fmt.Println()
175+
for idx, user := range users {
176+
roles := role_responses[idx]
177+
fmt.Println(standardStyleBold.Bold(true).Render(user))
178+
if roles.err == nil {
179+
for _, role := range roles.data {
180+
fmt.Printf(" %s\n", role.Render())
181+
}
182+
}
183+
println()
127184
}
185+
128186
} else {
129187
body := string(bytes)
130188
fmt.Printf("Request Failed\nStatus Code: %s\nResponse: %s\n", resp.Status, body)
@@ -133,3 +191,24 @@ var ListUserCmd = &cobra.Command{
133191
return nil
134192
},
135193
}
194+
195+
func fetchUserRoles(client *http.Client, profile *config.Profile, user string) (res FetchUserRoleRes) {
196+
endpoint := fmt.Sprintf("%s/%s", profile.Url, fmt.Sprintf("api/v1/user/%s/role", user))
197+
req, err := http.NewRequest("GET", endpoint, nil)
198+
if err != nil {
199+
return
200+
}
201+
req.SetBasicAuth(profile.Username, profile.Password)
202+
resp, err := client.Do(req)
203+
if err != nil {
204+
return
205+
}
206+
body, err := io.ReadAll(resp.Body)
207+
if err != nil {
208+
return
209+
}
210+
defer resp.Body.Close()
211+
212+
res.err = json.Unmarshal(body, &res.data)
213+
return
214+
}

pkg/model/help.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package model
2+
3+
import (
4+
"github.com/charmbracelet/bubbles/key"
5+
)
6+
7+
type TableKeyMap struct {
8+
Up key.Binding
9+
Down key.Binding
10+
PageUp key.Binding
11+
PageDown key.Binding
12+
ScrollRight key.Binding
13+
ScrollLeft key.Binding
14+
Filter key.Binding
15+
ClearFilter key.Binding
16+
}
17+
18+
// ShortHelp returns keybindings to be shown in the mini help view. It's part
19+
// of the key.Map interface.
20+
func (k TableKeyMap) ShortHelp() []key.Binding {
21+
return []key.Binding{k.ScrollRight, k.ScrollRight, k.Filter, k.ClearFilter}
22+
}
23+
24+
// FullHelp returns keybindings for the expanded help view. It's part of the
25+
// key.Map interface.
26+
func (k TableKeyMap) FullHelp() [][]key.Binding {
27+
return [][]key.Binding{
28+
{k.Up, k.Down, k.PageUp, k.PageDown}, // first column
29+
{k.ScrollLeft, k.ScrollRight},
30+
{k.ClearFilter, k.Filter}, // second column
31+
}
32+
}
33+
34+
var tableKeys = TableKeyMap{
35+
Up: key.NewBinding(
36+
key.WithKeys("up", "k"),
37+
key.WithHelp("↑/k", "move up"),
38+
),
39+
Down: key.NewBinding(
40+
key.WithKeys("down", "j"),
41+
key.WithHelp("↓/j", "move down"),
42+
),
43+
PageUp: key.NewBinding(
44+
key.WithKeys("right", "l", "pgdown"),
45+
key.WithHelp("→/l", "prev page"),
46+
),
47+
PageDown: key.NewBinding(
48+
key.WithKeys("left", "h", "pgup"),
49+
key.WithHelp("←/h", "next page"),
50+
),
51+
ScrollLeft: key.NewBinding(
52+
key.WithKeys("shift+left", "shift+h"),
53+
key.WithHelp("shift ←/h", "scroll left"),
54+
),
55+
ScrollRight: key.NewBinding(
56+
key.WithKeys("shift+right", "shift+l"),
57+
key.WithHelp("shift →/l", "scroll right"),
58+
),
59+
Filter: key.NewBinding(
60+
key.WithKeys("/"),
61+
key.WithHelp("/ .. <enter>", "Filter"),
62+
),
63+
ClearFilter: key.NewBinding(
64+
key.WithKeys("esc"),
65+
key.WithHelp("esc", "remove filter"),
66+
),
67+
}

0 commit comments

Comments
 (0)