From 801958386c9c0cd39901098c2bbcd7948b59a2e9 Mon Sep 17 00:00:00 2001 From: Rustam Gilyazov <16064414+rusq@users.noreply.github.com> Date: Mon, 4 Nov 2024 19:07:57 +1000 Subject: [PATCH] search wiz + workspace select fixes --- cmd/slackdump/internal/archive/search.go | 8 +- .../internal/archive/search_wizard.go | 110 +++++++++++++++++- cmd/slackdump/internal/ui/dumpui/dumpui.go | 33 ++++-- cmd/slackdump/internal/ui/dumpui/model.go | 11 +- cmd/slackdump/internal/ui/theme.go | 2 +- cmd/slackdump/internal/wizard/wizard.go | 2 +- cmd/slackdump/internal/workspace/wizard.go | 19 +-- go.mod | 2 +- go.sum | 2 + 9 files changed, 153 insertions(+), 36 deletions(-) diff --git a/cmd/slackdump/internal/archive/search.go b/cmd/slackdump/internal/archive/search.go index 5683ffcb..da7247e7 100644 --- a/cmd/slackdump/internal/archive/search.go +++ b/cmd/slackdump/internal/archive/search.go @@ -17,9 +17,11 @@ import ( ) var CmdSearch = &base.Command{ - UsageLine: "slackdump search", - Short: "dump search results", - Long: `Searches for messages matching criteria.`, + UsageLine: "slackdump search", + Short: "dump search results", + Long: `Searches for messages matching criteria.`, + Wizard: wizSearch, + RequireAuth: true, Commands: []*base.Command{ cmdSearchMessages, cmdSearchFiles, diff --git a/cmd/slackdump/internal/archive/search_wizard.go b/cmd/slackdump/internal/archive/search_wizard.go index 1c8bb23d..6868b946 100644 --- a/cmd/slackdump/internal/archive/search_wizard.go +++ b/cmd/slackdump/internal/archive/search_wizard.go @@ -2,17 +2,117 @@ package archive import ( "context" + "errors" + "strings" + "github.com/charmbracelet/huh" "github.com/rusq/slackdump/v3/cmd/slackdump/internal/golang/base" + "github.com/rusq/slackdump/v3/cmd/slackdump/internal/ui/cfgui" "github.com/rusq/slackdump/v3/cmd/slackdump/internal/ui/dumpui" + "github.com/rusq/slackdump/v3/cmd/slackdump/internal/ui/updaters" ) -func SearchWizard(ctx context.Context, cmd *base.Command, args []string) error { +func wizSearch(ctx context.Context, cmd *base.Command, args []string) error { w := &dumpui.Wizard{ - Title: "Dump Search Results", - Name: "Search", - Cmd: cmdSearchAll, + Title: "Archive Search Results", + Name: "Search", + Cmd: adapterCmd, + LocalConfig: searchCfg, + ArgsFn: func() []string { + return append([]string{action}, strings.Split(terms, " ")...) + }, + ValidateParamsFn: func() error { + if action == "" { + return errors.New("select action") + } + if len(terms) == 0 { + return errors.New("search terms are not specified") + } + return nil + }, } - return w.Run(ctx) } + +const ( + acMessages = "messages" + acFiles = "files" + acAll = "all" +) + +var ( + action string = acMessages + terms string +) + +func searchCfg() cfgui.Configuration { + return cfgui.Configuration{ + cfgui.ParamGroup{ + Name: "Required", + Params: []cfgui.Parameter{ + { + Name: "Search Terms", + Description: "Enter your search query.", + Value: terms, + Inline: true, + Updater: updaters.NewString(&terms, "Search...", false, huh.ValidateNotEmpty()), + }, + }, + }, + cfgui.ParamGroup{ + Name: "Other parameters", + Params: []cfgui.Parameter{ + + { + Name: "Scope", + Description: "Choose the search scope.", + Value: action, + Inline: false, + Updater: updaters.NewPicklist(&action, huh.NewSelect[string]().Options( + huh.NewOption("messages", acMessages), + huh.NewOption("files", acFiles), + huh.NewOption("all", acAll), + ).DescriptionFunc(func() string { + switch action { + case acMessages: + return "Search only in messages" + case acFiles: + return "Search only in files" + case acAll: + return "Search in both messages and in files" + default: + return "undefined search action" + } + }, &action)), + }, + }, + }, + } +} + +var adapterCmd = &base.Command{ + Run: adaptercmd, +} + +func adaptercmd(ctx context.Context, _ *base.Command, args []string) error { + if len(args) < 1 { + panic("internal error: empty arguments") + } + if len(args) < 2 { + return errors.New("no search terms") + } + aCmd := args[0] + var cmd *base.Command + switch aCmd { + case acMessages: + cmd = cmdSearchMessages + case acFiles: + cmd = cmdSearchFiles + case acAll: + cmd = cmdSearchAll + default: + return errors.New("invalid adapter command") + } + + return cmd.Run(ctx, cmd, args[1:]) +} diff --git a/cmd/slackdump/internal/ui/dumpui/dumpui.go b/cmd/slackdump/internal/ui/dumpui/dumpui.go index 9e9b0679..08ec98b6 100644 --- a/cmd/slackdump/internal/ui/dumpui/dumpui.go +++ b/cmd/slackdump/internal/ui/dumpui/dumpui.go @@ -23,6 +23,8 @@ type Wizard struct { ValidateParamsFn func() error // Cmd is the command to run. Cmd *base.Command + // Help is the markdown help text. + Help string } const ( @@ -41,8 +43,19 @@ var description = map[string]string{ func (w *Wizard) Run(ctx context.Context) error { var menu = func() *Model { - items := []MenuItem{ - { + var items []MenuItem + if w.LocalConfig != nil { + items = append(items, MenuItem{ + ID: actLocalConfig, + Name: "Configure " + w.Name + "...", + Help: description[actLocalConfig], + Model: cfgui.NewConfigUI(cfgui.DefaultStyle(), w.LocalConfig), + }) + } + + items = append( + items, + MenuItem{ ID: actRun, Name: "Run " + w.Name, Help: description[actRun], @@ -53,17 +66,17 @@ func (w *Wizard) Run(ctx context.Context) error { return nil }, }, - } - if w.LocalConfig != nil { + ) + if w.Help != "" { items = append(items, MenuItem{ - ID: actLocalConfig, - Name: w.Name + " Configuration...", - Help: description[actLocalConfig], - Model: cfgui.NewConfigUI(cfgui.DefaultStyle(), w.LocalConfig), + ID: "help", + Name: "Help", + Help: "Read help for " + w.Name, }) } - items = append( - items, + + items = append(items, + MenuItem{Separator: true}, MenuItem{ ID: actGlobalConfig, Name: "Global Configuration...", diff --git a/cmd/slackdump/internal/ui/dumpui/model.go b/cmd/slackdump/internal/ui/dumpui/model.go index d2a34679..324055b5 100644 --- a/cmd/slackdump/internal/ui/dumpui/model.go +++ b/cmd/slackdump/internal/ui/dumpui/model.go @@ -139,6 +139,13 @@ func (m *Model) View() string { return m.view() } +func capfirst(s string) string { + if s == "" { + return "" + } + return strings.ToUpper(s[:1]) + s[1:] +} + func (m *Model) view() string { var b strings.Builder @@ -154,7 +161,7 @@ func (m *Model) view() string { // Header p(sty.Title.Render(m.title) + "\n") if currentDisabled { - p(sty.Description.Render(currentItem.Validate().Error())) + p(sty.Description.Render("Requirements not met: " + capfirst(currentItem.Validate().Error()))) } else { p(sty.Description.Render(m.items[m.cursor].Help)) } @@ -183,7 +190,7 @@ func (m *Model) view() string { sty.Item.Render(padding+itm.Name), )) } - b.WriteString("\n" + m.footer()) + p("\n" + m.footer()) return sty.Border.Render(b.String()) } diff --git a/cmd/slackdump/internal/ui/theme.go b/cmd/slackdump/internal/ui/theme.go index 647e5d89..402495b6 100644 --- a/cmd/slackdump/internal/ui/theme.go +++ b/cmd/slackdump/internal/ui/theme.go @@ -82,7 +82,7 @@ func DefaultTheme() Theme { Name: lipgloss.NewStyle().Foreground(green), EnabledValue: lipgloss.NewStyle().Foreground(white), DisabledValue: lipgloss.NewStyle().Foreground(green), - SelectedName: lipgloss.NewStyle().Foreground(black).Underline(true).Background(green), + SelectedName: lipgloss.NewStyle().Foreground(black).Background(green), }, }, Blurred: ControlStyle{ diff --git a/cmd/slackdump/internal/wizard/wizard.go b/cmd/slackdump/internal/wizard/wizard.go index 4a16cbfd..29674e0d 100644 --- a/cmd/slackdump/internal/wizard/wizard.go +++ b/cmd/slackdump/internal/wizard/wizard.go @@ -108,7 +108,7 @@ func makeMenu(cmds []*base.Command, parent string, title string) (m *menu) { Description: cmd.Short, cmd: cmd, } - if len(cmd.Commands) > 0 { + if hasSubcommands && !hasWizard { item.Submenu = makeMenu(cmd.Commands, name, name) } diff --git a/cmd/slackdump/internal/workspace/wizard.go b/cmd/slackdump/internal/workspace/wizard.go index a6bac54f..7602eab2 100644 --- a/cmd/slackdump/internal/workspace/wizard.go +++ b/cmd/slackdump/internal/workspace/wizard.go @@ -6,7 +6,6 @@ import ( "github.com/charmbracelet/bubbles/table" tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" "github.com/rusq/slackdump/v3/cmd/slackdump/internal/cfg" "github.com/rusq/slackdump/v3/cmd/slackdump/internal/golang/base" "github.com/rusq/slackdump/v3/cmd/slackdump/internal/ui" @@ -54,19 +53,13 @@ func WorkspaceSelectModel(ctx context.Context, m *cache.Manager) (tea.Model, err table.WithHeight(7), ) - s := table.DefaultStyles() - s.Header = s.Header. - BorderStyle(lipgloss.NormalBorder()). - Foreground(ui.HuhTheme.Focused.NoteTitle.GetForeground()). - BorderForeground(lipgloss.Color("240")). - BorderBottom(true). - Bold(false) - s.Selected = s.Selected. - Foreground(ui.HuhTheme.Focused.Option.GetBackground()). - Background(ui.HuhTheme.Focused.SelectedOption.GetForeground()). - Bold(false) + s := table.Styles{ + Header: ui.DefaultTheme().Focused.Title.Padding(0, 1), + Selected: ui.DefaultTheme().Focused.SelectedLine.Bold(true), + Cell: ui.DefaultTheme().Focused.Text.Padding(0, 1), + } t.SetStyles(s) - + t.Focus() return selectModel{table: t}, nil } diff --git a/go.mod b/go.mod index 039e1681..fdb716a0 100644 --- a/go.mod +++ b/go.mod @@ -27,7 +27,7 @@ require ( github.com/rusq/fsadapter v1.0.2 github.com/rusq/osenv/v2 v2.0.1 github.com/rusq/rbubbles v0.0.2 - github.com/rusq/slack v0.9.6-0.20240712095442-5a0e2e405a99 + github.com/rusq/slack v0.9.6-0.20241104074952-d9b6e02955fa github.com/rusq/slackauth v0.5.1 github.com/rusq/tagops v0.0.2 github.com/rusq/tracer v1.0.1 diff --git a/go.sum b/go.sum index 0703517b..a4b9f241 100644 --- a/go.sum +++ b/go.sum @@ -133,6 +133,8 @@ github.com/rusq/secure v0.0.4 h1:svpiZHfHnx89eEDCCFI9OXG1Y8hL9kUWUG6fJbrWUOI= github.com/rusq/secure v0.0.4/go.mod h1:F1QilMKreuFRjov0UY7DZSIXn77/8RqMVGu2zV0RtqY= github.com/rusq/slack v0.9.6-0.20240712095442-5a0e2e405a99 h1:dqEcNs9hMc2PiMwhw8+Zi3wF8GNUHIK5OItZ01iM0Vk= github.com/rusq/slack v0.9.6-0.20240712095442-5a0e2e405a99/go.mod h1:9O0zQAFN6W47z4KpTQbe6vOHOzBO76vMg1+gthPwaTI= +github.com/rusq/slack v0.9.6-0.20241104074952-d9b6e02955fa h1:meNaDH2eLwjAqvOxMlgb5+gaLz3Kufm9rVFkALhsCRs= +github.com/rusq/slack v0.9.6-0.20241104074952-d9b6e02955fa/go.mod h1:9O0zQAFN6W47z4KpTQbe6vOHOzBO76vMg1+gthPwaTI= github.com/rusq/slackauth v0.5.1 h1:l+Gj96kYzHmljMYglRv76kgzuOJr/QbXDDA8JHyN71Q= github.com/rusq/slackauth v0.5.1/go.mod h1:wAtNCbeKH0pnaZnqJjG5RKY3e5BF9F2L/YTzhOjBIb0= github.com/rusq/tagops v0.0.2 h1:LkWsmpYSH5Q5IX3pv0Qm5PEKOtfjKqrwbJ3c19C1pvM=