diff options
| author | erdgeist <erdgeist@erdgeist.org> | 2026-08-09 13:26:23 +0200 |
|---|---|---|
| committer | erdgeist <erdgeist@erdgeist.org> | 2026-08-09 13:26:23 +0200 |
| commit | 616a0d2d2ba15a7e176938ee829d60366fb6a9c2 (patch) | |
| tree | fe12e0ab804948f0e3ff37636859b05cef7871cc | |
| parent | 42b996e9197680a1955cfa5639462908677e5a94 (diff) | |
Attach an asset to a page from the asset's own page
The picker moves from assets/edit to assets/show, where the list of attached
pages already is.
A member route, POST assets/:id/attach_to_node, replaces the ride on #update.
Supersedes the picker wiring in the previous commit; what remains of it is
@attach_node in #create, the flash composition and the corrected hint.
| -rw-r--r-- | app/controllers/assets_controller.rb | 16 | ||||
| -rw-r--r-- | app/views/assets/edit.html.erb | 17 | ||||
| -rw-r--r-- | app/views/assets/show.html.erb | 11 | ||||
| -rw-r--r-- | config/locales/de.yml | 2 | ||||
| -rw-r--r-- | config/locales/en.yml | 2 | ||||
| -rw-r--r-- | config/routes.rb | 7 | ||||
| -rw-r--r-- | test/controllers/assets_controller_test.rb | 34 |
7 files changed, 56 insertions, 33 deletions
diff --git a/app/controllers/assets_controller.rb b/app/controllers/assets_controller.rb index e58f4f30..4b27d1c4 100644 --- a/app/controllers/assets_controller.rb +++ b/app/controllers/assets_controller.rb | |||
| @@ -38,7 +38,6 @@ class AssetsController < ApplicationController | |||
| 38 | # GET /assets/1/edit | 38 | # GET /assets/1/edit |
| 39 | def edit | 39 | def edit |
| 40 | @asset = Asset.find(params[:id]) | 40 | @asset = Asset.find(params[:id]) |
| 41 | @attach_node = Node.not_in_trash.find_by(:id => params[:node_id]) if params[:node_id].present? | ||
| 42 | end | 41 | end |
| 43 | 42 | ||
| 44 | # POST /assets | 43 | # POST /assets |
| @@ -69,7 +68,6 @@ class AssetsController < ApplicationController | |||
| 69 | # PUT /assets/1.xml | 68 | # PUT /assets/1.xml |
| 70 | def update | 69 | def update |
| 71 | @asset = Asset.find(params[:id]) | 70 | @asset = Asset.find(params[:id]) |
| 72 | @attach_node = Node.not_in_trash.find_by(:id => params[:node_id]) if params[:node_id].present? | ||
| 73 | 71 | ||
| 74 | respond_to do |format| | 72 | respond_to do |format| |
| 75 | if @asset.update(asset_params) | 73 | if @asset.update(asset_params) |
| @@ -102,6 +100,20 @@ class AssetsController < ApplicationController | |||
| 102 | end | 100 | end |
| 103 | end | 101 | end |
| 104 | 102 | ||
| 103 | # POST /assets/1/attach_to_node | ||
| 104 | def attach_to_node | ||
| 105 | @asset = Asset.find(params[:id]) | ||
| 106 | node = Node.not_in_trash.find_by(:id => params[:node_id]) | ||
| 107 | |||
| 108 | if node | ||
| 109 | attach_to(node) | ||
| 110 | else | ||
| 111 | flash[:error] = t("flash.assets.attach_no_node") | ||
| 112 | end | ||
| 113 | |||
| 114 | redirect_to(asset_path(@asset)) | ||
| 115 | end | ||
| 116 | |||
| 105 | private | 117 | private |
| 106 | 118 | ||
| 107 | def asset_params | 119 | def asset_params |
diff --git a/app/views/assets/edit.html.erb b/app/views/assets/edit.html.erb index 5214e082..610ae20a 100644 --- a/app/views/assets/edit.html.erb +++ b/app/views/assets/edit.html.erb | |||
| @@ -36,23 +36,6 @@ | |||
| 36 | ) %> | 36 | ) %> |
| 37 | </div> | 37 | </div> |
| 38 | 38 | ||
| 39 | <div class="layout_row_label"><%= t("assets.form.attach_to_page") %></div> | ||
| 40 | <div class="layout_row_content"> | ||
| 41 | <div class="restore_picker"> | ||
| 42 | <%= text_field_tag :asset_node_search_term, @attach_node&.title, | ||
| 43 | :placeholder => t("assets.form.attach_search_placeholder"), :autocomplete => "off" %> | ||
| 44 | <div id="asset_node_search_results" class="search_results" style="display: none"></div> | ||
| 45 | </div> | ||
| 46 | <%= hidden_field_tag :node_id, @attach_node&.id %> | ||
| 47 | <span class="field_hint"><%= t("assets.form.attach_hint") %></span> | ||
| 48 | </div> | ||
| 49 | |||
| 50 | <div class="layout_row_label"></div> | ||
| 51 | <div class="layout_row_content"> | ||
| 52 | <label><%= check_box_tag :headline, "1" %> <%= t("assets.form.as_headline") %></label> | ||
| 53 | <span class="field_hint"><%= t("assets.form.headline_hint") %></span> | ||
| 54 | </div> | ||
| 55 | |||
| 56 | <div class="layout_row_label"><%= t("admin.columns.actions") %></div> | 39 | <div class="layout_row_label"><%= t("admin.columns.actions") %></div> |
| 57 | <div class="layout_row_content info_group"> | 40 | <div class="layout_row_content info_group"> |
| 58 | <div class="info_group_items"> | 41 | <div class="info_group_items"> |
diff --git a/app/views/assets/show.html.erb b/app/views/assets/show.html.erb index d76d312b..f31d34e1 100644 --- a/app/views/assets/show.html.erb +++ b/app/views/assets/show.html.erb | |||
| @@ -47,6 +47,17 @@ | |||
| 47 | <%= link_to new_node_path(:asset_id => @asset.id), :class => "action_button" do %> | 47 | <%= link_to new_node_path(:asset_id => @asset.id), :class => "action_button" do %> |
| 48 | <%= icon("file-plus", library: "tabler", "aria-hidden": true) %> <%= t(".new_page_with_attachment") %> | 48 | <%= icon("file-plus", library: "tabler", "aria-hidden": true) %> <%= t(".new_page_with_attachment") %> |
| 49 | <% end %> | 49 | <% end %> |
| 50 | <%= form_tag attach_to_node_asset_path(@asset), :class => "asset_attach_form" do %> | ||
| 51 | <div class="restore_picker"> | ||
| 52 | <%= text_field_tag :asset_node_search_term, nil, | ||
| 53 | :placeholder => t("assets.form.attach_search_placeholder"), :autocomplete => "off" %> | ||
| 54 | <div id="asset_node_search_results" class="search_results" style="display: none"></div> | ||
| 55 | </div> | ||
| 56 | <%= hidden_field_tag :node_id, nil %> | ||
| 57 | <label><%= check_box_tag :headline, "1" %> <%= t("assets.form.as_headline") %></label> | ||
| 58 | <%= submit_tag t(".attach_button") %> | ||
| 59 | <span class="field_hint"><%= t("assets.form.attach_hint") %></span> | ||
| 60 | <% end %> | ||
| 50 | </div> | 61 | </div> |
| 51 | 62 | ||
| 52 | <div class="layout_row_label"><%= t(".public_path") %></div> | 63 | <div class="layout_row_label"><%= t(".public_path") %></div> |
diff --git a/config/locales/de.yml b/config/locales/de.yml index aab46169..e410e519 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml | |||
| @@ -659,6 +659,7 @@ de: | |||
| 659 | already_attached: "Es war bereits an „%{title}“ angehängt." | 659 | already_attached: "Es war bereits an „%{title}“ angehängt." |
| 660 | attached_to_draft: "Zum Entwurf von %{title} hinzugefügt. Zum Veröffentlichen den Entwurf freigeben." | 660 | attached_to_draft: "Zum Entwurf von %{title} hinzugefügt. Zum Veröffentlichen den Entwurf freigeben." |
| 661 | attached_new_draft: "Entwurf von %{title} mit diesem Anhang angelegt. Zum Veröffentlichen den Entwurf freigeben." | 661 | attached_new_draft: "Entwurf von %{title} mit diesem Anhang angelegt. Zum Veröffentlichen den Entwurf freigeben." |
| 662 | attach_no_node: "Es wurde keine Seite ausgewählt, es wurde nichts angehängt." | ||
| 662 | events: | 663 | events: |
| 663 | created: "Termin wurde angelegt." | 664 | created: "Termin wurde angelegt." |
| 664 | updated: "Termin wurde aktualisiert." | 665 | updated: "Termin wurde aktualisiert." |
| @@ -703,6 +704,7 @@ de: | |||
| 703 | pending_only: "nur in ausstehenden Versionen" | 704 | pending_only: "nur in ausstehenden Versionen" |
| 704 | not_attached: "— an keine Seite angehängt —" | 705 | not_attached: "— an keine Seite angehängt —" |
| 705 | new_page_with_attachment: "Neue Seite mit diesem Anhang" | 706 | new_page_with_attachment: "Neue Seite mit diesem Anhang" |
| 707 | attach_button: "Anhängen" | ||
| 706 | public_path: "Öffentlicher Pfad" | 708 | public_path: "Öffentlicher Pfad" |
| 707 | copy_url: "URL kopieren" | 709 | copy_url: "URL kopieren" |
| 708 | creator: "Urheber" | 710 | creator: "Urheber" |
diff --git a/config/locales/en.yml b/config/locales/en.yml index 8da079dc..f8f586b9 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml | |||
| @@ -627,6 +627,7 @@ en: | |||
| 627 | already_attached: "It was already attached to “%{title}”." | 627 | already_attached: "It was already attached to “%{title}”." |
| 628 | attached_to_draft: "Attached to the draft of %{title}. Publish it to make the change live." | 628 | attached_to_draft: "Attached to the draft of %{title}. Publish it to make the change live." |
| 629 | attached_new_draft: "Created a draft of %{title} with this attachment. Publish it to make the change live." | 629 | attached_new_draft: "Created a draft of %{title} with this attachment. Publish it to make the change live." |
| 630 | attach_no_node: "No page was chosen, so nothing was attached." | ||
| 630 | events: | 631 | events: |
| 631 | created: "Event was successfully created." | 632 | created: "Event was successfully created." |
| 632 | updated: "Event was successfully updated." | 633 | updated: "Event was successfully updated." |
| @@ -670,6 +671,7 @@ en: | |||
| 670 | attached_to: "Attached to" | 671 | attached_to: "Attached to" |
| 671 | pending_only: "pending versions only" | 672 | pending_only: "pending versions only" |
| 672 | not_attached: "— not attached to any page —" | 673 | not_attached: "— not attached to any page —" |
| 674 | attach_button: "Attach" | ||
| 673 | new_page_with_attachment: "New page with this attachment" | 675 | new_page_with_attachment: "New page with this attachment" |
| 674 | public_path: "Public Path" | 676 | public_path: "Public Path" |
| 675 | copy_url: "Copy URL" | 677 | copy_url: "Copy URL" |
diff --git a/config/routes.rb b/config/routes.rb index a43769e6..e123a3fe 100644 --- a/config/routes.rb +++ b/config/routes.rb | |||
| @@ -26,7 +26,12 @@ Cccms::Application.routes.draw do | |||
| 26 | 26 | ||
| 27 | scope '/admin' do | 27 | scope '/admin' do |
| 28 | resources :events | 28 | resources :events |
| 29 | resources :assets | 29 | |
| 30 | resources :assets do | ||
| 31 | member do | ||
| 32 | post :attach_to_node | ||
| 33 | end | ||
| 34 | end | ||
| 30 | 35 | ||
| 31 | resources :nodes do | 36 | resources :nodes do |
| 32 | collection do | 37 | collection do |
diff --git a/test/controllers/assets_controller_test.rb b/test/controllers/assets_controller_test.rb index c2d7ad57..67f629d9 100644 --- a/test/controllers/assets_controller_test.rb +++ b/test/controllers/assets_controller_test.rb | |||
| @@ -163,19 +163,6 @@ class AssetsControllerTest < ActionController::TestCase | |||
| 163 | assert_equal users(:quentin), action.user | 163 | assert_equal users(:quentin), action.user |
| 164 | end | 164 | end |
| 165 | 165 | ||
| 166 | test "update with node_id attaches the asset to the node's draft" do | ||
| 167 | node = Node.root.children.create!(:slug => "asset_update_attach") | ||
| 168 | asset = Asset.create!(:name => "Existing", :upload_content_type => "image/png") | ||
| 169 | |||
| 170 | put :update, params: { id: asset.id, asset: { name: "Existing" }, node_id: node.id } | ||
| 171 | |||
| 172 | assert_response :redirect | ||
| 173 | assert_includes node.draft.assets.reload, asset | ||
| 174 | assert_equal [I18n.t("flash.assets.updated"), | ||
| 175 | I18n.t("flash.assets.attached_to_draft", :title => node.title)].join(" "), | ||
| 176 | flash[:notice] | ||
| 177 | end | ||
| 178 | |||
| 179 | # --- edit --- | 166 | # --- edit --- |
| 180 | 167 | ||
| 181 | test "get edit" do | 168 | test "get edit" do |
| @@ -235,6 +222,27 @@ class AssetsControllerTest < ActionController::TestCase | |||
| 235 | assert_equal users(:quentin), NodeAction.last.user | 222 | assert_equal users(:quentin), NodeAction.last.user |
| 236 | end | 223 | end |
| 237 | 224 | ||
| 225 | test "attach_to_node attaches the asset to the node's draft" do | ||
| 226 | node = Node.root.children.create!(:slug => "asset_show_attach") | ||
| 227 | asset = Asset.create!(:name => "From the asset page", :upload_content_type => "image/png") | ||
| 228 | |||
| 229 | post :attach_to_node, params: { id: asset.id, node_id: node.id } | ||
| 230 | |||
| 231 | assert_redirected_to asset_path(asset) | ||
| 232 | assert_includes node.draft.assets.reload, asset | ||
| 233 | assert_equal I18n.t("flash.assets.attached_to_draft", :title => node.title), flash[:notice] | ||
| 234 | end | ||
| 235 | |||
| 236 | test "attach_to_node without a node says so and attaches nothing" do | ||
| 237 | asset = Asset.create!(:name => "Unpicked", :upload_content_type => "image/png") | ||
| 238 | |||
| 239 | post :attach_to_node, params: { id: asset.id } | ||
| 240 | |||
| 241 | assert_redirected_to asset_path(asset) | ||
| 242 | assert_equal I18n.t("flash.assets.attach_no_node"), flash[:error] | ||
| 243 | assert_empty asset.related_assets.reload | ||
| 244 | end | ||
| 245 | |||
| 238 | # --- URL helpers --- | 246 | # --- URL helpers --- |
| 239 | 247 | ||
| 240 | test "upload url returns correct path for original" do | 248 | test "upload url returns correct path for original" do |
