Finish MVP for content editing
This commit is contained in:
		
							parent
							
								
									6713665a61
								
							
						
					
					
						commit
						6014134396
					
				
							
								
								
									
										30
									
								
								app/components/edit_content_button_component.html.erb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								app/components/edit_content_button_component.html.erb
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,30 @@ | ||||
| <div class="inline-block text-left" data-controller="modal" data-action="keydown.esc->modal#close"> | ||||
|   <button class="btn-md btn-outline text-red-600" data-action="click->modal#open" title="Edit"> | ||||
|     <%= content || "Edit" %> | ||||
|   </button> | ||||
| 
 | ||||
|   <%= render ModalComponent.new(show_close_button: false) do %> | ||||
|     <%= form_with model: [:admin, @editable_content], | ||||
|                   html: { autocomplete: "off" } do |form| %> | ||||
|       <%= form.hidden_field :redirect_to, value: @redirect_to  %> | ||||
|       <p class="mb-2"> | ||||
|         <%= form.label :content, @editable_content.key.capitalize, class: 'font-bold' %> | ||||
|       </p> | ||||
|       <% if @editable_content.rich_text %> | ||||
|         <p> | ||||
|           <%= form.textarea :content, class: "md:w-[56rem] md:h-[28rem]" %> | ||||
|         </p> | ||||
|         <p class="text-right"> | ||||
|           <%= form.submit "Save", class: "ml-2 btn-md btn-blue" %> | ||||
|         </p> | ||||
|       <% else %> | ||||
|         <p class=""> | ||||
|           <%= form.text_field :content, class: "w-80" %> | ||||
|         </p> | ||||
|         <p> | ||||
|           <%= form.submit "Save", class: "btn-md btn-blue w-full" %> | ||||
|         </p> | ||||
|       <% end %> | ||||
|     <% end %> | ||||
|   <% end %> | ||||
| </div> | ||||
							
								
								
									
										6
									
								
								app/components/edit_content_button_component.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								app/components/edit_content_button_component.rb
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | ||||
| class EditContentButtonComponent < ViewComponent::Base | ||||
|   def initialize(context:, key:, rich_text: false, redirect_to: nil) | ||||
|     @editable_content = EditableContent.find_or_create_by(context:, key:, rich_text:) | ||||
|     @redirect_to = redirect_to | ||||
|   end | ||||
| end | ||||
							
								
								
									
										9
									
								
								app/components/editable_content_component.html.erb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								app/components/editable_content_component.html.erb
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | ||||
| <% if @editable_content.has_content? %> | ||||
|   <% if @editable_content.rich_text %> | ||||
|     <%= helpers.markdown_to_html @editable_content.content %> | ||||
|   <% else %> | ||||
|     <%= @editable_content.content %> | ||||
|   <% end %> | ||||
| <% else %> | ||||
|   <%= @default %> | ||||
| <% end %> | ||||
							
								
								
									
										6
									
								
								app/components/editable_content_component.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								app/components/editable_content_component.rb
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | ||||
| class EditableContentComponent < ViewComponent::Base | ||||
|   def initialize(context:, key:, rich_text: false, default: nil) | ||||
|     @editable_content = EditableContent.find_or_create_by(context:, key:, rich_text:) | ||||
|     @default = default | ||||
|   end | ||||
| end | ||||
| @ -16,8 +16,14 @@ class Admin::EditableContentsController < Admin::BaseController | ||||
|   end | ||||
| 
 | ||||
|   def update | ||||
|     return_to = params[:editable_content][:redirect_to].presence | ||||
| 
 | ||||
|     if @editable_content.update(content_params) | ||||
|       render json: { status: "success", message: "Content updated" }, status: :ok | ||||
|       if return_to | ||||
|         redirect_to return_to | ||||
|       else | ||||
|         render status: :ok | ||||
|       end | ||||
|     else | ||||
|       render :edit, status: :unprocessable_entity | ||||
|     end | ||||
|  | ||||
| @ -4,12 +4,6 @@ class Contributions::OtherController < ApplicationController | ||||
| 
 | ||||
|   # GET /contributions/other | ||||
|   def index | ||||
|     @content_title = EditableContent.find_or_create_by( | ||||
|       path: "contributions/other", key: "title" | ||||
|     ) | ||||
|     @content_body = EditableContent.find_or_create_by( | ||||
|       path: "contributions/other", key: "body", rich_text: true | ||||
|     ) | ||||
|     @current_section = :contributions | ||||
|   end | ||||
| 
 | ||||
|  | ||||
| @ -15,6 +15,10 @@ module ApplicationHelper | ||||
|     tag.span text, class: "inline-flex items-center rounded-full bg-#{color}-100 px-2.5 py-0.5 text-xs font-medium text-#{color}-800" | ||||
|   end | ||||
| 
 | ||||
|   def markdown_to_html(string) | ||||
|     raw Kramdown::Document.new(string, { input: "GFM" }).to_html | ||||
|   end | ||||
| 
 | ||||
|   def image_url_for(attachment) | ||||
|     return s3_image_url(attachment) if Setting.s3_enabled? | ||||
| 
 | ||||
