diff --git a/app/controllers/story_ideas_controller.rb b/app/controllers/story_ideas_controller.rb index a99572a7c..d5be5f52a 100644 --- a/app/controllers/story_ideas_controller.rb +++ b/app/controllers/story_ideas_controller.rb @@ -110,7 +110,9 @@ def set_form_variables @organizations = (@user || current_user)&.organizations&.order(:name) || Organization.none @windows_types = WindowsType.all - @workshops = authorized_scope(Workshop.all).includes(:windows_type).order(:title) + # Create a special "New Workshop" option + new_workshop_option = OpenStruct.new(id: "new", type_name: "New Workshop") + @workshops = [ new_workshop_option ] + authorized_scope(Workshop.all).includes(:windows_type).order(:title).to_a users = authorized_scope(User.has_access.includes(:person)) users = users.or(User.where(id: @story_idea.created_by_id)) if @story_idea&.created_by_id @@ -156,7 +158,7 @@ def set_story_idea end def story_idea_params - params.require(:story_idea).permit( + permitted_params = params.require(:story_idea).permit( :title, :body, :youtube_url, :permission_given, :publish_preferences, :promoted_to_story, :windows_type_id, :organization_id, :workshop_id, :external_workshop_title, @@ -166,5 +168,12 @@ def story_idea_params primary_asset_attributes: [ :id, :file, :_destroy ], gallery_assets_attributes: [ :id, :file, :_destroy ] ) + + # Clear workshop_id if "new" was selected (triggers external_workshop_title) + if permitted_params[:workshop_id] == "new" + permitted_params[:workshop_id] = nil + end + + permitted_params end end diff --git a/app/frontend/javascript/controllers/workshop_toggle_controller.js b/app/frontend/javascript/controllers/workshop_toggle_controller.js new file mode 100644 index 000000000..a20f27473 --- /dev/null +++ b/app/frontend/javascript/controllers/workshop_toggle_controller.js @@ -0,0 +1,47 @@ +import { Controller } from "@hotwired/stimulus"; + +// Connects to data-controller="workshop-toggle" +// Handles toggling between workshop dropdown and external title field +export default class extends Controller { + static targets = ["dropdown", "externalField"]; + + connect() { + this.checkInitialState(); + } + + checkInitialState() { + const select = this.dropdownTarget.querySelector("select"); + if (select && select.value === "new") { + this.showExternalField(); + } + } + + handleChange(event) { + const value = event.target.value; + if (value === "new") { + this.showExternalField(); + } + } + + showExternalField() { + this.dropdownTarget.classList.add("hidden"); + this.externalFieldTarget.classList.remove("hidden"); + } + + showDropdown() { + this.externalFieldTarget.classList.add("hidden"); + this.dropdownTarget.classList.remove("hidden"); + + // Clear the selection back to prompt + const select = this.dropdownTarget.querySelector("select"); + if (select) { + select.value = ""; + } + + // Clear the external workshop title field + const externalField = this.externalFieldTarget.querySelector("input, textarea"); + if (externalField) { + externalField.value = ""; + } + } +} diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 4e9f8c3f5..8bb16f585 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -169,4 +169,17 @@ def us_time_zone_fundamentals ] ActiveSupport::TimeZone.us_zones.select { |z| zone_names.include?(z.name) }.sort_by { |z| zone_names.index(z.name) }.map { |z| [ z.to_s, z.name ] } end + + def workshop_selected_value(story_idea, params) + # If editing and has external title but no workshop, don't select anything + return nil if story_idea.workshop_id.nil? && story_idea.external_workshop_title.present? + + # Otherwise use param or object value + params[:workshop_id].presence || story_idea.workshop_id + end + + def show_external_workshop_field?(story_idea) + story_idea.workshop_id.nil? && story_idea.external_workshop_title.present? + end end + diff --git a/app/models/story_idea.rb b/app/models/story_idea.rb index c0124a2be..11c8768e1 100644 --- a/app/models/story_idea.rb +++ b/app/models/story_idea.rb @@ -44,6 +44,7 @@ def self.search_by_params(params) validates :body, presence: true validates :permission_given, presence: true validates :publish_preferences, presence: true + validate :workshop_or_external_title_present # Nested attributes accepts_nested_attributes_for :primary_asset, allow_destroy: true, reject_if: :all_blank @@ -83,4 +84,13 @@ def organization_locality def organization_description organization&.organization_description end + + private + + def workshop_or_external_title_present + if workshop_id.blank? && external_workshop_title.blank? + errors.add(:base, "Please select a workshop or enter an external workshop title") + end + end end + diff --git a/app/views/story_ideas/_form.html.erb b/app/views/story_ideas/_form.html.erb index 7ad4e4a4e..91e6be863 100644 --- a/app/views/story_ideas/_form.html.erb +++ b/app/views/story_ideas/_form.html.erb @@ -51,28 +51,53 @@ class: ("readonly" if promoted_to_story) } %> -