Skip to content

Commit

Permalink
feat(ui): ability to prompt a confirmation before an action is performed
Browse files Browse the repository at this point in the history
  • Loading branch information
orlandorode97 authored and dlvhdr committed Jul 24, 2023
1 parent 21a4668 commit 144d589
Show file tree
Hide file tree
Showing 6 changed files with 243 additions and 49 deletions.
2 changes: 1 addition & 1 deletion ui/common/styles.go
Expand Up @@ -8,7 +8,7 @@ import (
)

var (
SearchHeight = 3
SearchHeight = 4
FooterHeight = 1
ExpandedHelpHeight = 11
InputBoxHeight = 8
Expand Down
34 changes: 27 additions & 7 deletions ui/components/issuessection/issuessection.go
Expand Up @@ -4,7 +4,6 @@ import (
"fmt"
"time"

"github.com/charmbracelet/bubbles/key"
tea "github.com/charmbracelet/bubbletea"

"github.com/dlvhdr/gh-dash/config"
Expand All @@ -14,7 +13,6 @@ import (
"github.com/dlvhdr/gh-dash/ui/components/table"
"github.com/dlvhdr/gh-dash/ui/constants"
"github.com/dlvhdr/gh-dash/ui/context"
"github.com/dlvhdr/gh-dash/ui/keys"
"github.com/dlvhdr/gh-dash/utils"
)

Expand Down Expand Up @@ -72,13 +70,35 @@ func (m Model) Update(msg tea.Msg) (section.Section, tea.Cmd) {
break
}

switch {
case key.Matches(msg, keys.IssueKeys.Close):
cmd = m.close()
if m.IsPromptConfirmationFocused() {

case key.Matches(msg, keys.IssueKeys.Reopen):
cmd = m.reopen()
var promptCmd tea.Cmd
switch {

case msg.Type == tea.KeyCtrlC, msg.Type == tea.KeyEsc:
m.PromptConfirmationBox.Reset()
cmd = m.SetIsPromptConfirmationShown(false)
return &m, cmd

case msg.Type == tea.KeyEnter:
input := m.PromptConfirmationBox.Value()
action := m.GetPromptConfirmationAction()
if input == "Y" || input == "y" {
switch action {
case "close":
cmd = m.close()
case "reopen":
cmd = m.reopen()
}
}

m.PromptConfirmationBox.Reset()
blinkCmd := m.SetIsPromptConfirmationShown(false)

return &m, tea.Batch(cmd, blinkCmd)
}
m.PromptConfirmationBox, promptCmd = m.PromptConfirmationBox.Update(msg)
return &m, promptCmd
}

case UpdateIssueMsg:
Expand Down
62 changes: 62 additions & 0 deletions ui/components/prompt/prompt.go
@@ -0,0 +1,62 @@
package prompt

import (
"github.com/charmbracelet/bubbles/textinput"
tea "github.com/charmbracelet/bubbletea"
"github.com/dlvhdr/gh-dash/ui/context"
)

type Model struct {
ctx *context.ProgramContext
prompt textinput.Model
}

func NewModel(ctx *context.ProgramContext) Model {
ti := textinput.New()
ti.Focus()
ti.Blur()
ti.CursorStart()

return Model{
ctx: ctx,
prompt: ti,
}
}

func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
var cmd tea.Cmd
m.prompt, cmd = m.prompt.Update(msg)
return m, cmd
}

func (m Model) View() string {
return m.prompt.View()
}

func (m Model) Init() tea.Cmd {
return textinput.Blink
}

func (m *Model) Blur() {
m.prompt.Blur()
}

func (m *Model) Focus() tea.Cmd {
return m.prompt.Focus()
}

func (m *Model) SetValue(value string) {
m.prompt.SetValue(value)
}

func (m *Model) Value() string {
return m.prompt.Value()
}

func (m *Model) SetPrompt(prompt string) {
m.prompt.Prompt = prompt
}

func (m *Model) Reset() {
m.prompt.Reset()
}
47 changes: 34 additions & 13 deletions ui/components/prssection/prssection.go
Expand Up @@ -74,6 +74,40 @@ func (m Model) Update(msg tea.Msg) (section.Section, tea.Cmd) {
break
}

if m.IsPromptConfirmationFocused() {
var promptCmd tea.Cmd
switch {

case msg.Type == tea.KeyCtrlC, msg.Type == tea.KeyEsc:
m.PromptConfirmationBox.Reset()
cmd = m.SetIsPromptConfirmationShown(false)
return &m, cmd

case msg.Type == tea.KeyEnter:
input := m.PromptConfirmationBox.Value()
action := m.GetPromptConfirmationAction()
if input == "Y" || input == "y" {
switch action {
case "close":
cmd = m.close()
case "reopen":
cmd = m.reopen()
case "ready":
cmd = m.ready()
case "merge":
cmd = m.merge()
}
}

m.PromptConfirmationBox.Reset()
blinkCmd := m.SetIsPromptConfirmationShown(false)

return &m, tea.Batch(cmd, blinkCmd)
}
m.PromptConfirmationBox, promptCmd = m.PromptConfirmationBox.Update(msg)
return &m, promptCmd
}

switch {

case key.Matches(msg, keys.PRKeys.Diff):
Expand All @@ -84,19 +118,6 @@ func (m Model) Update(msg tea.Msg) (section.Section, tea.Cmd) {
if err != nil {
m.Ctx.Error = err
}

case key.Matches(msg, keys.PRKeys.Close):
cmd = m.close()

case key.Matches(msg, keys.PRKeys.Ready):
cmd = m.ready()

case key.Matches(msg, keys.PRKeys.Merge):
cmd = m.merge()

case key.Matches(msg, keys.PRKeys.Reopen):
cmd = m.reopen()

}

case UpdatePRMsg:
Expand Down
122 changes: 95 additions & 27 deletions ui/components/section/section.go
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/dlvhdr/gh-dash/config"
"github.com/dlvhdr/gh-dash/data"
"github.com/dlvhdr/gh-dash/ui/common"
"github.com/dlvhdr/gh-dash/ui/components/prompt"
"github.com/dlvhdr/gh-dash/ui/components/search"
"github.com/dlvhdr/gh-dash/ui/components/table"
"github.com/dlvhdr/gh-dash/ui/constants"
Expand All @@ -19,20 +20,23 @@ import (
)

type Model struct {
Id int
Config config.SectionConfig
Ctx *context.ProgramContext
Spinner spinner.Model
SearchBar search.Model
IsSearching bool
SearchValue string
Table table.Model
Type string
SingularForm string
PluralForm string
Columns []table.Column
TotalCount int
PageInfo *data.PageInfo
Id int
Config config.SectionConfig
Ctx *context.ProgramContext
Spinner spinner.Model
SearchBar search.Model
IsSearching bool
SearchValue string
Table table.Model
Type string
SingularForm string
PluralForm string
Columns []table.Column
TotalCount int
PageInfo *data.PageInfo
PromptConfirmationBox prompt.Model
IsPromptConfirmationShown bool
PromptConfirmationAction string
}

func NewModel(
Expand All @@ -45,19 +49,20 @@ func NewModel(
lastUpdated time.Time,
) Model {
m := Model{
Id: id,
Type: sType,
Config: cfg,
Ctx: ctx,
Spinner: spinner.Model{Spinner: spinner.Dot},
Columns: columns,
SingularForm: singular,
PluralForm: plural,
SearchBar: search.NewModel(sType, ctx, cfg.Filters),
SearchValue: cfg.Filters,
IsSearching: false,
TotalCount: 0,
PageInfo: nil,
Id: id,
Type: sType,
Config: cfg,
Ctx: ctx,
Spinner: spinner.Model{Spinner: spinner.Dot},
Columns: columns,
SingularForm: singular,
PluralForm: plural,
SearchBar: search.NewModel(sType, ctx, cfg.Filters),
SearchValue: cfg.Filters,
IsSearching: false,
TotalCount: 0,
PageInfo: nil,
PromptConfirmationBox: prompt.NewModel(ctx),
}
m.Table = table.NewModel(
*ctx,
Expand All @@ -81,6 +86,7 @@ type Section interface {
Component
Table
Search
PromptConfirmation
UpdateProgramContext(ctx *context.ProgramContext)
MakeSectionCmd(cmd tea.Cmd) tea.Cmd
LastUpdated() time.Time
Expand Down Expand Up @@ -121,6 +127,14 @@ type Search interface {
ResetPageInfo()
}

type PromptConfirmation interface {
SetIsPromptConfirmationShown(val bool) tea.Cmd
IsPromptConfirmationFocused() bool
SetPromptConfirmationAction(action string)
GetPromptConfirmationAction() string
GetPromptConfirmation() string
}

func (m *Model) CreateNextTickCmd(nextTickCmd tea.Cmd) tea.Cmd {
if m == nil || nextTickCmd == nil {
return nil
Expand Down Expand Up @@ -221,6 +235,29 @@ func (m *Model) ResetPageInfo() {
m.PageInfo = nil
}

func (m *Model) IsPromptConfirmationFocused() bool {
return m.IsPromptConfirmationShown
}

func (m *Model) SetIsPromptConfirmationShown(val bool) tea.Cmd {
m.IsPromptConfirmationShown = val
if val {
m.PromptConfirmationBox.Focus()
return m.PromptConfirmationBox.Init()
}

m.PromptConfirmationBox.Blur()
return nil
}

func (m *Model) SetPromptConfirmationAction(action string) {
m.PromptConfirmationAction = action
}

func (m *Model) GetPromptConfirmationAction() string {
return m.PromptConfirmationAction
}

type SectionMsg struct {
Id int
Type string
Expand Down Expand Up @@ -276,6 +313,7 @@ func (m *Model) View() string {
lipgloss.Left,
search,
m.GetMainContent(),
m.GetPromptConfirmation(),
),
)
}
Expand Down Expand Up @@ -308,3 +346,33 @@ func (m *Model) GetPagerContent() string {
pager := m.Ctx.Styles.ListViewPort.PagerStyle.Copy().Render(pagerContent)
return pager
}

func (m *Model) GetPromptConfirmation() string {
if m.IsPromptConfirmationShown {
var prompt string
switch {
case m.PromptConfirmationAction == "close" && m.Ctx.View == config.PRsView:
prompt = "Are you sure you want to close this PR? (Y/n) "

case m.PromptConfirmationAction == "reopen" && m.Ctx.View == config.PRsView:
prompt = "Are you sure you want to reopen this PR? (Y/n) "

case m.PromptConfirmationAction == "ready" && m.Ctx.View == config.PRsView:
prompt = "Are you sure you want to mark this PR as ready? (Y/n) "

case m.PromptConfirmationAction == "merge" && m.Ctx.View == config.PRsView:
prompt = "Are you sure you want to merge this PR? (Y/n) "

case m.PromptConfirmationAction == "close" && m.Ctx.View == config.IssuesView:
prompt = "Are you sure you want to close this issue? (Y/n) "

case m.PromptConfirmationAction == "reopen" && m.Ctx.View == config.IssuesView:
prompt = "Are you sure you want to reopen this issue? (Y/n) "
}
m.PromptConfirmationBox.SetPrompt(prompt)

return m.PromptConfirmationBox.View()
}

return ""
}

0 comments on commit 144d589

Please sign in to comment.