Commit Graph

36 Commits

Author SHA1 Message Date
Jeremy Daer 723c8180b4 Add JSON response format for full SDK/CLI coverage (#2675)
* Add JSON response format to void-response controller actions

Add respond_to blocks with JSON format to 14 controllers that
previously only rendered HTML or Turbo Stream responses. JSON
callers get head :no_content (or :created/:ok for push
subscriptions, distinguishing new vs existing).

Covers: board involvements, board/account entropies, column
reordering, card readings, card publishing, user roles, user
avatars, account settings, notification settings, join codes
(with 422 error branch), and push subscriptions.

* Add steps index endpoint with JSON view

Add index action to Cards::StepsController so SDK/CLI callers
can list all steps for a card. Reuses the existing _step.json
partial.

* Add JSON views for paginated card list endpoints

Add show.json.jbuilder for stream, not-now, and closed column
endpoints. No controller changes needed — set_page_and_extract_
portion_from and fresh_when already work format-agnostically.

* Add JSON search endpoint with distinct-card pagination

JSON search paginates distinct Card records (via the existing
Card.mentioning scope with .distinct) rather than Search::Record
objects. This ensures page boundaries, Link headers, and counts
reflect unique cards — no short pages from post-pagination dedup.

ID-match searches return a uniform single-element Card[] array
through the same pagination path.

* Add JSON views for settings and configuration endpoints

Add show.json.jbuilder for account settings (name), join codes
(code, usage_count, usage_limit, url, active), and notification
settings (bundle_email_frequency). Tests for show and update
were added in the void-response commit.

* Add JSON response format to data exports

Create returns 201 with export id, status, and created_at so
callers can poll. Show returns any-status exports for JSON (not
just completed) with a download_url when ready, or 404 for
missing/other-user exports.

* Extend access token JSON API

Add index.json and _access_token.json partial for listing tokens.
Add JSON format to destroy. Include id and created_at in the
create response alongside the existing token/description/permission
fields.

* Fix ambiguous precedence warning in export JSON view

* Assert X-Total-Count pagination header in streams JSON test

* Address review feedback

- Guard steps index against HTML requests (redirect to card)
- Normalize created_at to UTC in access token and export JSON
- Add deterministic ordering (.latest) to search JSON pagination

* Return 406 for HTML requests to steps index instead of redirect

* Add wrap_parameters for flat SDK JSON payload compatibility

Five controllers infer the wrong wrapper key from their class
name, so flat JSON bodies like {"role":"admin"} fail with 400.
Add explicit wrap_parameters declarations:

- Users::RolesController → :user
- Notifications::SettingsController → :user_settings
- Account::JoinCodesController → :account_join_code
- Account::SettingsController → :account
- Boards::EntropiesController → :board

Add integration tests that send flat (unwrapped) JSON payloads
for all seven param-bearing endpoints to prove SDK compatibility.

* Address PR review feedback

- Use 201 Created (not 204) for all create actions: publishes, readings,
  left/right positions, push subscriptions
- Simplify push subscription to always return :created (no 200/201 variance)
- Remove superfluous respond_to block from steps#index
- Merge exports#show into single respond_to block
- Move export download_url conditional out of inline args
- Ensure join code active is explicitly boolean
- Remove extra parens from search controller assignment
- Add blank lines between format blocks for readability

* Return JSON bodies on create actions

Create actions for boards, cards, columns, comments, and steps now
render the resource as JSON (via their show views) instead of returning
empty 201 responses with only a Location header. SDKs expect a JSON
body they can deserialize into the created resource.

* Return JSON bodies on reaction create actions

Card and comment reaction creates now render the reaction as JSON
instead of returning empty 201 responses, consistent with the other
resource-creating endpoints.

* Allow access tokens API without account scope

Access tokens are identity-level (not account-scoped), so the
controller needs to work with bearer token auth and no account slug
in the URL. Skip require_account so the bearer token auth path
can proceed.

Also fix involvement test to send params in JSON body (not query
string) to match real SDK usage.
2026-03-09 11:39:49 -07:00
Alp Keser 610cf7a190 Merge pull request #2398 from basecamp/notifications-tray-api
Add JSON response support for `notifications/tray`
2026-02-18 13:19:59 +03:00
Jirka Hutárek c4c46cce44 Add postponed and closed flags to Pinned and Notification cards 2026-02-13 00:45:47 +01:00
Mike Dalessio 851f13a934 Render inline code in card titles (#2518)
* Remove unused marked JS dependency

* Remove unused redcarpet dependency

* Render inline code in card titles

Add card_html_title helper that HTML-escapes input then converts
backtick-wrapped text to <code> elements. Apply to card titles in
board preview, card detail, public views, and notification emails.
Style inline code elements in titles to match description styling.

Co-authored-by: Andy Smith <andy@37signals.com>

---------

Co-authored-by: Andy Smith <andy@37signals.com>
2026-02-12 12:07:40 -05:00
Mike Dalessio 015bc3420e Fix boost button appearing prematurely on draft cards
When updating a draft card (e.g., adding a background image), the turbo
stream response was using the published card container partial, which
includes the reactions/boost button. Draft cards should use the draft
container partial which intentionally omits reactions.

Fixes https://app.fizzy.do/5986089/cards/3970
2026-02-03 09:28:08 -05:00
Mike Dalessio 16745e89d1 Add card reactions to API docs and reactions_url to card JSON (#2427)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 16:55:50 -05:00
Jorge Manrubia 4ab1e3ff7d Solve problem when Action Text raises on missing attachables
Reverts the previous patch. The problem was that I hadn't update
 Lexxy in the saas version https://github.com/basecamp/lexxy/pull/596
2026-01-16 17:32:41 +01:00
Jorge Manrubia f58a1aeb31 Use a dedicated resource for showing cards in draft mode
Mobile team needs this. Also, this lets us get rid from some conditionals for handling
both modes with a single template.

https://3.basecamp.com/2914079/buckets/44843469/messages/9437287330
2026-01-08 10:40:21 +01:00
Rosa Gutierrez 1e640643e9 Remove unused tag_ids parameter from CardsController#update
This is no longer used in the normal flow of the app. The tags are added
via `Cards::TaggingsController`.
2025-12-19 11:16:20 +01:00
Abdelkader Boudih b5caa8716d feat: expose closed boolean in card JSON API
Adds `closed` field to card JSON response, allowing API consumers
to detect closed status without parsing the status enum or making
additional API calls.
2025-12-12 10:12:21 +01:00
Jankees van Woezik 78fc80cf35 API: Allow updates to last_active_at (#2076)
* Allow Card#last_updated_at to be set

This is useful when doing an import from another system. I'm currently
working on a script to import our Github issues into Fizzy.

This is discussed in
https://github.com/basecamp/fizzy/pull/2056#discussion_r2609560246

* Add nil fallback and expand test coverage for last_active_at

Adds a safety fallback to Time.current if created_at is unexpectedly nil
during card creation.

Test coverage to verify:
* last_active_at defaults to created_at when not provided
* last_active_at can be updated via API on existing cards
* import workflow where last_active_at is restored after comments
* publishing doesn't overwrite explicit last_active_at values

---------

Co-authored-by: Jeremy Daer <jeremy@37signals.com>
2025-12-11 19:06:03 -08:00
Jankees van Woezik 477b4d65f2 API: Support created_at for API card and comment creation (#2056)
* Add support to set `created_at`

Discussed in
https://github.com/basecamp/fizzy/pull/1766#issuecomment-3637846074,
this allows users to import cards from another system with entries from
the past. For instance I'm importing all our Github issues (including
the closed onces) to Fizzy.

* Iron out published state tracking

---------

Co-authored-by: Jeremy Daer <jeremy@37signals.com>
2025-12-10 19:57:38 -08:00
Stanko K.R. 4e092407ab Fix crash due to missing partial 2025-12-10 18:47:00 +01:00
Stanko K.R. 235a94355e Add card update & delete actions 2025-12-10 09:23:52 +01:00
Stanko K.R. ae03f2b283 Move tests into their controller tests 2025-12-10 09:23:52 +01:00
Mike Dalessio 89940d36f8 Gracefully handle ill-formed remote images in rich text
A better fix has been proposed upstream at
https://github.com/rails/rails/pull/56283 but this should be fine in
the meantime.

ref: https://app.fizzy.do/5986089/cards/3188
2025-12-04 09:24:52 -05:00
Mike Dalessio b05ecb7809 Update card buttons dynamically
User flows when editing a card look like:
- Click "Edit" → the closure buttons are replaced by "Save changes"
- Submit card form → Saves and restores closure buttons
- Press ESC while editing → Cancels and restores closure buttons

Also, renamed for clarity:
- _title.html.erb → _content.html.erb

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-22 12:14:39 -05:00
Kevin McConnell 59dd8ca549 Make IDs more time-sortable in tests
In order for model ordering to work as expected in tests, we need to
keep two properties:

- Fixtures are all created in the past
- Models sort in the order that they were created

This allows us to do things like this:

    post cards_path, params: { ... }
    created_card = Card.last

When using UUIDv7 PKs rather than sequential integers, we have to make
sure a couple of things happen in order for this still to be true:

- Fixtures should generate deterministic IDs that translate to UUIDs
  that would have been created in the past (i.e. before today)
- Newly created objects must have enough precision in their timestamps
  so that they sort in the order they were created, and their random
  component doesn't come into play.

To solve this, we use the deterministic numeric ID as a number of
milliseconds after an early year. And we ensure that the new timestamps
we create have sub-millisecond precision.
2025-11-17 09:12:40 -05:00
Kevin McConnell 1959e15f7e Fix more tests
These are mainly because the fixture's UUIDs are deterministic rather
than time-sortable, and more places where we need to correct the fixture
IDs as well.
2025-11-17 09:12:31 -05:00
Jorge Manrubia 3b34703db3 Make sure that only admins or card creators can delete cards 2025-11-05 16:37:43 +01:00
Jorge Manrubia 03a345609e Baseline replacing collection with board across code 2025-11-05 13:31:54 +01:00
Jorge Manrubia 9d4dd3b00e Remove "save as draft"
Removes the creating status completely as well as the abandoned cards system. It will
always resume drafts if they exist, for a given collection and user.

https://app.box-car.com/5986089/cards/2489
2025-11-03 09:32:29 +01:00
David Heinemeier Hansson 6c15610fb3 Fix test 2025-10-30 15:56:12 +01:00
Jorge Manrubia 23895e53aa Add tests for new controllers 2025-09-28 21:11:07 +02:00
Jorge Manrubia 4e72566856 Flatten card resource
We only need the parent collection for creating cards. Carrying it in the
rest of actions is a hassle.
2025-09-10 11:24:23 +02:00
Jorge Manrubia fa04016cbe Revert "Revert "Replace House with Lexical"" 2025-05-29 14:25:16 +02:00
Jorge Manrubia 08d8b2e5ff Revert "Replace House with Lexical" 2025-05-29 14:22:27 +02:00
Jorge Manrubia 10b2aad647 Replace House with lexical-powered actiontext 2025-05-23 11:41:08 +02:00
Jorge Manrubia b0aae3ad9e Reapply "Add a description field for cards"
This reverts commit a4cc143b09.
2025-04-21 16:45:24 +02:00
Jorge Manrubia a4cc143b09 Revert "Add a description field for cards" 2025-04-21 16:41:33 +02:00
Jason Zimdars 44a5215da7 Merge branch 'main' into add-card-description
* main:
  Fix failing test (we're no longer redirecting here
  Display the empty message via CSS when there are no unread notifications
  Hide Previously Seen section when empty with CSS
2025-04-17 17:08:49 -05:00
Jason Zimdars c61fa77d6b Fix failing test (we're no longer redirecting here
See: #411
2025-04-17 17:03:18 -05:00
Jason Zimdars 47d0ae98a1 Remove DraftCommenting 2025-04-16 19:01:21 -05:00
David Heinemeier Hansson dbf61f4fc3 Use _path in all cases where we are not potentially changing the domain 2025-04-13 08:17:36 +02:00
Jason Zimdars aa7694ce7b Update fixtures and test 2025-04-09 17:28:24 -05:00
Jorge Manrubia 723e6d94f5 Rename bubbles => cards 2025-04-09 14:50:58 +02:00