From 558ea7764757cfe324bdba72fc5279fa78efd1ea Mon Sep 17 00:00:00 2001 From: erdgeist Date: Wed, 22 Jul 2026 20:03:50 +0200 Subject: Implement controller and view side of the attach logic --- app/controllers/assets_controller.rb | 22 ++++++++++++++++++++++ app/views/assets/edit.html.erb | 17 +++++++++++++++++ app/views/assets/new.html.erb | 17 +++++++++++++++++ app/views/nodes/show.html.erb | 18 ++++++++++++------ public/javascripts/admin_interface.js | 4 ++++ public/javascripts/admin_search.js | 17 +++++++++++++++++ public/stylesheets/admin.css | 7 +++---- 7 files changed, 92 insertions(+), 10 deletions(-) diff --git a/app/controllers/assets_controller.rb b/app/controllers/assets_controller.rb index becfe133..fbede0a7 100644 --- a/app/controllers/assets_controller.rb +++ b/app/controllers/assets_controller.rb @@ -28,6 +28,7 @@ class AssetsController < ApplicationController # GET /assets/new.xml def new @asset = Asset.new + @attach_node = Node.not_in_trash.find_by(:id => params[:node_id]) if params[:node_id].present? respond_to do |format| format.html # new.html.erb @@ -44,10 +45,12 @@ class AssetsController < ApplicationController # POST /assets.xml def create @asset = Asset.new(asset_params) + attach_node = Node.not_in_trash.find_by(:id => params[:node_id]) if params[:node_id].present? respond_to do |format| if @asset.save flash[:notice] = 'Asset was successfully created.' + attach_to(attach_node) if attach_node format.html { redirect_to(@asset) } format.xml { render :xml => @asset, :status => :created, :location => @asset } else @@ -91,4 +94,23 @@ class AssetsController < ApplicationController def asset_params params.require(:asset).permit(:name, :upload, :creator, :source_url, :license_key) end + + def attach_to node + result = node.attach_asset!(@asset, :user => current_user, + :headline => params[:headline].present?) + flash[:notice] = + if result[:attached].zero? + "Asset saved — it was already attached to “#{node.title}”." + else + "Asset was successfully created and attached to “#{node.title}”." + end + case result[:headline] + when :set then flash[:notice] += " It is now the page's headline." + when :kept_existing then flash[:headline_kept_path] = node_path(node) + when :not_eligible then flash[:error] = "This asset type cannot be a headline." + end + rescue LockedByAnotherUser + flash[:locked_by] = node.lock_owner&.login + flash[:locked_node_path] = node_path(node) + end end diff --git a/app/views/assets/edit.html.erb b/app/views/assets/edit.html.erb index 3ef8fea5..0c1dd8fe 100644 --- a/app/views/assets/edit.html.erb +++ b/app/views/assets/edit.html.erb @@ -31,6 +31,23 @@ ) %> +
attach to page
+
+
+ <%= text_field_tag :asset_node_search_term, @attach_node&.title, + :placeholder => "Search for a page…", :autocomplete => "off" %> + +
+ <%= hidden_field_tag :node_id, @attach_node&.id %> + Optional — attaches this asset to that page, all pending versions included. +
+ +
+
+ + Applies only if the page has no headline yet. +
+
Actions
diff --git a/app/views/assets/new.html.erb b/app/views/assets/new.html.erb index 2cf88650..7bded949 100644 --- a/app/views/assets/new.html.erb +++ b/app/views/assets/new.html.erb @@ -26,6 +26,23 @@ ) %>
+
attach to page
+
+
+ <%= text_field_tag :asset_node_search_term, @attach_node&.title, + :placeholder => "Search for a page…", :autocomplete => "off" %> + +
+ <%= hidden_field_tag :node_id, @attach_node&.id %> + Optional — attaches this asset to that page, all pending versions included. +
+ +
+
+ + Applies only if the page has no headline yet. +
+
Actions
diff --git a/app/views/nodes/show.html.erb b/app/views/nodes/show.html.erb index adf79dd8..b981e4b0 100644 --- a/app/views/nodes/show.html.erb +++ b/app/views/nodes/show.html.erb @@ -253,10 +253,10 @@ <% end %>
- <% if @page.assets.any? %> - <% headline_asset_id = @page.headline_asset&.id %> -
Images
-
+
Attachments
+
+ <% if @page.assets.any? %> + <% headline_asset_id = @page.headline_asset&.id %>
    <% @page.assets.each do |asset| %>
  • "> @@ -269,8 +269,14 @@
  • <% end %>
-
- <% end %> + <% end %> +

+ <%= link_to new_asset_path(:node_id => @node.id), class: 'action_button' do %> + <%= icon("paperclip", library: "tabler", "aria-hidden": true) %> Upload new attachment + <% end %> + To add or remove existing attachments, edit this node instead. +

+
Events
diff --git a/public/javascripts/admin_interface.js b/public/javascripts/admin_interface.js index 64da5a86..5514f3b3 100644 --- a/public/javascripts/admin_interface.js +++ b/public/javascripts/admin_interface.js @@ -65,6 +65,10 @@ $(document).ready(function () { related_assets.initialize(); } + if ($("#asset_node_search_term").length != 0) { + asset_node_search.initialize_search(); + } + if ($("#rrule_builder").length != 0) { rrule_builder.initialize(); } diff --git a/public/javascripts/admin_search.js b/public/javascripts/admin_search.js index ad368cbe..792849f7 100644 --- a/public/javascripts/admin_search.js +++ b/public/javascripts/admin_search.js @@ -286,3 +286,20 @@ event_search = { }); } }; + +asset_node_search = { + initialize_search : function() { + initSearchPicker({ + inputSelector: "#asset_node_search_term", + resultsSelector: "#asset_node_search_results", + onSelect: function(node) { + $("#asset_node_search_term").val(node.title); + $("#node_id").val(node.node_id); + } + }); + + $("#asset_node_search_term").bind("input", function() { + if ($(this).val() === "") { $("#node_id").val(""); } + }); + } +}; diff --git a/public/stylesheets/admin.css b/public/stylesheets/admin.css index b69b1780..9f737752 100644 --- a/public/stylesheets/admin.css +++ b/public/stylesheets/admin.css @@ -831,12 +831,11 @@ form.button_to button[type="submit"] { /* Layout only -- the at-rest visibility (wavy underline) for these links comes from the scoped rule in Base elements above. */ +.add_events, +.add_attachments, .add_child_links { margin-top: 0.5rem; -} - -.add_child_links a { - white-space: nowrap; + margin-bottom: 0; } .sitemap_node { -- cgit v1.3