Add drag-and-drop positioning for categories scoped by category type#712
Add drag-and-drop positioning for categories scoped by category type#712
Conversation
|
@jmilljr24 lgtm, but you have more context on gem implementation. main thing is scoping the position uniqueness to within the CategoryType (via metadatum_id, until that table gets renamed and it can be category_type_id) i've got a separate pr to fix the allow_nil in the category model. |
Awesome! Yes, scoping is a great feature!! |
|
Check out the stimulus controller we have |
There was a problem hiding this comment.
@maebeale Love this feature. Can you update the stimulus sortable controller to send the param as position: instead of ordering: I missed it when we changed everything over to the same column name. Faq is broken at the moment.
body: JSON.stringify({ position: newIndex + 1 })
Once merged we can just run Category.heal_position_column! in production to dedup positions and remove the default value.
| if params[:ordering].present? | ||
| ordering = params[:ordering] | ||
| # Validate ordering is a valid positive integer | ||
| if ordering.to_s.match?(/^\d+$/) && (ordering = ordering.to_i) > 0 | ||
| if @category.update(position: ordering) | ||
| head :ok | ||
| else | ||
| head :unprocessable_entity | ||
| end | ||
| else | ||
| head :bad_request | ||
| end | ||
| return | ||
| end |
There was a problem hiding this comment.
Shouldn't need this. @category.update(category_params) should do the trick and the position gem will handle validation.
There was a problem hiding this comment.
@jmilljr24 i removed it and the UI stopped working and my tests were failing, so i'm going to keep it for now and figure out how to remove it later.
There was a problem hiding this comment.
nvm. i see now it's bc of the stimulus controller sending ordering param instead of position!
7e07d0e to
f6ce54f
Compare
| const url = this.urlValue.replace(":id", id); | ||
| put(url, { | ||
| body: JSON.stringify({ ordering: newIndex + 1 }), // add 1 to change sortablejs 0-based index to 1-based for positioning gem | ||
| body: JSON.stringify({ position: newIndex + 1 }), // add 1 to change sortablejs 0-based index to 1-based for positioning gem |
b9168e5 to
17a4876
Compare
Co-authored-by: maebeale <7607813+maebeale@users.noreply.github.com>
Co-authored-by: maebeale <7607813+maebeale@users.noreply.github.com>
…coverage Co-authored-by: maebeale <7607813+maebeale@users.noreply.github.com>
…rmatting Co-authored-by: maebeale <7607813+maebeale@users.noreply.github.com>
* note * Small fixes
… as the column did
…me (tho no positions should match using position gem)
17a4876 to
3b9e531
Compare
| " user authentication", required: true | ||
| param :sector, String, desc: "One of #{Sector.all.pluck(:name).join(', ')}" | ||
| # param :sector, String, desc: "One of #{Sector.all.pluck(:name).join(', ')}" | ||
| param :sector, String, desc: "Sector name" |
There was a problem hiding this comment.
this was blowing up after upgrading ruby
| render :edit, status: :unprocessable_content | ||
| respond_to do |format| | ||
| if @category.update(category_params) | ||
| format.html { redirect_to categories_path, notice: "Category was successfully updated.", status: :see_other } |
| @@ -1,16 +1,25 @@ | |||
| class Category < ApplicationRecord | |||
| include NameFilterable | |||
| include Positioning | |||
There was a problem hiding this comment.
I don't think so. I don't see any reference in the doc's of having to include anything. just the basic positioned method is all thats needed. Then anything extra for scopes etc.
| t.string "country" | ||
| t.string "device_type" | ||
| t.string "ip" | ||
| t.text "landing_page", size: :medium |
There was a problem hiding this comment.
i thought we'd gotten out of this back and forth :(
There was a problem hiding this comment.
from production
create_table "ahoy_visits", charset: "utf8mb4", collation: "utf8mb4_unicode_ci", force: :cascade do |t|
t.string "app_version"
t.string "browser"
t.string "city"
t.string "country"
t.string "device_type"
t.string "ip"
t.text "landing_page", size: :medium
There was a problem hiding this comment.
The change you pushed seemed to at least fix the charset and collation changes in my db, so progress!
| end | ||
|
|
||
| add_foreign_key "action_text_mentions", "action_text_rich_texts" | ||
| add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id" |
There was a problem hiding this comment.
@jmilljr24 is this odd to be removed from schema?
There was a problem hiding this comment.
Yeah, not sure why thats happening. Looking at the schema.rb file generate in the production server, that line is in there.
| it "orders categories by position first, then by name" do | ||
| cat_c_pos_30 = create(:category, name: "C Category", position: 30, category_type: category_type) | ||
| cat_a_pos_1 = create(:category, name: "A Category", position: 1, category_type: category_type) | ||
| cat_b_pos_1 = create(:category, name: "B Category", position: 1, category_type: category_type) |
There was a problem hiding this comment.
don't need two 1's anymore, since that's now invalid
| assert_select "form[action=?][method=?]", categories_path, "post" do | ||
| assert_select "input[name=?]", "category[name]" | ||
| assert_select "select[name=?]", "category[metadatum_id]" | ||
| assert_select "input[name=?][type=number]", "category[position]" |
There was a problem hiding this comment.
it's no longer editable in the UI
What is the goal of this PR and why is this important?
Implements drag-and-drop reordering for categories on the categories index page, matching the existing FAQ implementation. Positions are scoped to
metadatum_id(category_type) so categories of different types maintain independent position sequences.How did you approach the change?
Model (
category.rb)positioned scope: :metadatum_idto enable position management per category typeController (
categories_controller.rb)orderingparameter inupdateaction for drag-and-drop position updatesView (
categories/index.html.erb)data-sortable-handleicondata-controller="sortable"anddata-sortable-url-valueto tbodydata-sortable-idto each rowTests
Reuses existing
sortable_controller.jsStimulus controller andpositioninggem (v0.4.7).Anything else to add?
Position updates work across paginated results since the positioning gem handles server-side state. Categories can share position values across different category types due to the metadatum_id scope.
Original prompt
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.