Skip to content

Commit ab0ae59

Browse files
committed
Update project options
1 parent f48befc commit ab0ae59

File tree

2 files changed

+103
-8
lines changed

2 files changed

+103
-8
lines changed

pkg/github/projects.go

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -876,16 +876,55 @@ type updateProjectItem struct {
876876
ID int `json:"id"`
877877
Value any `json:"value"`
878878
}
879+
type OptionDescription struct {
880+
Raw string `json:"raw,omitempty"`
881+
HTML string `json:"html,omitempty"`
882+
}
883+
884+
func (d *OptionDescription) UnmarshalJSON(data []byte) error {
885+
if string(data) == "null" { // nothing to do
886+
return nil
887+
}
888+
// Try string
889+
var asString string
890+
if err := json.Unmarshal(data, &asString); err == nil {
891+
d.Raw = asString
892+
return nil
893+
}
894+
// Try object form
895+
type alias OptionDescription
896+
var a alias
897+
if err := json.Unmarshal(data, &a); err != nil {
898+
return err
899+
}
900+
d.Raw = a.Raw
901+
d.HTML = a.HTML
902+
return nil
903+
}
904+
905+
func (d OptionDescription) String() string {
906+
if d.Raw != "" {
907+
return d.Raw
908+
}
909+
return d.HTML
910+
}
911+
912+
type projectV2FieldOption struct {
913+
ID string `json:"id,omitempty"` // Unique identifier for this option (string like "option_1").
914+
Name string `json:"name,omitempty"` // Display name of the option.
915+
Color string `json:"color,omitempty"` // Uppercase color name or hex code as returned by the API.
916+
Description *OptionDescription `json:"description,omitempty"` // Optional human-friendly description (raw or html form).
917+
}
879918

880919
type projectV2Field struct {
881-
ID *int64 `json:"id,omitempty"` // The unique identifier for this field.
882-
NodeID string `json:"node_id,omitempty"` // The GraphQL node ID for this field.
883-
Name string `json:"name,omitempty"` // The display name of the field.
884-
DataType string `json:"data_type,omitempty"` // The data type of the field (e.g., "text", "number", "date", "single_select", "multi_select").
885-
URL string `json:"url,omitempty"` // The API URL for this field.
886-
Options []*any `json:"options,omitempty"` // Available options for single_select and multi_select fields.
887-
CreatedAt *github.Timestamp `json:"created_at,omitempty"` // The time when this field was created.
888-
UpdatedAt *github.Timestamp `json:"updated_at,omitempty"` // The time when this field was last updated.
920+
ID *int64 `json:"id,omitempty"` // The unique identifier for this field.
921+
NodeID string `json:"node_id,omitempty"` // The GraphQL node ID for this field.
922+
Name string `json:"name,omitempty"` // The display name of the field.
923+
DataType string `json:"data_type,omitempty"` // The data type of the field (e.g., "text", "number", "date", "single_select", "multi_select").
924+
URL string `json:"url,omitempty"` // The API URL for this field.
925+
Options []*projectV2FieldOption `json:"options,omitempty"` // Available options for single_select and multi_select fields.
926+
CreatedAt *github.Timestamp `json:"created_at,omitempty"` // The time when this field was created.
927+
UpdatedAt *github.Timestamp `json:"updated_at,omitempty"` // The time when this field was last updated.
889928
}
890929

891930
type projectV2Item struct {
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package github
2+
3+
import (
4+
"encoding/json"
5+
"testing"
6+
)
7+
8+
func TestOptionDescription_Unmarshal_String(t *testing.T) {
9+
input := `"Simple description"`
10+
var d OptionDescription
11+
if err := json.Unmarshal([]byte(input), &d); err != nil {
12+
t.Fatalf("unexpected error: %v", err)
13+
}
14+
if d.Raw != "Simple description" || d.HTML != "" {
15+
t.Fatalf("unexpected values: %+v", d)
16+
}
17+
if d.String() != "Simple description" {
18+
t.Fatalf("String() mismatch: %s", d.String())
19+
}
20+
}
21+
22+
func TestOptionDescription_Unmarshal_Object(t *testing.T) {
23+
input := `{"raw": "Raw desc", "html": "<p>Raw desc</p>"}`
24+
var d OptionDescription
25+
if err := json.Unmarshal([]byte(input), &d); err != nil {
26+
t.Fatalf("unexpected error: %v", err)
27+
}
28+
if d.Raw != "Raw desc" || d.HTML != "<p>Raw desc</p>" {
29+
t.Fatalf("unexpected values: %+v", d)
30+
}
31+
if d.String() != "Raw desc" { // prefers Raw
32+
t.Fatalf("String() mismatch: %s", d.String())
33+
}
34+
}
35+
36+
func TestProjectV2FieldOption_Unmarshal_WithStringDescription(t *testing.T) {
37+
input := `{"id":"option_1","name":"Low","color":"GREEN","description":"Low priority"}`
38+
var opt projectV2FieldOption
39+
if err := json.Unmarshal([]byte(input), &opt); err != nil {
40+
t.Fatalf("unexpected error: %v", err)
41+
}
42+
if opt.Description == nil || opt.Description.Raw != "Low priority" {
43+
t.Fatalf("expected raw description, got %+v", opt.Description)
44+
}
45+
}
46+
47+
func TestProjectV2FieldOption_Unmarshal_WithObjectDescription(t *testing.T) {
48+
input := `{"id":"option_1","name":"Low","color":"GREEN","description":{"raw":"Low priority","html":"<p>Low priority</p>"}}`
49+
var opt projectV2FieldOption
50+
if err := json.Unmarshal([]byte(input), &opt); err != nil {
51+
t.Fatalf("unexpected error: %v", err)
52+
}
53+
if opt.Description == nil || opt.Description.Raw != "Low priority" || opt.Description.HTML != "<p>Low priority</p>" {
54+
t.Fatalf("expected structured description, got %+v", opt.Description)
55+
}
56+
}

0 commit comments

Comments
 (0)