Add a JSON cards endpoint for workflow columns (#2800)
* Add JSON endpoint for cards in workflow columns * Add cards URL to column JSON responses * Add coverage for column cards authorization
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
class Boards::Columns::CardsController < ApplicationController
|
||||
include BoardScoped
|
||||
|
||||
before_action :set_column
|
||||
|
||||
def index
|
||||
set_page_and_extract_portion_from @column.cards.active.latest.with_golden_first.preloaded
|
||||
fresh_when etag: @page.records
|
||||
|
||||
respond_to do |format|
|
||||
format.json
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def set_column
|
||||
@column = @board.columns.find(params[:column_id])
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1 @@
|
||||
json.array! @page.records, partial: "cards/card", as: :card
|
||||
@@ -1,4 +1,5 @@
|
||||
json.cache! column do
|
||||
json.(column, :id, :name, :color)
|
||||
json.created_at column.created_at.utc
|
||||
json.cards_url board_column_cards_url(column.board, column)
|
||||
end
|
||||
|
||||
+5
-1
@@ -39,7 +39,11 @@ Rails.application.routes.draw do
|
||||
resource :closed
|
||||
end
|
||||
|
||||
resources :columns
|
||||
resources :columns do
|
||||
scope module: :columns do
|
||||
resources :cards, only: :index
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
resources :cards, only: :create
|
||||
|
||||
@@ -14,20 +14,22 @@ __Response:__
|
||||
"id": "03f5v9zkft4hj9qq0lsn9ohcm",
|
||||
"name": "Recording",
|
||||
"color": "var(--color-card-default)",
|
||||
"created_at": "2025-12-05T19:36:35.534Z"
|
||||
"created_at": "2025-12-05T19:36:35.534Z",
|
||||
"cards_url": "http://fizzy.localhost:3006/897362094/boards/03f5v9zkft4hj9qq0lsn9ohcm/columns/03f5v9zkft4hj9qq0lsn9ohcm/cards"
|
||||
},
|
||||
{
|
||||
"id": "03f5v9zkft4hj9qq0lsn9ohcn",
|
||||
"name": "Published",
|
||||
"color": "var(--color-card-4)",
|
||||
"created_at": "2025-12-05T19:36:35.534Z"
|
||||
"created_at": "2025-12-05T19:36:35.534Z",
|
||||
"cards_url": "http://fizzy.localhost:3006/897362094/boards/03f5v9zkft4hj9qq0lsn9ohcm/columns/03f5v9zkft4hj9qq0lsn9ohcn/cards"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## `GET /:account_slug/boards/:board_id/columns/:column_id`
|
||||
|
||||
Returns the specified column.
|
||||
Returns the specified column metadata.
|
||||
|
||||
__Response:__
|
||||
|
||||
@@ -36,10 +38,93 @@ __Response:__
|
||||
"id": "03f5v9zkft4hj9qq0lsn9ohcm",
|
||||
"name": "In Progress",
|
||||
"color": "var(--color-card-default)",
|
||||
"created_at": "2025-12-05T19:36:35.534Z"
|
||||
"created_at": "2025-12-05T19:36:35.534Z",
|
||||
"cards_url": "http://fizzy.localhost:3006/897362094/boards/03f5v9zkft4hj9qq0lsn9ohcm/columns/03f5v9zkft4hj9qq0lsn9ohcm/cards"
|
||||
}
|
||||
```
|
||||
|
||||
## `GET /:account_slug/boards/:board_id/columns/:column_id/cards`
|
||||
|
||||
Returns a paginated list of open cards in the specified workflow column.
|
||||
This only includes cards triaged into that column. Cards in "Maybe?", "Not Now", and "Done"
|
||||
are not included.
|
||||
|
||||
The response items have the same shape as `GET /:account_slug/cards`.
|
||||
|
||||
__Response:__
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": "03f5vaeq985jlvwv3arl4srq2",
|
||||
"number": 1,
|
||||
"title": "First!",
|
||||
"status": "published",
|
||||
"description": "Hello, World!",
|
||||
"description_html": "<div class=\"action-text-content\"><p>Hello, World!</p></div>",
|
||||
"image_url": null,
|
||||
"has_attachments": false,
|
||||
"tags": ["programming"],
|
||||
"closed": false,
|
||||
"postponed": false,
|
||||
"golden": false,
|
||||
"last_active_at": "2025-12-05T19:38:48.553Z",
|
||||
"created_at": "2025-12-05T19:38:48.540Z",
|
||||
"url": "http://fizzy.localhost:3006/897362094/cards/4",
|
||||
"board": {
|
||||
"id": "03f5v9zkft4hj9qq0lsn9ohcm",
|
||||
"name": "Fizzy",
|
||||
"all_access": true,
|
||||
"created_at": "2025-12-05T19:36:35.534Z",
|
||||
"auto_postpone_period_in_days": 30,
|
||||
"url": "http://fizzy.localhost:3006/897362094/boards/03f5v9zkft4hj9qq0lsn9ohcm",
|
||||
"creator": {
|
||||
"id": "03f5v9zjw7pz8717a4no1h8a7",
|
||||
"name": "David Heinemeier Hansson",
|
||||
"role": "owner",
|
||||
"active": true,
|
||||
"email_address": "david@example.com",
|
||||
"created_at": "2025-12-05T19:36:35.401Z",
|
||||
"url": "http://fizzy.localhost:3006/897362094/users/03f5v9zjw7pz8717a4no1h8a7",
|
||||
"avatar_url": "http://fizzy.localhost:3006/897362094/users/03f5v9zjw7pz8717a4no1h8a7/avatar"
|
||||
}
|
||||
},
|
||||
"column": {
|
||||
"id": "03f5v9zkft4hj9qq0lsn9ohcn",
|
||||
"name": "In Progress",
|
||||
"color": "var(--color-card-4)",
|
||||
"created_at": "2025-12-05T19:36:35.534Z",
|
||||
"cards_url": "http://fizzy.localhost:3006/897362094/boards/03f5v9zkft4hj9qq0lsn9ohcm/columns/03f5v9zkft4hj9qq0lsn9ohcn/cards"
|
||||
},
|
||||
"creator": {
|
||||
"id": "03f5v9zjw7pz8717a4no1h8a7",
|
||||
"name": "David Heinemeier Hansson",
|
||||
"role": "owner",
|
||||
"active": true,
|
||||
"email_address": "david@example.com",
|
||||
"created_at": "2025-12-05T19:36:35.401Z",
|
||||
"url": "http://fizzy.localhost:3006/897362094/users/03f5v9zjw7pz8717a4no1h8a7",
|
||||
"avatar_url": "http://fizzy.localhost:3006/897362094/users/03f5v9zjw7pz8717a4no1h8a7/avatar"
|
||||
},
|
||||
"assignees": [
|
||||
{
|
||||
"id": "03f5v9zjw7pz8717a4no1h8a7",
|
||||
"name": "David Heinemeier Hansson",
|
||||
"role": "owner",
|
||||
"active": true,
|
||||
"email_address": "david@example.com",
|
||||
"created_at": "2025-12-05T19:36:35.401Z",
|
||||
"url": "http://fizzy.localhost:3006/897362094/users/03f5v9zjw7pz8717a4no1h8a7",
|
||||
"avatar_url": "http://fizzy.localhost:3006/897362094/users/03f5v9zjw7pz8717a4no1h8a7/avatar"
|
||||
}
|
||||
],
|
||||
"has_more_assignees": false,
|
||||
"comments_url": "http://fizzy.localhost:3006/897362094/cards/4/comments",
|
||||
"reactions_url": "http://fizzy.localhost:3006/897362094/cards/4/reactions"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## `POST /:account_slug/boards/:board_id/columns`
|
||||
|
||||
Creates a new column on the board.
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
require "test_helper"
|
||||
|
||||
class Boards::Columns::CardsControllerTest < ActionDispatch::IntegrationTest
|
||||
setup do
|
||||
sign_in_as :kevin
|
||||
end
|
||||
|
||||
test "index as JSON" do
|
||||
column = columns(:writebook_in_progress)
|
||||
|
||||
get board_column_cards_path(column.board, column), as: :json
|
||||
|
||||
assert_response :success
|
||||
assert_kind_of Array, @response.parsed_body
|
||||
assert_equal [ cards(:text).number ], @response.parsed_body.pluck("number")
|
||||
assert_equal "1", response.headers["X-Total-Count"]
|
||||
end
|
||||
|
||||
test "cannot access cards on board without access as JSON" do
|
||||
board = boards(:private)
|
||||
column = board.columns.create!(name: "Secret")
|
||||
|
||||
logout_and_sign_in_as :jason
|
||||
|
||||
get board_column_cards_path(board, column), as: :json
|
||||
|
||||
assert_response :not_found
|
||||
end
|
||||
end
|
||||
@@ -55,6 +55,7 @@ class Boards::ColumnsControllerTest < ActionDispatch::IntegrationTest
|
||||
|
||||
assert_response :success
|
||||
assert_equal board.columns.count, @response.parsed_body.count
|
||||
assert_equal board_column_cards_url(board, board.columns.sorted.first), @response.parsed_body.first["cards_url"]
|
||||
end
|
||||
|
||||
test "show as JSON" do
|
||||
@@ -64,6 +65,7 @@ class Boards::ColumnsControllerTest < ActionDispatch::IntegrationTest
|
||||
|
||||
assert_response :success
|
||||
assert_equal column.id, @response.parsed_body["id"]
|
||||
assert_equal board_column_cards_url(column.board, column), @response.parsed_body["cards_url"]
|
||||
end
|
||||
|
||||
test "create as JSON" do
|
||||
@@ -76,6 +78,7 @@ class Boards::ColumnsControllerTest < ActionDispatch::IntegrationTest
|
||||
assert_response :created
|
||||
assert_equal board_column_path(board, Column.last, format: :json), @response.headers["Location"]
|
||||
assert_equal "New Column", @response.parsed_body["name"]
|
||||
assert_equal board_column_cards_url(board, Column.last), @response.parsed_body["cards_url"]
|
||||
end
|
||||
|
||||
test "update as JSON" do
|
||||
|
||||
Reference in New Issue
Block a user