mirror of
https://github.com/we-promise/sure.git
synced 2026-04-08 23:04:49 +00:00
* fix: handle tags separately from entryable_attributes in bulk updates Tags use a join table (taggings) rather than a direct column, which means empty tag_ids clears all tags rather than meaning "no change". This caused bulk category-only edits to accidentally clear existing tags. This fix: - Removes tag_ids from entryable_attributes in Entry.bulk_update! - Adds update_tags parameter to explicitly control tag updates - Uses params.key?(:tag_ids) in controller to detect explicit tag changes - Preserves existing tags when tag_ids is not provided in the request This is a cleaner architectural solution compared to tracking "touched" state in the frontend, as it properly acknowledges the semantic difference between column attributes and join table associations. https://claude.ai/code/session_014CsmTwjteP4qJs6YZqCKnY * fix: handle tags separately in API transaction updates Apply the same pattern to the API endpoint: tags are now handled separately from entryable_attributes to distinguish between "not provided" (preserve existing tags) and "explicitly set to empty" (clear all tags). This allows API consumers to: - Update other fields without affecting tags (omit tag_ids) - Clear all tags (send tag_ids: []) - Set specific tags (send tag_ids: [id1, id2]) https://claude.ai/code/session_014CsmTwjteP4qJs6YZqCKnY * Proposed fix * fix: improve tag handling in bulk updates for transactions * fix: allow bulk edit to clear/preserve tags by omitting hidden multi-select field * PR comments * Dumb copy/paste error * Linter --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Juan José Mata <juanjo.mata@gmail.com> Co-authored-by: Juan José Mata <jjmata@jjmata.com>
28 lines
1.8 KiB
Plaintext
28 lines
1.8 KiB
Plaintext
<%= render DS::Dialog.new(variant: "drawer", frame: "bulk_transaction_edit_drawer") do |dialog| %>
|
|
<% dialog.with_header(title: "Edit transactions", data: { bulk_select_target: "bulkEditDrawerHeader" }) %>
|
|
|
|
<% dialog.with_body do %>
|
|
<%= styled_form_with url: transactions_bulk_update_path, scope: "bulk_update", class: "h-full flex flex-col justify-between gap-4", data: { turbo_frame: "_top" } do |form| %>
|
|
<div class="space-y-4">
|
|
<%= render DS::Disclosure.new(title: "Overview", open: true) do %>
|
|
<%= form.date_field :date, label: "Date", max: Date.current %>
|
|
<% end %>
|
|
|
|
<%= render DS::Disclosure.new(title: "Transactions", open: true) do %>
|
|
<div class="space-y-2">
|
|
<%= form.collection_select :category_id, Current.family.categories.alphabetically, :id, :name, { prompt: "Select a category", label: "Category", class: "text-subdued" } %>
|
|
<%= form.collection_select :merchant_id, Current.family.available_merchants.alphabetically, :id, :name, { prompt: "Select a merchant", label: "Merchant", class: "text-subdued" } %>
|
|
<%= form.select :tag_ids, Current.family.tags.alphabetically.pluck(:name, :id), { include_blank: "None", multiple: true, label: "Tags", include_hidden: false } %>
|
|
<%= form.text_area :notes, label: "Notes", placeholder: "Enter a note that will be applied to selected transactions", rows: 5 %>
|
|
</div>
|
|
<% end %>
|
|
</div>
|
|
|
|
<div class="flex justify-end gap-2 mt-auto">
|
|
<%= render DS::Button.new(text: "Cancel", variant: "ghost", data: { action: "click->DS--dialog#close" }) %>
|
|
<%= render DS::Button.new(text: "Save", data: { bulk_select_scope_param: "bulk_update", action: "bulk-select#submitBulkRequest" }) %>
|
|
</div>
|
|
<% end %>
|
|
<% end %>
|
|
<% end %>
|