Skip to content
25 changes: 25 additions & 0 deletions app/controllers/card_grants_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,31 @@ def update
redirect_to card_grant_url(@card_grant)
end

def set_index
card_grant = CardGrant.find(params[:id])
authorize card_grant

index = params[:index]

# get all the card grants as an array
card_grants = StaticPageService::Index.new(current_user:).card_grants.not_hidden.to_a

return head status: :bad_request if index < 0 || index >= card_grants.size

# switch the position *in the in-memory array*
card_grants.delete card_grant
card_grants.insert index, card_grant

# persist the sort order
ActiveRecord::Base.transaction do
card_grants.each_with_index do |cg, idx|
cg.update(sort_index: idx)
end
end

render json: card_grants.pluck(:id)
end

def clear_purpose
authorize @card_grant, :update?
@card_grant.update(purpose: nil)
Expand Down
30 changes: 30 additions & 0 deletions app/javascript/controllers/sort_card_controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Controller } from '@hotwired/stimulus'
import csrf from '../common/csrf'

export default class extends Controller {
static values = {
order: Array,
}

async sort({ detail: { oldIndex, newIndex } }) {
if (oldIndex == newIndex) return

const copy = this.orderValue

const id = copy[oldIndex]

copy.splice(oldIndex, 1)
copy.splice(newIndex, 0, id)

this.orderValue = copy

await fetch(`/grants/${id}/set_index`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-Token': csrf(),
},
body: JSON.stringify({ index: newIndex }),
})
}
}
1 change: 1 addition & 0 deletions app/models/card_grant.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
# keyword_lock :string
# merchant_lock :string
# purpose :string
# sort_index :float
# status :integer default("active"), not null
# created_at :datetime not null
# updated_at :datetime not null
Expand Down
12 changes: 10 additions & 2 deletions app/views/static_pages/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,17 @@
<% if current_user.card_grants.activated.size > 0 %>
<h2 class="heading h2 line-height-4 mt-0 ml-0 py-2 px-4 border-none">Grants</h2>

<div class="grid grid--wide mb-12">
<div
class="grid grid--wide mb-12"
data-controller="sortable sort-card"
data-sortable-append-to-value="body"
data-sort-card-order-value='<%= current_user.card_grants.includes(:stripe_card).map(&:hashid).to_json %>'
data-action="sortable:stop->sort-card#sort"
>
<% current_user.card_grants.includes(:stripe_card).activated.each do |grant| %>
Comment on lines +39 to 42
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
data-sort-card-order-value='<%= current_user.card_grants.includes(:stripe_card).map(&:hashid).to_json %>'
data-action="sortable:stop->sort-card#sort"
>
<% current_user.card_grants.includes(:stripe_card).activated.each do |grant| %>
data-sort-card-order-value='<%= current_user.card_grants.includes(:stripe_card).map(&:hashid).to_json %>'
data-action="sortable:stop->sort-card#sort">
<% current_user.card_grants.includes(:stripe_card).activated.each do |grant| %>

<%= render grant.stripe_card, headless: true, show_purpose: true, href: card_grant_path(grant) %>
<div class="draggable">
<%= render grant.stripe_card, headless: true, show_purpose: true, href: card_grant_path(grant) %>
</div>
<% end %>
</div>
<% end %>
Expand Down
1 change: 1 addition & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -655,6 +655,7 @@
post "activate"
get "spending"
post "clear_purpose"
post "set_index"
end
end

Expand Down
5 changes: 5 additions & 0 deletions db/migrate/20250621234202_add_sort_index_to_card_grants.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddSortIndexToCardGrants < ActiveRecord::Migration[7.2]
def change
add_column :card_grants, :sort_index, :float
end
end
3 changes: 2 additions & 1 deletion db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema[7.2].define(version: 2025_06_19_045020) do
ActiveRecord::Schema[7.2].define(version: 2025_06_21_234202) do
# These are extensions that must be enabled in order to support this database
enable_extension "citext"
enable_extension "pg_stat_statements"
Expand Down Expand Up @@ -432,6 +432,7 @@
t.string "keyword_lock"
t.string "purpose"
t.boolean "one_time_use"
t.float "sort_index"
t.index ["disbursement_id"], name: "index_card_grants_on_disbursement_id"
t.index ["event_id"], name: "index_card_grants_on_event_id"
t.index ["sent_by_id"], name: "index_card_grants_on_sent_by_id"
Expand Down
Loading