Module: ActiveProject::Adapters::Fizzy::Issues

Included in:
ActiveProject::Adapters::FizzyAdapter
Defined in:
lib/active_project/adapters/fizzy/issues.rb

Instance Method Summary collapse

Instance Method Details

#create_issue(board_id, attributes) ⇒ ActiveProject::Resources::Issue

Creates a new card in a board.

Parameters:

  • board_id (String)

    The ULID of the Fizzy board.

  • attributes (Hash)

    Card attributes.

    • :title [String] Required. The card title.

    • :description [String] Optional. Rich text description (HTML).

    • :status [String] Optional. Initial status: published (default), drafted.

    • :tag_ids [Array<String>] Optional. Tag IDs to apply.

Returns:



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/active_project/adapters/fizzy/issues.rb', line 69

def create_issue(board_id, attributes)
  title = attributes[:title]
  unless title && !title.empty?
    raise ArgumentError, "Missing required attribute for Fizzy card creation: :title"
  end

  path = "boards/#{board_id}/cards.json"
  payload = {
    card: {
      title: title,
      description: attributes[:description],
      status: attributes[:status] || "published",
      tag_ids: attributes[:tag_ids]
    }.compact
  }

  # Fizzy returns 201 Created with Location header
  response = @connection.post(path) do |req|
    req.body = payload.to_json
  end

  # Extract card number from Location header and fetch it
  location = response.headers["Location"]
  if location
    card_number = location.match(%r{/cards/(\d+)})[1]
    find_issue(card_number)
  else
    # Fallback: parse response body if available
    card_data = parse_response(response)
    map_card_data(card_data, board_id)
  end
rescue Faraday::Error => e
  handle_faraday_error(e)
end

#delete_issue(card_number, context = {}) ⇒ Boolean

Deletes a card.

Parameters:

  • card_number (Integer, String)

    The card number to delete.

  • context (Hash) (defaults to: {})

    Optional context (not required for Fizzy).

Returns:

  • (Boolean)

    True if successfully deleted.



144
145
146
147
148
# File 'lib/active_project/adapters/fizzy/issues.rb', line 144

def delete_issue(card_number, context = {})
  path = "cards/#{card_number}.json"
  make_request(:delete, path)
  true
end

#find_issue(card_number, context = {}) ⇒ ActiveProject::Resources::Issue

Finds a specific card by its number.

Parameters:

  • card_number (Integer, String)

    The card number (sequential per account).

  • context (Hash) (defaults to: {})

    Optional context (not required for Fizzy).

Returns:



52
53
54
55
56
57
58
59
# File 'lib/active_project/adapters/fizzy/issues.rb', line 52

def find_issue(card_number, context = {})
  path = "cards/#{card_number}.json"
  card_data = make_request(:get, path)
  return nil unless card_data

  board_id = card_data.dig("board", "id")
  map_card_data(card_data, board_id)
end

#list_issues(board_id, options = {}) ⇒ Array<ActiveProject::Resources::Issue>

Lists cards within a specific board.

Parameters:

  • board_id (String)

    The ULID of the Fizzy board.

  • options (Hash) (defaults to: {})

    Optional options for filtering.

    • :tag_ids [Array<String>] Filter by tag IDs

    • :assignee_ids [Array<String>] Filter by assignee user IDs

    • :indexed_by [String] Filter: all, closed, not_now, stalled, postponing_soon, golden

    • :sorted_by [String] Sort: latest, newest, oldest

Returns:



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/active_project/adapters/fizzy/issues.rb', line 15

def list_issues(board_id, options = {})
  all_cards = []
  query = { "board_ids[]" => board_id }

  # Add optional filters
  options[:tag_ids]&.each { |id| query["tag_ids[]"] = id }
  options[:assignee_ids]&.each { |id| query["assignee_ids[]"] = id }
  query[:indexed_by] = options[:indexed_by] if options[:indexed_by]
  query[:sorted_by] = options[:sorted_by] if options[:sorted_by]

  path = "cards.json"

  loop do
    response = @connection.get(path, query)
    cards_data = parse_response(response)
    break if cards_data.empty?

    cards_data.each do |card_data|
      all_cards << map_card_data(card_data, board_id)
    end

    next_url = parse_next_link(response.headers["Link"])
    break unless next_url

    path = extract_path_from_url(next_url)
    query = {} # Query params are in the URL now
  end

  all_cards
rescue Faraday::Error => e
  handle_faraday_error(e)
end

#update_issue(card_number, attributes, context = {}) ⇒ ActiveProject::Resources::Issue

Updates an existing card.

Parameters:

  • card_number (Integer, String)

    The card number.

  • attributes (Hash)

    Attributes to update.

    • :title [String] The card title.

    • :description [String] Rich text description.

    • :status [Symbol] Status change: :open, :closed, :on_hold.

    • :tag_ids [Array<String>] Tag IDs to apply.

  • context (Hash) (defaults to: {})

    Optional context (not required for Fizzy).

Returns:



113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/active_project/adapters/fizzy/issues.rb', line 113

def update_issue(card_number, attributes, context = {})
  put_payload = {}
  put_payload[:title] = attributes[:title] if attributes.key?(:title)
  put_payload[:description] = attributes[:description] if attributes.key?(:description)
  put_payload[:tag_ids] = attributes[:tag_ids] if attributes.key?(:tag_ids)

  status_change_required = attributes.key?(:status)
  target_status = attributes[:status] if status_change_required

  unless !put_payload.empty? || status_change_required
    raise ArgumentError, "No attributes provided to update for FizzyAdapter#update_issue"
  end

  # Update basic fields via PUT
  unless put_payload.empty?
    put_path = "cards/#{card_number}.json"
    make_request(:put, put_path, { card: put_payload }.to_json)
  end

  # Handle status changes via separate endpoints
  if status_change_required
    handle_status_change(card_number, target_status)
  end

  find_issue(card_number, context)
end