-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: create prod-ready quickstart command #75
Changes from 2 commits
92ac46b
e9fcc4f
4ba9898
92bdec7
b49e59c
5a8cc44
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package cmd | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
"os" | ||
|
||
tea "github.com/charmbracelet/bubbletea" | ||
"github.com/spf13/cobra" | ||
|
||
"ldcli/internal/flags" | ||
"ldcli/internal/quickstart" | ||
) | ||
|
||
func NewQuickStartCmd(client flags.Client) *cobra.Command { | ||
return &cobra.Command{ | ||
Long: "", | ||
RunE: runQuickStart(client), | ||
Short: "Setup guide to create your first feature flag", | ||
Use: "setup", | ||
} | ||
} | ||
|
||
func runQuickStart(client flags.Client) func(*cobra.Command, []string) error { | ||
return func(cmd *cobra.Command, args []string) error { | ||
f, err := tea.LogToFile("debug.log", "") | ||
if err != nil { | ||
fmt.Println("could not open file for debugging:", err) | ||
os.Exit(1) | ||
} | ||
defer f.Close() | ||
|
||
_, err = tea.NewProgram(quickstart.NewContainerModel(client)).Run() | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
return nil | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,7 +12,7 @@ import ( | |
) | ||
|
||
var setupCmd = &cobra.Command{ | ||
Use: "setup", | ||
Use: "setup-TOREMOVE", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can keep this in so we can run the two setups in parallel for comparison until the new one is done. |
||
Short: "Setup guide to create your first feature flag", | ||
Long: "", | ||
RunE: runSetup, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
package quickstart | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/charmbracelet/bubbles/key" | ||
tea "github.com/charmbracelet/bubbletea" | ||
"github.com/charmbracelet/lipgloss" | ||
|
||
"ldcli/internal/flags" | ||
) | ||
|
||
// step is an identifier for each step in the quick-start flow. | ||
type step int | ||
|
||
const ( | ||
createFlagStep step = iota | ||
) | ||
|
||
// ContainerModel is a high level container model that controls the nested models which each | ||
// represent a step in the quick-start flow. | ||
type ContainerModel struct { | ||
currentStep step | ||
err error | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We'll use these from the model that creates the flag so we can display them later. |
||
flagKey string | ||
flagsClient flags.Client | ||
quitting bool | ||
steps []tea.Model | ||
} | ||
|
||
func NewContainerModel(flagsClient flags.Client) tea.Model { | ||
return ContainerModel{ | ||
currentStep: createFlagStep, | ||
flagsClient: flagsClient, | ||
steps: []tea.Model{}, | ||
} | ||
} | ||
|
||
func (m ContainerModel) Init() tea.Cmd { | ||
return nil | ||
} | ||
|
||
func (m ContainerModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { | ||
switch msg := msg.(type) { | ||
case tea.KeyMsg: | ||
switch { | ||
case key.Matches(msg, keys.Enter): | ||
switch m.currentStep { | ||
case createFlagStep: | ||
// TODO: add createFlagModel | ||
default: | ||
} | ||
case key.Matches(msg, keys.Quit): | ||
m.quitting = true | ||
|
||
return m, tea.Quit | ||
default: | ||
// delegate all other input to the current model | ||
|
||
// TODO: update model once there is at least one | ||
// updated, _ := m.steps[m.currentStep].Update(msg) | ||
// m.steps[m.currentStep] = updated | ||
} | ||
default: | ||
} | ||
|
||
return m, nil | ||
} | ||
|
||
func (m ContainerModel) View() string { | ||
if m.quitting { | ||
return "" | ||
} | ||
|
||
if m.err != nil { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was trivial enough to add. Another ticket will make it look nice. |
||
return lipgloss. | ||
NewStyle(). | ||
Foreground(lipgloss.Color("#eb4034")). | ||
SetString(m.err.Error()). | ||
Render() | ||
} | ||
|
||
// TODO: remove after creating more steps | ||
if m.currentStep > createFlagStep { | ||
return fmt.Sprintf("created flag %s", m.flagKey) | ||
} | ||
|
||
return fmt.Sprintf("\nStep %d of %d\n"+m.steps[m.currentStep].View(), m.currentStep+1, len(m.steps)) | ||
} | ||
|
||
type keyMap struct { | ||
Enter key.Binding | ||
Quit key.Binding | ||
} | ||
|
||
var keys = keyMap{ | ||
Enter: key.NewBinding( | ||
key.WithKeys("enter"), | ||
key.WithHelp("enter", "select"), | ||
), | ||
Quit: key.NewBinding( | ||
key.WithKeys("ctrl+c"), | ||
key.WithHelp("q", "quit"), | ||
), | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I created a ticket to set up configurable logging.