Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions behavior-model.json
Original file line number Diff line number Diff line change
Expand Up @@ -1392,6 +1392,18 @@
]
}
},
"ListLineupMarkers": {
"readonly": true,
"retry": {
"max": 3,
"base_delay_ms": 1000,
"backoff": "exponential",
"retry_on": [
429,
503
]
}
},
"ListMessageTypes": {
"readonly": true,
"pagination": {
Expand Down
65 changes: 48 additions & 17 deletions go/pkg/basecamp/lineup.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,16 @@ import (

// LineupMarker represents a marker on the Basecamp Lineup.
type LineupMarker struct {
ID int64 `json:"id"`
Status string `json:"status"`
Color string `json:"color"`
Title string `json:"title"`
StartsOn string `json:"starts_on"`
EndsOn string `json:"ends_on"`
Description string `json:"description,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
Type string `json:"type"`
URL string `json:"url"`
AppURL string `json:"app_url"`
Creator *Person `json:"creator,omitempty"`
Parent *Parent `json:"parent,omitempty"`
Bucket *Bucket `json:"bucket,omitempty"`
ID int64 `json:"id"`
Name string `json:"name"`
Date string `json:"date"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}

// ListMarkersResult contains the results from listing lineup markers.
type ListMarkersResult struct {
Markers []LineupMarker
}

// CreateMarkerRequest specifies the parameters for creating a lineup marker.
Expand Down Expand Up @@ -146,5 +141,41 @@ func (s *LineupService) DeleteMarker(ctx context.Context, markerID int64) (err e
return checkResponse(resp.HTTPResponse)
}

// Note: lineupMarkerFromGenerated was removed because CreateLineupMarker and
// UpdateLineupMarker now return 204 No Content with no response body.
// ListMarkers returns all markers for the account.
func (s *LineupService) ListMarkers(ctx context.Context) (result *ListMarkersResult, err error) {
op := OperationInfo{
Service: "Lineup", Operation: "ListMarkers",
ResourceType: "lineup_marker", IsMutation: false,
}
if gater, ok := s.client.parent.hooks.(GatingHooks); ok {
if ctx, err = gater.OnOperationGate(ctx, op); err != nil {
return
}
}
start := time.Now()
ctx = s.client.parent.hooks.OnOperationStart(ctx, op)
defer func() { s.client.parent.hooks.OnOperationEnd(ctx, op, err, time.Since(start)) }()

resp, err := s.client.parent.gen.ListLineupMarkersWithResponse(ctx, s.client.accountID)
if err != nil {
return nil, err
}
if err = checkResponse(resp.HTTPResponse); err != nil {
return nil, err
}

var markers []LineupMarker
if resp.JSON200 != nil {
for _, gm := range *resp.JSON200 {
markers = append(markers, LineupMarker{
ID: gm.Id,
Name: gm.Name,
Date: gm.Date,
CreatedAt: gm.CreatedAt,
UpdatedAt: gm.UpdatedAt,
})
}
}

return &ListMarkersResult{Markers: markers}, nil
}
91 changes: 17 additions & 74 deletions go/pkg/basecamp/lineup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,91 +21,34 @@ func loadLineupFixture(t *testing.T, name string) []byte {
return data
}

func TestLineupMarker_UnmarshalCreate(t *testing.T) {
data := loadLineupFixture(t, "create.json")
func TestLineupMarker_UnmarshalList(t *testing.T) {
data := loadLineupFixture(t, "list.json")

var marker LineupMarker
if err := json.Unmarshal(data, &marker); err != nil {
t.Fatalf("failed to unmarshal create.json: %v", err)
var markers []LineupMarker
if err := json.Unmarshal(data, &markers); err != nil {
t.Fatalf("failed to unmarshal list.json: %v", err)
}

if marker.ID != 1069479400 {
t.Errorf("expected ID 1069479400, got %d", marker.ID)
if len(markers) != 2 {
t.Fatalf("expected 2 markers, got %d", len(markers))
}
if marker.Status != "active" {
t.Errorf("expected status 'active', got %q", marker.Status)
}
if marker.Type != "Lineup::Marker" {
t.Errorf("expected type 'Lineup::Marker', got %q", marker.Type)
}
if marker.Title != "Product Launch" {
t.Errorf("expected title 'Product Launch', got %q", marker.Title)
}
if marker.Color != "blue" {
t.Errorf("expected color 'blue', got %q", marker.Color)
}
if marker.StartsOn != "2024-03-01" {
t.Errorf("expected starts_on '2024-03-01', got %q", marker.StartsOn)
}
if marker.EndsOn != "2024-03-15" {
t.Errorf("expected ends_on '2024-03-15', got %q", marker.EndsOn)
}
if marker.Description != "<div>Launch phase for the new product</div>" {
t.Errorf("unexpected description: %q", marker.Description)

m := markers[0]
if m.ID != 1069479400 {
t.Errorf("expected ID 1069479400, got %d", m.ID)
}
if marker.URL != "https://3.basecampapi.com/195539477/lineup/markers/1069479400.json" {
t.Errorf("unexpected URL: %q", marker.URL)
if m.Name != "Product Launch" {
t.Errorf("expected name 'Product Launch', got %q", m.Name)
}
if marker.AppURL != "https://3.basecamp.com/195539477/lineup" {
t.Errorf("unexpected AppURL: %q", marker.AppURL)
if m.Date != "2024-03-01" {
t.Errorf("expected date '2024-03-01', got %q", m.Date)
}

// Verify timestamps are parsed
if marker.CreatedAt.IsZero() {
if m.CreatedAt.IsZero() {
t.Error("expected CreatedAt to be non-zero")
}
if marker.UpdatedAt.IsZero() {
if m.UpdatedAt.IsZero() {
t.Error("expected UpdatedAt to be non-zero")
}

// Verify creator
if marker.Creator == nil {
t.Fatal("expected Creator to be non-nil")
}
if marker.Creator.ID != 1049715914 {
t.Errorf("expected Creator.ID 1049715914, got %d", marker.Creator.ID)
}
if marker.Creator.Name != "Victor Cooper" {
t.Errorf("expected Creator.Name 'Victor Cooper', got %q", marker.Creator.Name)
}
if marker.Creator.EmailAddress != "victor@honchodesign.com" {
t.Errorf("expected Creator.EmailAddress 'victor@honchodesign.com', got %q", marker.Creator.EmailAddress)
}
}

func TestLineupMarker_UnmarshalUpdate(t *testing.T) {
data := loadLineupFixture(t, "update.json")

var marker LineupMarker
if err := json.Unmarshal(data, &marker); err != nil {
t.Fatalf("failed to unmarshal update.json: %v", err)
}

if marker.ID != 1069479400 {
t.Errorf("expected ID 1069479400, got %d", marker.ID)
}
if marker.Title != "Product Launch - Extended" {
t.Errorf("expected title 'Product Launch - Extended', got %q", marker.Title)
}
if marker.Color != "green" {
t.Errorf("expected color 'green', got %q", marker.Color)
}
if marker.EndsOn != "2024-03-31" {
t.Errorf("expected ends_on '2024-03-31', got %q", marker.EndsOn)
}
if marker.Description != "<div>Extended launch phase for the new product</div>" {
t.Errorf("unexpected description: %q", marker.Description)
}
}

func TestCreateMarkerRequest_Marshal(t *testing.T) {
Expand Down
31 changes: 14 additions & 17 deletions go/pkg/basecamp/url-routes.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,23 +52,6 @@
}
}
},
{
"pattern": "/{accountId}/buckets/{projectId}/dock/tools",
"resource": "Automation",
"operations": {
"POST": "CloneTool"
},
"params": {
"accountId": {
"role": "account",
"type": "string"
},
"projectId": {
"role": "bucket",
"type": "int64"
}
}
},
{
"pattern": "/{accountId}/card_tables/cards/{cardId}",
"resource": "Card Tables",
Expand Down Expand Up @@ -604,6 +587,19 @@
}
}
},
{
"pattern": "/{accountId}/dock/tools",
"resource": "Automation",
"operations": {
"POST": "CloneTool"
},
"params": {
"accountId": {
"role": "account",
"type": "string"
}
}
},
{
"pattern": "/{accountId}/dock/tools/{toolId}",
"resource": "Automation",
Expand Down Expand Up @@ -735,6 +731,7 @@
"pattern": "/{accountId}/lineup/markers",
"resource": "Automation",
"operations": {
"GET": "ListLineupMarkers",
"POST": "CreateLineupMarker"
},
"params": {
Expand Down
Loading
Loading