Support setting the default attribute of the issue template dropdown field (#31045)

Fix #31044

According to [GitHub issue template
documentation](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema#attributes-for-dropdown),
the `default` attribute can be used to specify the preselected option
for a dropdown field.

(cherry picked from commit 7ab0988af140aa3e0204979765f75961f1dc9c11)
This commit is contained in:
Zettat123 2024-05-23 21:01:02 +08:00 committed by Earl Warren
parent d6e454c320
commit df15abd072
No known key found for this signature in database
GPG key ID: 0579CB2928A78A00
3 changed files with 118 additions and 1 deletions

View file

@ -91,6 +91,9 @@ func validateYaml(template *api.IssueTemplate) error {
if err := validateOptions(field, idx); err != nil { if err := validateOptions(field, idx); err != nil {
return err return err
} }
if err := validateDropdownDefault(position, field.Attributes); err != nil {
return err
}
case api.IssueFormFieldTypeCheckboxes: case api.IssueFormFieldTypeCheckboxes:
if err := validateStringItem(position, field.Attributes, false, "description"); err != nil { if err := validateStringItem(position, field.Attributes, false, "description"); err != nil {
return err return err
@ -249,6 +252,28 @@ func validateBoolItem(position errorPosition, m map[string]any, names ...string)
return nil return nil
} }
func validateDropdownDefault(position errorPosition, attributes map[string]any) error {
v, ok := attributes["default"]
if !ok {
return nil
}
defaultValue, ok := v.(int)
if !ok {
return position.Errorf("'default' should be an int")
}
options, ok := attributes["options"].([]any)
if !ok {
// should not happen
return position.Errorf("'options' is required and should be a array")
}
if defaultValue < 0 || defaultValue >= len(options) {
return position.Errorf("the value of 'default' is out of range")
}
return nil
}
type errorPosition string type errorPosition string
func (p errorPosition) Errorf(format string, a ...any) error { func (p errorPosition) Errorf(format string, a ...any) error {

View file

@ -355,6 +355,96 @@ body:
`, `,
wantErr: "body[0](checkboxes), option[1]: can not require a hidden checkbox", wantErr: "body[0](checkboxes), option[1]: can not require a hidden checkbox",
}, },
{
name: "dropdown default is not an integer",
content: `
name: "test"
about: "this is about"
body:
- type: dropdown
id: "1"
attributes:
label: Label of dropdown
description: Description of dropdown
multiple: true
options:
- Option 1 of dropdown
- Option 2 of dropdown
- Option 3 of dropdown
default: "def"
validations:
required: true
`,
wantErr: "body[0](dropdown): 'default' should be an int",
},
{
name: "dropdown default is out of range",
content: `
name: "test"
about: "this is about"
body:
- type: dropdown
id: "1"
attributes:
label: Label of dropdown
description: Description of dropdown
multiple: true
options:
- Option 1 of dropdown
- Option 2 of dropdown
- Option 3 of dropdown
default: 3
validations:
required: true
`,
wantErr: "body[0](dropdown): the value of 'default' is out of range",
},
{
name: "dropdown without default is valid",
content: `
name: "test"
about: "this is about"
body:
- type: dropdown
id: "1"
attributes:
label: Label of dropdown
description: Description of dropdown
multiple: true
options:
- Option 1 of dropdown
- Option 2 of dropdown
- Option 3 of dropdown
validations:
required: true
`,
want: &api.IssueTemplate{
Name: "test",
About: "this is about",
Fields: []*api.IssueFormField{
{
Type: "dropdown",
ID: "1",
Attributes: map[string]any{
"label": "Label of dropdown",
"description": "Description of dropdown",
"multiple": true,
"options": []any{
"Option 1 of dropdown",
"Option 2 of dropdown",
"Option 3 of dropdown",
},
},
Validations: map[string]any{
"required": true,
},
Visible: []api.IssueFormFieldVisible{api.IssueFormFieldVisibleForm, api.IssueFormFieldVisibleContent},
},
},
FileName: "test.yaml",
},
wantErr: "",
},
{ {
name: "valid", name: "valid",
content: ` content: `
@ -399,6 +489,7 @@ body:
- Option 1 of dropdown - Option 1 of dropdown
- Option 2 of dropdown - Option 2 of dropdown
- Option 3 of dropdown - Option 3 of dropdown
default: 1
validations: validations:
required: true required: true
- type: checkboxes - type: checkboxes
@ -475,6 +566,7 @@ body:
"Option 2 of dropdown", "Option 2 of dropdown",
"Option 3 of dropdown", "Option 3 of dropdown",
}, },
"default": 1,
}, },
Validations: map[string]any{ Validations: map[string]any{
"required": true, "required": true,

View file

@ -2,7 +2,7 @@
{{template "repo/issue/fields/header" .}} {{template "repo/issue/fields/header" .}}
{{/* FIXME: required validation */}} {{/* FIXME: required validation */}}
<div class="ui fluid selection dropdown {{if .item.Attributes.multiple}}multiple clearable{{end}}"> <div class="ui fluid selection dropdown {{if .item.Attributes.multiple}}multiple clearable{{end}}">
<input type="hidden" name="form-field-{{.item.ID}}" value="0"> <input type="hidden" name="form-field-{{.item.ID}}" value="{{.item.Attributes.default}}">
{{svg "octicon-triangle-down" 14 "dropdown icon"}} {{svg "octicon-triangle-down" 14 "dropdown icon"}}
{{if not .item.Validations.required}} {{if not .item.Validations.required}}
{{svg "octicon-x" 14 "remove icon"}} {{svg "octicon-x" 14 "remove icon"}}