Skip to content

Allow custom field values to be specified as JSON #661

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

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
30 changes: 1 addition & 29 deletions pkg/jira/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"
"encoding/json"
"net/http"
"strconv"
"strings"

"github.com/ankitpokhrel/jira-cli/pkg/adf"
Expand Down Expand Up @@ -240,34 +239,7 @@ func constructCustomFields(fields map[string]string, configuredFields []IssueTyp
if identifier != strings.ToLower(key) {
continue
}

switch configured.Schema.DataType {
case customFieldFormatOption:
data.Fields.M.customFields[configured.Key] = customFieldTypeOption{Value: val}
case customFieldFormatProject:
data.Fields.M.customFields[configured.Key] = customFieldTypeProject{Value: val}
case customFieldFormatArray:
pieces := strings.Split(strings.TrimSpace(val), ",")
if configured.Schema.Items == customFieldFormatOption {
items := make([]customFieldTypeOption, 0)
for _, p := range pieces {
items = append(items, customFieldTypeOption{Value: p})
}
data.Fields.M.customFields[configured.Key] = items
} else {
data.Fields.M.customFields[configured.Key] = pieces
}
case customFieldFormatNumber:
num, err := strconv.ParseFloat(val, 64) //nolint:gomnd
if err != nil {
// Let Jira API handle data type error for now.
data.Fields.M.customFields[configured.Key] = val
} else {
data.Fields.M.customFields[configured.Key] = customFieldTypeNumber(num)
}
default:
data.Fields.M.customFields[configured.Key] = val
}
data.Fields.M.customFields[configured.Key] = constructCustomField(configured.Schema.DataType, configured.Schema.Items, val)
}
}
}
Expand Down
77 changes: 62 additions & 15 deletions pkg/jira/customfield.go
Original file line number Diff line number Diff line change
@@ -1,41 +1,88 @@
package jira

import (
"encoding/json"
"strconv"
"strings"
)

const (
customFieldFormatAny = "any"
customFieldFormatOption = "option"
customFieldFormatArray = "array"
customFieldFormatNumber = "number"
customFieldFormatString = "string"
customFieldFormatProject = "project"
customFieldFormatJson = "json"
)

type customField map[string]interface{}

type customFieldTypeNumber float64

type customFieldTypeNumberSet struct {
Set customFieldTypeNumber `json:"set"`
type customFieldTypeString string

type customFieldTypeOption struct {
Value string `json:"value"`
}

type customFieldTypeStringSet struct {
Set string `json:"set"`
type customFieldTypeProject struct {
Value string `json:"key"`
}

type customFieldTypeOption struct {
Value string `json:"value"`
type customFieldTypeJson struct {
Json string
}

type customFieldTypeOptionSet struct {
Set customFieldTypeOption `json:"set"`
func (field customFieldTypeJson) MarshalJSON() ([]byte, error) {
return []byte(field.Json), nil
}

type customFieldTypeOptionAddRemove struct {
Add *customFieldTypeOption `json:"add,omitempty"`
Remove *customFieldTypeOption `json:"remove,omitempty"`
type customFieldEditTypeSet struct {
Set any `json:"set"`
}

type customFieldTypeProject struct {
Value string `json:"key"`
type customFieldEditTypeAddRemove struct {
Add *any `json:"add,omitempty"`
Remove *any `json:"remove,omitempty"`
}

type customFieldTypeProjectSet struct {
Set customFieldTypeProject `json:"set"`
func constructCustomField(dataType string, itemType string, value string) any {
switch dataType {
case customFieldFormatOption:
return customFieldTypeOption{Value: value}
case customFieldFormatProject:
return customFieldTypeProject{Value: value}
case customFieldFormatArray:
pieces := strings.Split(strings.TrimSpace(value), ",")
items := make([]any, len(pieces))
for idx, piece := range pieces {
items[idx] = constructCustomField(itemType, "", piece)
}
return items
case customFieldFormatNumber:
num, err := strconv.ParseFloat(value, 64) //nolint:gomnd
if err != nil {
// Let Jira API handle data type error for now.
return value
} else {
return customFieldTypeNumber(num)
}
case customFieldFormatAny:
fallthrough
case customFieldFormatString:
return customFieldTypeString(value)
case customFieldFormatJson:
return customFieldTypeJson{Json: value}
default:
// An unknown type like "version" or "user". Try parsing as JSON,
// and if that doesn't work, just send as a string
var unused any
err := json.Unmarshal([]byte(value), &unused)
if err == nil {
return customFieldTypeJson{Json: value}
} else {
return value
}
}
}
41 changes: 12 additions & 29 deletions pkg/jira/edit.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"
"encoding/json"
"net/http"
"strconv"
"strings"
)

Expand Down Expand Up @@ -366,37 +365,21 @@ func constructCustomFieldsForEdit(fields map[string]string, configuredFields []I
if identifier != strings.ToLower(key) {
continue
}

switch configured.Schema.DataType {
case customFieldFormatOption:
data.Update.M.customFields[configured.Key] = []customFieldTypeOptionSet{{Set: customFieldTypeOption{Value: val}}}
case customFieldFormatProject:
data.Update.M.customFields[configured.Key] = []customFieldTypeProjectSet{{Set: customFieldTypeProject{Value: val}}}
case customFieldFormatArray:
if configured.Schema.DataType == customFieldFormatArray {
pieces := strings.Split(strings.TrimSpace(val), ",")
if configured.Schema.Items == customFieldFormatOption {
items := make([]customFieldTypeOptionAddRemove, 0)
for _, p := range pieces {
if strings.HasPrefix(p, separatorMinus) {
items = append(items, customFieldTypeOptionAddRemove{Remove: &customFieldTypeOption{Value: strings.TrimPrefix(p, separatorMinus)}})
} else {
items = append(items, customFieldTypeOptionAddRemove{Add: &customFieldTypeOption{Value: p}})
}
items := make([]customFieldEditTypeAddRemove, len(pieces))
for idx, piece := range pieces {
field := constructCustomField(configured.Schema.Items, "", strings.TrimPrefix(piece, separatorMinus))
if strings.HasPrefix(piece, separatorMinus) {
items[idx] = customFieldEditTypeAddRemove{Remove: &field}
} else {
items[idx] = customFieldEditTypeAddRemove{Add: &field}
}
data.Update.M.customFields[configured.Key] = items
} else {
data.Update.M.customFields[configured.Key] = pieces
}
case customFieldFormatNumber:
num, err := strconv.ParseFloat(val, 64) //nolint:gomnd
if err != nil {
// Let Jira API handle data type error for now.
data.Update.M.customFields[configured.Key] = []customFieldTypeStringSet{{Set: val}}
} else {
data.Update.M.customFields[configured.Key] = []customFieldTypeNumberSet{{Set: customFieldTypeNumber(num)}}
}
default:
data.Update.M.customFields[configured.Key] = []customFieldTypeStringSet{{Set: val}}
data.Update.M.customFields[configured.Key] = items
} else {
field := constructCustomField(configured.Schema.DataType, "", val)
data.Update.M.customFields[configured.Key] = []customFieldEditTypeSet{{Set: field}}
}
}
}
Expand Down