|  | ||||
| @ -1,10 +0,0 @@ | ||||
| module EditableContentHelper | ||||
|   def editable_content_for(path, key, default: nil, create_rich: false) | ||||
|     @content = EditableContent.find_by(path: "contributions/other", key: key) | ||||
|     @content.content.present? ? @content.content : default | ||||
|   end | ||||
| 
 | ||||
|   def markdown_to_html(string) | ||||
|     raw Kramdown::Document.new(string, { input: "GFM" }).to_html | ||||
|   end | ||||
| end | ||||
| @ -1,4 +1,12 @@ | ||||
| class EditableContent < ApplicationRecord | ||||
|   validates :key, presence: true, | ||||
|                   uniqueness: { scope: :path } | ||||
|                   uniqueness: { scope: :context } | ||||
| 
 | ||||
|   def has_content? | ||||
|     content.present? | ||||
|   end | ||||
| 
 | ||||
|   def is_empty? | ||||
|     content.blank? | ||||
|   end | ||||
| end | ||||
|  | ||||
| @ -1,42 +1,20 @@ | ||||
| <%= render HeaderComponent.new(title: "Contributions") %> | ||||
| 
 | ||||
| <%= render MainWithTabnavComponent.new(tabnav_partial: "shared/tabnav_contributions") do %> | ||||
|   <% if @edit_content %> | ||||
|     <section> | ||||
|       <%= form_with model: [:admin, @content_title] do |form| %> | ||||
|         <p class="mb-2"> | ||||
|           <%= form.label :content, @content_title.key.capitalize, class: 'font-bold' %> | ||||
|         </p> | ||||
|         <p class="flex gap-1"> | ||||
|           <%= form.text_field :content %> | ||||
|           <%# <%= form.submit "Save", class: "btn-md btn-blue" %> | ||||
|           <%= button_tag type: 'submit', name: nil, title: "Save", class: 'btn-md btn-icon btn-outline' do %> | ||||
|             <%= render partial: "icons/save", locals: { custom_class: "text-blue-600 h-4 w-4 inline" } %> | ||||
|           <% end %> | ||||
|         </p> | ||||
|       <% end %> | ||||
|     </section> | ||||
|     <section> | ||||
|       <%= form_with model: [:admin, @content_body] do |form| %> | ||||
|         <p class="mb-2"> | ||||
|           <%= form.label :content, @content_body.key.capitalize, class: 'font-bold' %> | ||||
|         </p> | ||||
|         <p> | ||||
|           <%= form.textarea :content, class: "w-full h-96" %> | ||||
|         </p> | ||||
|         <p class="text-right"> | ||||
|           <%= link_to 'Cancel', request.path, class: 'btn-md btn-gray' %> | ||||
|           <%= form.submit "Save", class: "ml-2 btn-md btn-blue" %> | ||||
|         </p> | ||||
|       <% end %> | ||||
|     </section> | ||||
|   <% else %> | ||||
|     <section> | ||||
|       <% if @content_body.content.present? %> | ||||
|         <%= markdown_to_html @content_body.content %> | ||||
|       <% else %> | ||||
|         No content yet | ||||
|       <% end %> | ||||
|     </section> | ||||
|   <% end %> | ||||
|   <section> | ||||
|     <%= render EditableContentComponent.new( | ||||
|       context: "contributions/other", key: "body", rich_text: true, | ||||
|       default: "No content yet") %> | ||||
| 
 | ||||
|     <% if current_user.is_admin? %> | ||||
|     <div class="mt-8 pt-6 border-t border-gray-200 text-right"> | ||||
|       <%= render EditContentButtonComponent.new( | ||||
|         context: "contributions/other", key: "title", | ||||
|         redirect_to: request.path) do %>Edit title<% end %> | ||||
|       <%= render EditContentButtonComponent.new( | ||||
|         context: "contributions/other", key: "body", rich_text: true, | ||||
|         redirect_to: request.path) do %>Edit content<% end %> | ||||
|     </div> | ||||
|     <% end %> | ||||
|   </section> | ||||
| <% end %> | ||||
|  | ||||
| @ -6,7 +6,9 @@ | ||||
|       active: current_page?(contributions_donations_path) | ||||
|     ) %> | ||||
|     <%= render TabnavLinkComponent.new( | ||||
|       name: editable_content_for("contributions/other", "title", default: "Other"), | ||||
|       name: render(EditableContentComponent.new( | ||||
|         context: "contributions/other", key: "title", default: "Other" | ||||
|       )), | ||||
|       path: contributions_other_path, | ||||
|       active: current_page?(contributions_other_path) | ||||
|     ) %> | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| class CreateEditableContents < ActiveRecord::Migration[8.0] | ||||
|   def change | ||||
|     create_table :editable_contents do |t| | ||||
|       t.string :path | ||||
|       t.string :context | ||||
|       t.string :key | ||||
|       t.string :lang, default: "en" | ||||
|       t.text :content | ||||
|  | ||||
| @ -65,7 +65,7 @@ ActiveRecord::Schema[8.0].define(version: 2025_05_28_092931) do | ||||
|   end | ||||
| 
 | ||||
|   create_table "editable_contents", force: :cascade do |t| | ||||
|     t.string "path" | ||||
|     t.string "context" | ||||
|     t.string "key" | ||||
|     t.string "lang", default: "en" | ||||
|     t.text "content" | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user