mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-12-01 13:44:06 +01:00
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:
parent
d6e454c320
commit
df15abd072
3 changed files with 118 additions and 1 deletions
|
@ -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 {
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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"}}
|
||||||
|
|
Loading…
Reference in a new issue