From 3496a580516ba6ca36af1a33c62bd891ca61e89b Mon Sep 17 00:00:00 2001 From: Kelly Hofmann <55991524+k3llymariee@users.noreply.github.com> Date: Mon, 18 Mar 2024 13:57:09 -0700 Subject: [PATCH] feat: select child resources based on parent key (#31) * add new text input mmodel * add new input step to project model, update wizard step to handle that update * add note about error handling; * remove debugging stmt * store projects in memory so we can mimic adding new ones * refetch projects if we go back to that step from environment step * make fetching resources more generic * fetch environments based on project selected * fetch flags based on environment selected --- internal/setup/environments.go | 52 ++++++++++++++++++---- internal/setup/flags.go | 81 +++++++++++++++++++++++++++++++--- internal/setup/projects.go | 9 ++-- internal/setup/wizard.go | 18 +++++++- 4 files changed, 139 insertions(+), 21 deletions(-) diff --git a/internal/setup/environments.go b/internal/setup/environments.go index 6cb977af..02b24f2c 100644 --- a/internal/setup/environments.go +++ b/internal/setup/environments.go @@ -26,13 +26,14 @@ type environment struct { func (p environment) FilterValue() string { return "" } type environmentModel struct { - choice string - err error - list list.Model + choice string + err error + list list.Model + parentKey string } -func NewEnvironment() tea.Model { - environments := []environment{ +var environments = map[string][]environment{ + "proj1": { { Key: "env1", Name: "environment 1", @@ -41,9 +42,38 @@ func NewEnvironment() tea.Model { Key: "env2", Name: "environment 2", }, - } + }, + "proj2": { + { + Key: "env3", + Name: "environment 3", + }, + { + Key: "env4", + Name: "environment 4", + }, + }, + "proj3": { + { + Key: "env5", + Name: "environment 5", + }, + { + Key: "env6", + Name: "environment 6", + }, + }, +} - l := list.New(environmentsToItems(environments), envDelegate{}, 30, 14) +func getEnvironments(projKey string) ([]environment, error) { + envList := environments[projKey] + createNewOption := environment{Key: CreateNewResourceKey, Name: "Create a new environment"} + envList = append(envList, createNewOption) + return envList, nil +} + +func NewEnvironment() tea.Model { + l := list.New(nil, envDelegate{}, 30, 14) l.Title = "Select an environment" l.SetShowStatusBar(false) l.SetFilteringEnabled(false) @@ -57,10 +87,16 @@ func (p environmentModel) Init() tea.Cmd { return nil } -// This method has drifted from the ProjectModel's version, but it should do something similar. func (m environmentModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { var cmd tea.Cmd switch msg := msg.(type) { + case fetchResources: + envs, err := getEnvironments(m.parentKey) + if err != nil { + m.err = err + return m, nil + } + m.list.SetItems(environmentsToItems(envs)) case tea.KeyMsg: switch { case key.Matches(msg, keys.Enter): diff --git a/internal/setup/flags.go b/internal/setup/flags.go index 2f90ad05..c5d2f175 100644 --- a/internal/setup/flags.go +++ b/internal/setup/flags.go @@ -26,13 +26,14 @@ type flag struct { func (p flag) FilterValue() string { return "" } type flagModel struct { - choice string - err error - list list.Model + choice string + err error + list list.Model + parentKey string } -func NewFlag() tea.Model { - flags := []flag{ +var flags = map[string][]flag{ + "env1": { { Key: "flag1", Name: "flag 1", @@ -41,9 +42,61 @@ func NewFlag() tea.Model { Key: "flag2", Name: "flag 2", }, - } + }, + "env2": { + { + Key: "flag3", + Name: "flag 3", + }, + { + Key: "flag4", + Name: "flag 4", + }, + }, + "env3": { + { + Key: "flag5", + Name: "flag 5", + }, + { + Key: "flag6", + Name: "flag 6", + }, + }, + "env4": { + { + Key: "flag7", + Name: "flag 7", + }, + { + Key: "flag8", + Name: "flag 8", + }, + }, + "env5": { + { + Key: "flag9", + Name: "flag 9", + }, + { + Key: "flag10", + Name: "flag 10", + }, + }, + "env6": { + { + Key: "flag11", + Name: "flag 11", + }, + { + Key: "flag12", + Name: "flag 12", + }, + }, +} - l := list.New(flagsToItems(flags), flagDelegate{}, 30, 14) +func NewFlag() tea.Model { + l := list.New(nil, flagDelegate{}, 30, 14) l.Title = "Select a flag" l.SetShowStatusBar(false) l.SetFilteringEnabled(false) @@ -61,6 +114,13 @@ func (p flagModel) Init() tea.Cmd { func (m flagModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { var cmd tea.Cmd switch msg := msg.(type) { + case fetchResources: + fs, err := getFlags(m.parentKey) + if err != nil { + m.err = err + return m, nil + } + m.list.SetItems(flagsToItems(fs)) case tea.KeyMsg: switch { case key.Matches(msg, keys.Enter): @@ -82,6 +142,13 @@ func (m flagModel) View() string { return "\n" + m.list.View() } +func getFlags(envKey string) ([]flag, error) { + flagList := flags[envKey] + createNewOption := flag{Key: CreateNewResourceKey, Name: "Create a new flag"} + flagList = append(flagList, createNewOption) + return flagList, nil +} + type flagDelegate struct{} func (d flagDelegate) Height() int { return 1 } diff --git a/internal/setup/projects.go b/internal/setup/projects.go index e01808bb..a9939321 100644 --- a/internal/setup/projects.go +++ b/internal/setup/projects.go @@ -11,6 +11,8 @@ import ( "github.com/charmbracelet/lipgloss" ) +const CreateNewResourceKey string = "create-new" + var ( projectStyle = lipgloss.NewStyle().PaddingLeft(4) selectedItemStyle = lipgloss.NewStyle().PaddingLeft(2).Foreground(lipgloss.Color("170")) @@ -50,14 +52,13 @@ func (p projectModel) Init() tea.Cmd { func (m projectModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { var cmd tea.Cmd - // if we've selected the option to create a new project, delegate to the textInput model if m.showInput { m.textInput, cmd = m.textInput.Update(msg) - - // catch the enter key here to update the projectModel when a final value is provided switch msg := msg.(type) { case tea.KeyMsg: switch { + // catch the enter key here to update the model when a final value is provided + // if we've selected the option to create a new project, delegate to the textInput model case key.Matches(msg, keys.Enter): iModel, ok := m.textInput.(inputModel) if ok { @@ -167,7 +168,7 @@ var projects = []project{ func getProjects() ([]project, error) { projectList := projects - createNewOption := project{Key: "create-new-project", Name: "Create a new project"} + createNewOption := project{Key: CreateNewResourceKey, Name: "Create a new project"} projectList = append(projectList, createNewOption) return projectList, nil diff --git a/internal/setup/wizard.go b/internal/setup/wizard.go index ef2dbb88..1e530fec 100644 --- a/internal/setup/wizard.go +++ b/internal/setup/wizard.go @@ -154,7 +154,14 @@ func (m WizardModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { m.steps[projectsStep] = p // only progress if we don't want to show input if !p.showInput { - m.currStep += 1 + // pre-load environments based on project selected + envModel := m.steps[environmentsStep] + e, ok := envModel.(environmentModel) + if ok { + e.parentKey = m.currProjectKey + m.steps[environmentsStep], _ = e.Update(fetchResources{}) + m.currStep += 1 + } } } case environmentsStep: @@ -162,7 +169,14 @@ func (m WizardModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { p, ok := envModel.(environmentModel) if ok { m.currEnvironmentKey = p.choice - m.currStep += 1 + // pre-load flags based on environment selected + fModel := m.steps[flagsStep] + f, ok := fModel.(flagModel) + if ok { + f.parentKey = m.currEnvironmentKey + m.steps[flagsStep], _ = f.Update(fetchResources{}) + m.currStep += 1 + } } case flagsStep: model, _ := m.steps[flagsStep].Update(msg)