mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: implement rich multi-selector (#19201)
Fixes: https://github.com/coder/coder/issues/19182
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
"slices"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
@@ -299,6 +300,73 @@ func (m selectModel) filteredOptions() []string {
|
||||
return options
|
||||
}
|
||||
|
||||
type RichMultiSelectOptions struct {
|
||||
Message string
|
||||
Options []codersdk.TemplateVersionParameterOption
|
||||
Defaults []string
|
||||
EnableCustomInput bool
|
||||
}
|
||||
|
||||
func RichMultiSelect(inv *serpent.Invocation, richOptions RichMultiSelectOptions) ([]string, error) {
|
||||
var opts []string
|
||||
var defaultOpts []string
|
||||
|
||||
asLine := func(option codersdk.TemplateVersionParameterOption) string {
|
||||
line := option.Name
|
||||
if len(option.Description) > 0 {
|
||||
line += ": " + option.Description
|
||||
}
|
||||
return line
|
||||
}
|
||||
|
||||
var predefinedOpts []string
|
||||
for i, option := range richOptions.Options {
|
||||
opts = append(opts, asLine(option)) // Some options may have description defined.
|
||||
|
||||
// Check if option is selected by default
|
||||
if slices.Contains(richOptions.Defaults, option.Value) {
|
||||
defaultOpts = append(defaultOpts, opts[i])
|
||||
predefinedOpts = append(predefinedOpts, option.Value)
|
||||
}
|
||||
}
|
||||
|
||||
// Check if "defaults" contains extra/custom options, user could select them.
|
||||
for _, def := range richOptions.Defaults {
|
||||
if !slices.Contains(predefinedOpts, def) {
|
||||
opts = append(opts, def)
|
||||
defaultOpts = append(defaultOpts, def)
|
||||
}
|
||||
}
|
||||
|
||||
selected, err := MultiSelect(inv, MultiSelectOptions{
|
||||
Message: richOptions.Message,
|
||||
Options: opts,
|
||||
Defaults: defaultOpts,
|
||||
EnableCustomInput: richOptions.EnableCustomInput,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Check selected option, convert descriptions (line) to values
|
||||
var results []string
|
||||
for _, sel := range selected {
|
||||
custom := true
|
||||
for i, option := range richOptions.Options {
|
||||
if asLine(option) == sel {
|
||||
results = append(results, richOptions.Options[i].Value)
|
||||
custom = false
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if custom {
|
||||
results = append(results, sel)
|
||||
}
|
||||
}
|
||||
return results, nil
|
||||
}
|
||||
|
||||
type MultiSelectOptions struct {
|
||||
Message string
|
||||
Options []string
|
||||
|
||||
Reference in New Issue
Block a user