From 501c03403b733b566d3442da9492592a542a2bca Mon Sep 17 00:00:00 2001 From: HashMapsData2Value <83883690+HashMapsData2Value@users.noreply.github.com> Date: Wed, 30 Oct 2024 15:35:33 +0100 Subject: [PATCH 1/8] feat: modal --- ui/pages/keys/cmds.go | 8 ++++++++ ui/pages/keys/controller.go | 22 ++++++++++++++++++++-- ui/pages/keys/model.go | 4 ++++ ui/pages/keys/view.go | 37 ++++++++++++++++++++++++++++++++++++- ui/viewport.go | 14 ++++++-------- 5 files changed, 74 insertions(+), 11 deletions(-) diff --git a/ui/pages/keys/cmds.go b/ui/pages/keys/cmds.go index 167c356..c44f86f 100644 --- a/ui/pages/keys/cmds.go +++ b/ui/pages/keys/cmds.go @@ -7,12 +7,20 @@ import ( type DeleteKey *api.ParticipationKey +type DeleteFinished string + func EmitDeleteKey(key *api.ParticipationKey) tea.Cmd { return func() tea.Msg { return DeleteKey(key) } } +func EmitKeyDeleted() tea.Cmd { + return func() tea.Msg { + return DeleteFinished("Key deleted") + } +} + // EmitKeySelected waits for and retrieves a new set of table rows from a given channel. func EmitKeySelected(key *api.ParticipationKey) tea.Cmd { return func() tea.Msg { diff --git a/ui/pages/keys/controller.go b/ui/pages/keys/controller.go index 7f406f3..edfcb93 100644 --- a/ui/pages/keys/controller.go +++ b/ui/pages/keys/controller.go @@ -23,15 +23,33 @@ func (m ViewModel) HandleMessage(msg tea.Msg) (ViewModel, tea.Cmd) { case internal.Account: m.Address = msg.Address m.table.SetRows(m.makeRows(m.Data)) + case DeleteFinished: + m.SelectedKeyToDelete = nil + m.DeleteLoading = false case tea.KeyMsg: switch msg.String() { case "enter": return m, EmitKeySelected(m.SelectedKey()) case "g": // TODO: navigation - case "d": - return m, EmitDeleteKey(m.SelectedKey()) + if m.SelectedKeyToDelete == nil { + m.SelectedKeyToDelete = m.SelectedKey() + } else { + m.SelectedKeyToDelete = nil + } + return m, nil + case "y": // "Yes do delete" option in the delete confirmation modal + if m.SelectedKeyToDelete != nil { + m.DeleteLoading = true // show loading spinner + return m, EmitDeleteKey(m.SelectedKeyToDelete) + } + return m, nil + case "n": // "do NOT delete" option in the delete confirmation modal + if m.SelectedKeyToDelete != nil { + m.SelectedKeyToDelete = nil + } + return m, nil case "ctrl+c": return m, tea.Quit } diff --git a/ui/pages/keys/model.go b/ui/pages/keys/model.go index 7bf8580..ba96438 100644 --- a/ui/pages/keys/model.go +++ b/ui/pages/keys/model.go @@ -17,6 +17,10 @@ type ViewModel struct { Width int Height int + SelectedKeyToDelete *api.ParticipationKey + + DeleteLoading bool + table table.Model controls controls.Model } diff --git a/ui/pages/keys/view.go b/ui/pages/keys/view.go index f249f57..6c3bf97 100644 --- a/ui/pages/keys/view.go +++ b/ui/pages/keys/view.go @@ -1,10 +1,45 @@ package keys import ( + "fmt" + + "github.com/algorandfoundation/hack-tui/api" "github.com/algorandfoundation/hack-tui/ui/pages" + "github.com/charmbracelet/bubbles/spinner" "github.com/charmbracelet/lipgloss" ) func (m ViewModel) View() string { - return lipgloss.JoinVertical(lipgloss.Center, pages.Padding1(m.table.View()), m.controls.View()) + if m.SelectedKeyToDelete != nil { + return lipgloss.JoinVertical( + lipgloss.Center, + renderDeleteConfirmationModal(m.SelectedKeyToDelete, m.DeleteLoading), + m.controls.View(), + ) + } + return lipgloss.JoinVertical( + lipgloss.Center, + pages.Padding1(m.table.View()), + m.controls.View(), + ) +} + +func renderDeleteConfirmationModal(partKey *api.ParticipationKey, deleteLoading bool) string { + modalStyle := lipgloss.NewStyle(). + Width(60). + Height(7). + Align(lipgloss.Center). + Border(lipgloss.RoundedBorder()). + Padding(1, 2) + + var modalContent string + if deleteLoading { + s := spinner.New() + s.Spinner = spinner.Dot + modalContent = fmt.Sprintf("Deleting key...\n%s", s.View()) + } else { + modalContent = fmt.Sprintf("Are you sure you want to delete this key from your node?\nParticipation Key: %v\nAccount Address: %v\nPress either y (yes) or n (no).", partKey.Id, partKey.Address) + } + + return modalStyle.Render(modalContent) } diff --git a/ui/viewport.go b/ui/viewport.go index 02f07f7..24b9751 100644 --- a/ui/viewport.go +++ b/ui/viewport.go @@ -48,15 +48,13 @@ type ViewportViewModel struct { errorPage ErrorViewModel } -type DeleteFinished string - func DeleteKey(client *api.ClientWithResponses, key keys.DeleteKey) tea.Cmd { return func() tea.Msg { err := internal.DeletePartKey(context.Background(), client, key.Id) if err != nil { - return DeleteFinished(err.Error()) + return keys.DeleteFinished(err.Error()) } - return DeleteFinished("Key deleted") + return keys.DeleteFinished("Key deleted") } } @@ -96,8 +94,8 @@ func (m ViewportViewModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { m.page = KeysPage case keys.DeleteKey: return m, DeleteKey(m.client, msg) - case DeleteFinished: - // TODO + case keys.DeleteFinished: + return m, keys.EmitKeyDeleted() case tea.KeyMsg: switch msg.String() { // Tab Backwards @@ -128,12 +126,12 @@ func (m ViewportViewModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { // Navigate to the transaction page return m, keys.EmitKeySelected(m.keysPage.SelectedKey()) } + case "a": + m.page = AccountsPage case "g": m.generatePage.Inputs[0].SetValue(m.accountsPage.SelectedAccount().Address) m.page = GeneratePage return m, nil - case "a": - m.page = AccountsPage case "k": m.page = KeysPage return m, accounts.EmitAccountSelected(m.accountsPage.SelectedAccount()) From b8f4d0d4676bc5f8d76185d2417e4a1fbf76da53 Mon Sep 17 00:00:00 2001 From: HashMapsData2Value <83883690+HashMapsData2Value@users.noreply.github.com> Date: Thu, 31 Oct 2024 10:04:43 +0100 Subject: [PATCH 2/8] fix: simplifying --- ui/pages/keys/controller.go | 32 +++++++++++--------------------- ui/pages/keys/model.go | 6 ------ ui/viewport.go | 16 +++++++++++++++- 3 files changed, 26 insertions(+), 28 deletions(-) diff --git a/ui/pages/keys/controller.go b/ui/pages/keys/controller.go index f9fa48a..c8ae201 100644 --- a/ui/pages/keys/controller.go +++ b/ui/pages/keys/controller.go @@ -17,26 +17,13 @@ func (m ViewModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } // Removes a participation key from the list of keys -func removePartKeyByID(slice []api.ParticipationKey, id string) []api.ParticipationKey { - for i, item := range slice { +func removePartKeyByID(slice *[]api.ParticipationKey, id string) { + for i, item := range *slice { if item.Id == id { - return append(slice[:i], slice[i+1:]...) + *slice = append((*slice)[:i], (*slice)[i+1:]...) + return } } - return slice -} - -func isPartKeyInList(partKey api.ParticipationKey, keys []api.ParticipationKey) bool { - if len(keys) == 0 { - return false - } - - for _, key := range keys { - if key.Id == partKey.Id { - return true - } - } - return false } func (m ViewModel) HandleMessage(msg tea.Msg) (ViewModel, tea.Cmd) { @@ -48,7 +35,13 @@ func (m ViewModel) HandleMessage(msg tea.Msg) (ViewModel, tea.Cmd) { m.Address = msg.Address m.table.SetRows(m.makeRows(m.Data)) case DeleteFinished: + if m.SelectedKeyToDelete == nil { + panic("SelectedKeyToDelete is unexpectedly nil") + } + removePartKeyByID(m.Data, m.SelectedKeyToDelete.Id) + m.SelectedKeyToDelete = nil m.table.SetRows(m.makeRows(m.Data)) + case tea.KeyMsg: switch msg.String() { case "enter": @@ -64,10 +57,7 @@ func (m ViewModel) HandleMessage(msg tea.Msg) (ViewModel, tea.Cmd) { return m, nil case "y": // "Yes do delete" option in the delete confirmation modal if m.SelectedKeyToDelete != nil { - m.KeysInDeletion = append(m.KeysInDeletion, *m.SelectedKeyToDelete) - keyToDelete := m.SelectedKeyToDelete - m.SelectedKeyToDelete = nil - return m, EmitDeleteKey(keyToDelete) + return m, EmitDeleteKey(m.SelectedKeyToDelete) } return m, nil case "n": // "do NOT delete" option in the delete confirmation modal diff --git a/ui/pages/keys/model.go b/ui/pages/keys/model.go index d55f978..e3879de 100644 --- a/ui/pages/keys/model.go +++ b/ui/pages/keys/model.go @@ -18,7 +18,6 @@ type ViewModel struct { Height int SelectedKeyToDelete *api.ParticipationKey - KeysInDeletion []api.ParticipationKey table table.Model controls string @@ -102,11 +101,6 @@ func (m ViewModel) makeRows(keys *[]api.ParticipationKey) []table.Row { } for _, key := range *keys { if key.Address == m.Address { - - if isPartKeyInList(key, m.KeysInDeletion) { - continue - } - rows = append(rows, table.Row{ key.Id, key.Address, diff --git a/ui/viewport.go b/ui/viewport.go index 7b660cf..8e27358 100644 --- a/ui/viewport.go +++ b/ui/viewport.go @@ -58,6 +58,19 @@ func DeleteKey(client *api.ClientWithResponses, key keys.DeleteKey) tea.Cmd { } } +// Check if there are any participation keys available for the account +// Prevents navigation to the transaction page if there are no keys +func tGuard(m ViewportViewModel) bool { + if m.Data == nil || len(*m.Data.ParticipationKeys) == 0 { + panic("No participation keys available for this account. Please add a key first.") + errorMsg := "No participation keys available for this account. Please add a key first." + m.errorMsg = &errorMsg + return true + } + + return false +} + // Init is a no-op func (m ViewportViewModel) Init() tea.Cmd { return nil @@ -139,13 +152,14 @@ func (m ViewportViewModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case "t": m.page = TransactionPage // If there isn't a key already, select the first record for that account - if m.keysPage.SelectedKey() == nil && m.Data != nil { + if m.keysPage.SelectedKey() == nil { data := *m.Data.ParticipationKeys acct := m.accountsPage.SelectedAccount() for i, key := range data { if key.Address == acct.Address { return m, keys.EmitKeySelected(&data[i]) } + return m, nil } } // Navigate to the transaction page From cd692e0bbd981c218d9ea35f783a8268a5388cd4 Mon Sep 17 00:00:00 2001 From: HashMapsData2Value <83883690+HashMapsData2Value@users.noreply.github.com> Date: Thu, 31 Oct 2024 12:44:08 +0100 Subject: [PATCH 3/8] fix: no key found block t, tab and enter --- ui/pages/keys/controller.go | 6 +++++- ui/viewport.go | 30 ++++++++++++++++-------------- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/ui/pages/keys/controller.go b/ui/pages/keys/controller.go index c8ae201..91ebd60 100644 --- a/ui/pages/keys/controller.go +++ b/ui/pages/keys/controller.go @@ -45,7 +45,11 @@ func (m ViewModel) HandleMessage(msg tea.Msg) (ViewModel, tea.Cmd) { case tea.KeyMsg: switch msg.String() { case "enter": - return m, EmitKeySelected(m.SelectedKey()) + selKey := m.SelectedKey() + if selKey != nil { + return m, EmitKeySelected(selKey) + } + return m, nil case "g": // TODO: navigation case "d": diff --git a/ui/viewport.go b/ui/viewport.go index 8e27358..c45fdb4 100644 --- a/ui/viewport.go +++ b/ui/viewport.go @@ -131,15 +131,13 @@ func (m ViewportViewModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { return m, accounts.EmitAccountSelected(m.accountsPage.SelectedAccount()) } if m.page == KeysPage { - m.page = TransactionPage - // If there isn't a key already, select the first record - if m.keysPage.SelectedKey() == nil && m.Data != nil { - data := *m.Data.ParticipationKeys - return m, keys.EmitKeySelected(&data[0]) + selKey := m.keysPage.SelectedKey() + if selKey != nil { + m.page = TransactionPage + return m, keys.EmitKeySelected(selKey) } - // Navigate to the transaction page - return m, keys.EmitKeySelected(m.keysPage.SelectedKey()) } + return m, nil case "a": m.page = AccountsPage case "g": @@ -150,20 +148,24 @@ func (m ViewportViewModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { m.page = KeysPage return m, accounts.EmitAccountSelected(m.accountsPage.SelectedAccount()) case "t": - m.page = TransactionPage - // If there isn't a key already, select the first record for that account - if m.keysPage.SelectedKey() == nil { - data := *m.Data.ParticipationKeys + if m.page == AccountsPage { acct := m.accountsPage.SelectedAccount() + data := *m.Data.ParticipationKeys for i, key := range data { if key.Address == acct.Address { + m.page = TransactionPage return m, keys.EmitKeySelected(&data[i]) } - return m, nil } } - // Navigate to the transaction page - return m, keys.EmitKeySelected(m.keysPage.SelectedKey()) + if m.page == KeysPage { + selKey := m.keysPage.SelectedKey() + if selKey != nil { + m.page = TransactionPage + return m, keys.EmitKeySelected(selKey) + } + } + return m, nil case "ctrl+c": if m.page != GeneratePage { return m, tea.Quit From efe5d29383996ba7ecec3275256c01c97d35f711 Mon Sep 17 00:00:00 2001 From: HashMapsData2Value <83883690+HashMapsData2Value@users.noreply.github.com> Date: Thu, 31 Oct 2024 12:48:14 +0100 Subject: [PATCH 4/8] fix: remove unnecessary code --- ui/viewport.go | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/ui/viewport.go b/ui/viewport.go index c45fdb4..3b241b5 100644 --- a/ui/viewport.go +++ b/ui/viewport.go @@ -58,19 +58,6 @@ func DeleteKey(client *api.ClientWithResponses, key keys.DeleteKey) tea.Cmd { } } -// Check if there are any participation keys available for the account -// Prevents navigation to the transaction page if there are no keys -func tGuard(m ViewportViewModel) bool { - if m.Data == nil || len(*m.Data.ParticipationKeys) == 0 { - panic("No participation keys available for this account. Please add a key first.") - errorMsg := "No participation keys available for this account. Please add a key first." - m.errorMsg = &errorMsg - return true - } - - return false -} - // Init is a no-op func (m ViewportViewModel) Init() tea.Cmd { return nil From fc0f5596d0cc37ff55ef1942b1737c7883c8f4c6 Mon Sep 17 00:00:00 2001 From: HashMapsData2Value <83883690+HashMapsData2Value@users.noreply.github.com> Date: Thu, 31 Oct 2024 13:06:12 +0100 Subject: [PATCH 5/8] fix: prevent from entering empty keys page --- ui/pages/accounts/controller.go | 6 +++++- ui/viewport.go | 16 ++++++++++++---- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/ui/pages/accounts/controller.go b/ui/pages/accounts/controller.go index 434f0ea..139ee6d 100644 --- a/ui/pages/accounts/controller.go +++ b/ui/pages/accounts/controller.go @@ -26,7 +26,11 @@ func (m ViewModel) HandleMessage(msg tea.Msg) (ViewModel, tea.Cmd) { case tea.KeyMsg: switch msg.String() { case "enter": - return m, EmitAccountSelected(m.SelectedAccount()) + selAcc := m.SelectedAccount() + if selAcc != (internal.Account{}) { + return m, EmitAccountSelected(selAcc) + } + return m, nil case "ctrl+c": return m, tea.Quit } diff --git a/ui/viewport.go b/ui/viewport.go index 3b241b5..660c73c 100644 --- a/ui/viewport.go +++ b/ui/viewport.go @@ -114,8 +114,12 @@ func (m ViewportViewModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { // Tab Forwards case "tab": if m.page == AccountsPage { - m.page = KeysPage - return m, accounts.EmitAccountSelected(m.accountsPage.SelectedAccount()) + selAcc := m.accountsPage.SelectedAccount() + if selAcc != (internal.Account{}) { + m.page = KeysPage + return m, accounts.EmitAccountSelected(selAcc) + } + return m, nil } if m.page == KeysPage { selKey := m.keysPage.SelectedKey() @@ -132,8 +136,12 @@ func (m ViewportViewModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { m.page = GeneratePage return m, nil case "k": - m.page = KeysPage - return m, accounts.EmitAccountSelected(m.accountsPage.SelectedAccount()) + selAcc := m.accountsPage.SelectedAccount() + if selAcc != (internal.Account{}) { + m.page = KeysPage + return m, accounts.EmitAccountSelected(selAcc) + } + return m, nil case "t": if m.page == AccountsPage { acct := m.accountsPage.SelectedAccount() From fcce77546b2a71e3a56d0ddfeb7573c76607a75c Mon Sep 17 00:00:00 2001 From: HashMapsData2Value <83883690+HashMapsData2Value@users.noreply.github.com> Date: Thu, 31 Oct 2024 14:17:50 +0100 Subject: [PATCH 6/8] fix: move removePartKeyById into internal + add test --- internal/participation.go | 13 +++++++- internal/participation_test.go | 55 ++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/internal/participation.go b/internal/participation.go index 5a05c9a..29ef856 100644 --- a/internal/participation.go +++ b/internal/participation.go @@ -3,8 +3,9 @@ package internal import ( "context" "errors" - "github.com/algorandfoundation/hack-tui/api" "time" + + "github.com/algorandfoundation/hack-tui/api" ) // GetPartKeys get the participation keys from the node @@ -116,3 +117,13 @@ func DeletePartKey(ctx context.Context, client *api.ClientWithResponses, partici } return nil } + +// Removes a participation key from the list of keys +func RemovePartKeyByID(slice *[]api.ParticipationKey, id string) { + for i, item := range *slice { + if item.Id == id { + *slice = append((*slice)[:i], (*slice)[i+1:]...) + return + } + } +} diff --git a/internal/participation_test.go b/internal/participation_test.go index 69038da..2588366 100644 --- a/internal/participation_test.go +++ b/internal/participation_test.go @@ -146,3 +146,58 @@ func Test_DeleteParticipationKey(t *testing.T) { t.Fatal(err) } } +func Test_RemovePartKeyByID(t *testing.T) { + // Test case: Remove an existing key + t.Run("Remove existing key", func(t *testing.T) { + keys := []api.ParticipationKey{ + {Id: "key1"}, + {Id: "key2"}, + {Id: "key3"}, + } + expectedKeys := []api.ParticipationKey{ + {Id: "key1"}, + {Id: "key3"}, + } + RemovePartKeyByID(&keys, "key2") + if len(keys) != len(expectedKeys) { + t.Fatalf("expected %d keys, got %d", len(expectedKeys), len(keys)) + } + for i, key := range keys { + if key.Id != expectedKeys[i].Id { + t.Fatalf("expected key ID %s, got %s", expectedKeys[i].Id, key.Id) + } + } + }) + + // Test case: Remove a non-existing key + t.Run("Remove non-existing key", func(t *testing.T) { + keys := []api.ParticipationKey{ + {Id: "key1"}, + {Id: "key2"}, + {Id: "key3"}, + } + expectedKeys := []api.ParticipationKey{ + {Id: "key1"}, + {Id: "key2"}, + {Id: "key3"}, + } + RemovePartKeyByID(&keys, "key4") + if len(keys) != len(expectedKeys) { + t.Fatalf("expected %d keys, got %d", len(expectedKeys), len(keys)) + } + for i, key := range keys { + if key.Id != expectedKeys[i].Id { + t.Fatalf("expected key ID %s, got %s", expectedKeys[i].Id, key.Id) + } + } + }) + + // Test case: Remove a key from an empty list + t.Run("Remove key from empty list", func(t *testing.T) { + keys := []api.ParticipationKey{} + RemovePartKeyByID(&keys, "key1") + if len(keys) != 0 { + t.Fatalf("expected 0 keys, got %d", len(keys)) + } + }) +} From 724669755314786b8434a3c9e230cfd20ec5ae73 Mon Sep 17 00:00:00 2001 From: HashMapsData2Value <83883690+HashMapsData2Value@users.noreply.github.com> Date: Thu, 31 Oct 2024 14:19:46 +0100 Subject: [PATCH 7/8] fix: change import --- ui/pages/keys/cmds.go | 6 ------ ui/pages/keys/controller.go | 13 +------------ 2 files changed, 1 insertion(+), 18 deletions(-) diff --git a/ui/pages/keys/cmds.go b/ui/pages/keys/cmds.go index c44f86f..a8f89ec 100644 --- a/ui/pages/keys/cmds.go +++ b/ui/pages/keys/cmds.go @@ -15,12 +15,6 @@ func EmitDeleteKey(key *api.ParticipationKey) tea.Cmd { } } -func EmitKeyDeleted() tea.Cmd { - return func() tea.Msg { - return DeleteFinished("Key deleted") - } -} - // EmitKeySelected waits for and retrieves a new set of table rows from a given channel. func EmitKeySelected(key *api.ParticipationKey) tea.Cmd { return func() tea.Msg { diff --git a/ui/pages/keys/controller.go b/ui/pages/keys/controller.go index 91ebd60..22e242f 100644 --- a/ui/pages/keys/controller.go +++ b/ui/pages/keys/controller.go @@ -1,7 +1,6 @@ package keys import ( - "github.com/algorandfoundation/hack-tui/api" "github.com/algorandfoundation/hack-tui/internal" "github.com/algorandfoundation/hack-tui/ui/style" tea "github.com/charmbracelet/bubbletea" @@ -16,16 +15,6 @@ func (m ViewModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { return m.HandleMessage(msg) } -// Removes a participation key from the list of keys -func removePartKeyByID(slice *[]api.ParticipationKey, id string) { - for i, item := range *slice { - if item.Id == id { - *slice = append((*slice)[:i], (*slice)[i+1:]...) - return - } - } -} - func (m ViewModel) HandleMessage(msg tea.Msg) (ViewModel, tea.Cmd) { switch msg := msg.(type) { case internal.StateModel: @@ -38,7 +27,7 @@ func (m ViewModel) HandleMessage(msg tea.Msg) (ViewModel, tea.Cmd) { if m.SelectedKeyToDelete == nil { panic("SelectedKeyToDelete is unexpectedly nil") } - removePartKeyByID(m.Data, m.SelectedKeyToDelete.Id) + internal.RemovePartKeyByID(m.Data, m.SelectedKeyToDelete.Id) m.SelectedKeyToDelete = nil m.table.SetRows(m.makeRows(m.Data)) From 9298e09b089666f0e44c0ddf02fd3d0246139390 Mon Sep 17 00:00:00 2001 From: HashMapsData2Value <83883690+HashMapsData2Value@users.noreply.github.com> Date: Thu, 31 Oct 2024 15:31:55 +0100 Subject: [PATCH 8/8] fix: center --- ui/pages/keys/view.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/ui/pages/keys/view.go b/ui/pages/keys/view.go index 1d9e52b..8107e71 100644 --- a/ui/pages/keys/view.go +++ b/ui/pages/keys/view.go @@ -10,10 +10,9 @@ import ( func (m ViewModel) View() string { if m.SelectedKeyToDelete != nil { - return lipgloss.JoinVertical( - lipgloss.Center, - renderDeleteConfirmationModal(m.SelectedKeyToDelete), - ) + modal := renderDeleteConfirmationModal(m.SelectedKeyToDelete) + overlay := lipgloss.Place(m.Width, m.Height, lipgloss.Center, lipgloss.Center, modal) + return overlay } table := style.ApplyBorder(m.Width, m.Height, "8").Render(m.table.View()) return style.WithNavigation( @@ -38,5 +37,5 @@ func renderDeleteConfirmationModal(partKey *api.ParticipationKey) string { modalContent := fmt.Sprintf("Participation Key: %v\nAccount Address: %v\nPress either y (yes) or n (no).", partKey.Id, partKey.Address) - return modalStyle.Render("Are you sure you want to delete this key from your node?\n", modalContent) + return modalStyle.Render("Are you sure you want to delete this key from your node?\n" + modalContent) }