diff --git a/decidim-initiatives/app/commands/decidim/initiatives/create_initiative.rb b/decidim-initiatives/app/commands/decidim/initiatives/create_initiative.rb
index 5ec2e78221b85..d6b07712042d9 100644
--- a/decidim-initiatives/app/commands/decidim/initiatives/create_initiative.rb
+++ b/decidim-initiatives/app/commands/decidim/initiatives/create_initiative.rb
@@ -5,7 +5,6 @@ module Initiatives
# A command with all the business logic that creates a new initiative.
class CreateInitiative < Decidim::Command
include CurrentLocale
- include ::Decidim::MultipleAttachmentsMethods
# Public: Initializes the command.
#
@@ -19,17 +18,12 @@ def initialize(form, current_user)
# Executes the command. Broadcasts these events:
#
# - :ok when everything is valid.
- # - :invalid if the form wasn't valid and we couldn't proceed.
+ # - :invalid if the form was not valid and we could not proceed.
#
# Returns nothing.
def call
return broadcast(:invalid) if form.invalid?
- if process_attachments?
- build_attachments
- return broadcast(:invalid) if attachments_invalid?
- end
-
initiative = create_initiative
if initiative.persisted?
@@ -50,8 +44,6 @@ def create_initiative
initiative.transaction do
initiative.save!
- @attached_to = initiative
- create_attachments if process_attachments?
create_components_for(initiative)
send_notification(initiative)
@@ -68,21 +60,14 @@ def build_initiative
title: { current_locale => form.title },
description: { current_locale => form.description },
author: current_user,
- decidim_user_group_id: form.decidim_user_group_id,
scoped_type: scoped_type,
- area: area,
- signature_type: form.signature_type,
- signature_end_date: signature_end_date,
- state: "created",
- hashtag: form.hashtag
+ signature_type: form.type.signature_type,
+ state: "created"
)
end
def scoped_type
- InitiativesTypeScope.find_by(
- type: form.initiative_type,
- scope: form.scope
- )
+ InitiativesTypeScope.order(:id).find_by(type: form.type)
end
def signature_end_date
@@ -112,7 +97,7 @@ def create_components_for(initiative)
def initialize_pages(component)
Decidim::Pages::CreatePage.call(component) do
- on(:invalid) { raise "Can't create page" }
+ on(:invalid) { raise "Cannot create page" }
end
end
diff --git a/decidim-initiatives/app/commands/decidim/initiatives/update_initiative.rb b/decidim-initiatives/app/commands/decidim/initiatives/update_initiative.rb
index 4ed342eb686a1..05dc1632fa332 100644
--- a/decidim-initiatives/app/commands/decidim/initiatives/update_initiative.rb
+++ b/decidim-initiatives/app/commands/decidim/initiatives/update_initiative.rb
@@ -57,7 +57,8 @@ def attributes
attrs = {
title: { current_locale => form.title },
description: { current_locale => form.description },
- hashtag: form.hashtag
+ hashtag: form.hashtag,
+ decidim_user_group_id: form.decidim_user_group_id
}
if form.signature_type_updatable?
diff --git a/decidim-initiatives/app/controllers/decidim/initiatives/create_initiative_controller.rb b/decidim-initiatives/app/controllers/decidim/initiatives/create_initiative_controller.rb
index 809753fe5b3ef..8ab39b0f637ef 100644
--- a/decidim-initiatives/app/controllers/decidim/initiatives/create_initiative_controller.rb
+++ b/decidim-initiatives/app/controllers/decidim/initiatives/create_initiative_controller.rb
@@ -8,7 +8,6 @@ module Initiatives
class CreateInitiativeController < Decidim::Initiatives::ApplicationController
layout "layouts/decidim/initiative_creation"
- include Wicked::Wizard
include Decidim::FormFactory
include InitiativeHelper
include TypeSelectorOptions
@@ -26,163 +25,127 @@ class CreateInitiativeController < Decidim::Initiatives::ApplicationController
helper_method :promotal_committee_required?
before_action :authenticate_user!
+ before_action :ensure_type_exists,
+ only: [:store_initiative_type, :previous_form, :store_initial_data, :fill_data, :store_data, :show_similar_initiatives, :promotal_committee, :finish]
+ before_action :ensure_user_can_create_initiative,
+ only: [:previous_form, :store_initial_data, :fill_data, :store_data, :show_similar_initiatives, :promotal_committee, :finish]
+ before_action :ensure_initiative_exists, only: [:fill_data, :store_data, :show_similar_initiatives, :promotal_committee, :finish]
- steps :select_initiative_type,
- :previous_form,
- :show_similar_initiatives,
- :fill_data,
- :promotal_committee,
- :finish
+ def select_initiative_type
+ @form = form(Decidim::Initiatives::SelectInitiativeTypeForm).from_params(params)
- before_action :ensure_type_exists, only: :show
-
- def show
- send("#{step}_step", initiative: session_initiative)
- end
-
- def update
- enforce_permission_to :create, :initiative, { initiative_type: initiative_type_from_params }
- send("#{step}_step", params)
- end
-
- private
-
- def ensure_type_exists
- destination_step = single_initiative_type? ? :previous_form : :select_initiative_type
-
- return if step == destination_step
- return if initiative_type_id.present? && initiative_type.present?
-
- redirect_to wizard_path(destination_step)
+ redirect_to previous_form_create_initiative_index_path if single_initiative_type?
end
- def select_initiative_type_step(_parameters)
- @form = form(Decidim::Initiatives::SelectInitiativeTypeForm).instance
- session[:initiative] = {}
+ def store_initiative_type
+ @form = form(Decidim::Initiatives::SelectInitiativeTypeForm).from_params(params)
- if single_initiative_type?
- redirect_to next_wizard_path
- return
+ if @form.valid?
+ session[:type_id] = @form.type_id
+ redirect_to previous_form_create_initiative_index_path
+ else
+ render :select_initiative_type
end
-
- @form = form(Decidim::Initiatives::SelectInitiativeTypeForm).instance
- render_wizard unless performed?
end
- def previous_form_step(parameters)
- @form = build_form(Decidim::Initiatives::PreviousForm, parameters)
-
- enforce_permission_to :create, :initiative, { initiative_type: initiative_type }
-
- render_wizard
+ def previous_form
+ @form = form(Decidim::Initiatives::PreviousForm).from_params({ type_id: initiative_type_id })
end
- def show_similar_initiatives_step(parameters)
- @form = build_form(Decidim::Initiatives::PreviousForm, parameters)
- unless @form.valid?
- redirect_to previous_wizard_path(validate_form: true)
- return
- end
+ def store_initial_data
+ @form = form(Decidim::Initiatives::PreviousForm).from_params(params, { initiative_type: initiative_type })
- if similar_initiatives.empty?
- @form = build_form(Decidim::Initiatives::InitiativeForm, parameters)
- redirect_to wizard_path(:fill_data)
- end
+ CreateInitiative.call(@form, current_user) do
+ on(:ok) do |initiative|
+ session[:initiative_id] = initiative.id
+ redirect_to show_similar_initiatives_create_initiative_index_path
+ end
- render_wizard unless performed?
+ on(:invalid) do
+ render :previous_form
+ end
+ end
end
- def fill_data_step(parameters)
- @form = build_form(Decidim::Initiatives::InitiativeForm, parameters)
- @form.attachment = form(AttachmentForm).from_params({})
+ def show_similar_initiatives
+ @form = form(Decidim::Initiatives::PreviousForm).from_model(current_initiative)
- render_wizard
+ redirect_to fill_data_create_initiative_index_path if similar_initiatives.empty?
end
- def promotal_committee_step(parameters)
- @form = build_form(Decidim::Initiatives::InitiativeForm, parameters)
- unless @form.valid?
- redirect_to previous_wizard_path(validate_form: true)
- return
- end
+ def fill_data
+ @form = form(Decidim::Initiatives::InitiativeForm).from_model(current_initiative, { initiative_type: initiative_type })
+ end
- skip_step unless promotal_committee_required?
+ def store_data
+ @form = form(Decidim::Initiatives::InitiativeForm).from_params(params, { initiative_type: initiative_type })
- if session_initiative.has_key?(:id)
- render_wizard
- return
- end
+ UpdateInitiative.call(current_initiative, @form, current_user) do
+ on(:ok) do
+ path = promotal_committee_required? ? "promotal_committee" : "finish"
- CreateInitiative.call(@form, current_user) do
- on(:ok) do |initiative|
- session[:initiative][:id] = initiative.id
- if current_initiative.created_by_individual?
- render_wizard
- else
- redirect_to wizard_path(:finish)
- end
+ redirect_to send("#{path}_create_initiative_index_path".to_sym)
end
- on(:invalid) do |initiative|
- logger.fatal "Failed creating initiative: #{initiative.errors.full_messages.join(", ")}" if initiative
- redirect_to previous_wizard_path(validate_form: true)
+ on(:invalid) do
+ render :fill_data
end
end
end
- def finish_step(_parameters)
- render_wizard
+ def promotal_committee
+ redirect_to finish_create_initiative_index_path unless promotal_committee_required?
end
- def similar_initiatives
- @similar_initiatives ||= Decidim::Initiatives::SimilarInitiatives
- .for(current_organization, @form)
- .all
- end
+ def finish; end
- def build_form(klass, parameters)
- @form = if single_initiative_type?
- form(klass).from_params(parameters.except(:id).merge(type_id: current_organization_initiatives_type.first.id), extra_context)
- else
- form(klass).from_params(parameters.except(:id), extra_context)
- end
+ private
- attributes = @form.attributes_with_values
- session[:initiative] = session_initiative.merge(attributes)
- @form.valid? if params[:validate_form]
+ def ensure_user_can_create_initiative
+ enforce_permission_to :create, :initiative, { initiative_type: initiative_type }
+ end
- @form
+ def initiative_type_id
+ @initiative_type_id ||= fetch_initiative_type_id
end
- def extra_context
- return {} unless initiative_type_id
+ def fetch_initiative_type_id
+ return current_organization_initiatives_type.first.id if single_initiative_type?
+ return params.dig(:initiative, :type_id) if params.dig(:initiative, :type_id).present?
+ return current_initiative&.type&.id if session[:initiative_id].present?
- { initiative_type: initiative_type }
+ session[:type_id]
end
- def scopes
- @scopes ||= @form.available_scopes
+ def ensure_initiative_exists
+ redirect_to previous_form_create_initiative_index_path if session[:initiative_id].blank?
end
- def current_initiative
- Initiative.where(organization: current_organization).find_by(id: session_initiative[:id]) if session_initiative.has_key?(:id)
+ def ensure_type_exists
+ destination_step = single_initiative_type? ? "previous_form" : "select_initiative_type"
+
+ return if action_name == destination_step
+ return if initiative_type_id.present? && initiative_type.present?
+
+ redirect_to send("#{destination_step}_create_initiative_index_path".to_sym)
end
- def initiative_type
- @initiative_type ||= InitiativesType.where(organization: current_organization).find_by(id: initiative_type_id)
+ def similar_initiatives
+ @similar_initiatives ||= Decidim::Initiatives::SimilarInitiatives
+ .for(current_organization, @form)
+ .all
end
- def initiative_type_from_params
- Decidim::InitiativesType.find_by(id: params["initiative"]["type_id"])
+ def scopes
+ @scopes ||= @form.available_scopes
end
- def initiative_type_id
- session_initiative[:type_id] || @form&.type_id
+ def current_initiative
+ Initiative.find(session[:initiative_id] || nil)
end
- def session_initiative
- session[:initiative] ||= {}
- session[:initiative].with_indifferent_access
+ def initiative_type
+ @initiative_type ||= InitiativesType.find(initiative_type_id)
end
def promotal_committee_required?
diff --git a/decidim-initiatives/app/forms/decidim/initiatives/initiative_form.rb b/decidim-initiatives/app/forms/decidim/initiatives/initiative_form.rb
index bd1eddab546fa..35434274e1d22 100644
--- a/decidim-initiatives/app/forms/decidim/initiatives/initiative_form.rb
+++ b/decidim-initiatives/app/forms/decidim/initiatives/initiative_form.rb
@@ -3,16 +3,12 @@
module Decidim
module Initiatives
# A form object used to collect the data for a new initiative.
- class InitiativeForm < Form
+ class InitiativeForm < PreviousForm
include TranslatableAttributes
include AttachmentAttributes
mimic :initiative
- attribute :title, String
- attribute :description, String
- attribute :type_id, Integer
- attribute :scope_id, Integer
attribute :area_id, Integer
attribute :decidim_user_group_id, Integer
attribute :signature_type, String
@@ -20,18 +16,16 @@ class InitiativeForm < Form
attribute :state, String
attribute :attachment, AttachmentForm
attribute :hashtag, String
+ attribute :scope_id, Integer
attachments_attribute :photos
attachments_attribute :documents
- validates :title, :description, presence: true
- validates :title, length: { maximum: 150 }
validates :signature_type, presence: true
- validates :type_id, presence: true
validates :area, presence: true, if: ->(form) { form.area_id.present? }
- validate :scope_exists
validate :notify_missing_attachment_if_errored
validate :trigger_attachment_errors
+ validate :scope_exists
validates :signature_end_date, date: { after: Date.current }, if: lambda { |form|
form.context.initiative_type.custom_signature_end_date_enabled? && form.signature_end_date.present?
}
@@ -39,6 +33,7 @@ class InitiativeForm < Form
def map_model(model)
self.type_id = model.type.id
self.scope_id = model.scope&.id
+ self.decidim_user_group_id = model.decidim_user_group_id
self.signature_type = model.signature_type
self.title = translated_attribute(model.title)
self.description = translated_attribute(model.description)
@@ -56,12 +51,6 @@ def area_updatable?
@area_updatable ||= current_user.admin? || context.initiative.created?
end
- def scope_id
- return nil if initiative_type.only_global_scope_enabled?
-
- super.presence
- end
-
def area
@area ||= current_organization.areas.find_by(id: area_id)
end
@@ -70,37 +59,39 @@ def initiative_type
@initiative_type ||= type_id ? InitiativesType.find(type_id) : context.initiative.type
end
- def available_scopes
- @available_scopes ||= if initiative_type.only_global_scope_enabled?
- initiative_type.scopes.where(scope: nil)
- else
- initiative_type.scopes
- end
+ def scoped_type_id
+ return unless type && scope_id
+
+ type.scopes.find_by(decidim_scopes_id: scope_id.presence).id
end
def scope
@scope ||= Scope.find(scope_id) if scope_id.present?
end
- def scoped_type_id
- return unless type && scope_id
+ def scope_id
+ return nil if type.only_global_scope_enabled?
- type.scopes.find_by(decidim_scopes_id: scope_id.presence).id
+ super.presence
end
- private
-
- def type
- @type ||= type_id ? Decidim::InitiativesType.find(type_id) : context.initiative.type
+ def available_scopes
+ @available_scopes ||= if type.only_global_scope_enabled?
+ type.scopes.where(scope: nil)
+ else
+ type.scopes
+ end
end
+ private
+
def scope_exists
return if scope_id.blank?
- errors.add(:scope_id, :invalid) unless InitiativesTypeScope.exists?(type: initiative_type, scope: scope)
+ errors.add(:scope_id, :invalid) unless InitiativesTypeScope.exists?(type: type, scope: scope)
end
- # This method will add an error to the `attachment` field only if there's
+ # This method will add an error to the `attachment` field only if there is
# any error in any other field. This is needed because when the form has
# an error, the attachment is lost, so we need a way to inform the user of
# this problem.
diff --git a/decidim-initiatives/app/forms/decidim/initiatives/previous_form.rb b/decidim-initiatives/app/forms/decidim/initiatives/previous_form.rb
index 1010d0e8505e2..86a007f2846fb 100644
--- a/decidim-initiatives/app/forms/decidim/initiatives/previous_form.rb
+++ b/decidim-initiatives/app/forms/decidim/initiatives/previous_form.rb
@@ -15,6 +15,10 @@ class PreviousForm < Form
validates :title, :description, presence: true
validates :title, length: { maximum: 150 }
validates :type_id, presence: true
+
+ def type
+ @type ||= type_id ? Decidim::InitiativesType.find(type_id) : context.initiative.type
+ end
end
end
end
diff --git a/decidim-initiatives/app/models/decidim/initiative.rb b/decidim-initiatives/app/models/decidim/initiative.rb
index 5184c005f7902..f720c8edc7986 100644
--- a/decidim-initiatives/app/models/decidim/initiative.rb
+++ b/decidim-initiatives/app/models/decidim/initiative.rb
@@ -27,6 +27,11 @@ class Initiative < ApplicationRecord
translatable_fields :title, :description, :answer
+ delegate :type, :scope, :scope_name, :supports_required, to: :scoped_type, allow_nil: true
+ delegate :document_number_authorization_handler, :promoting_committee_enabled?, :attachments_enabled?,
+ :promoting_committee_enabled?, :custom_signature_end_date_enabled?, :area_enabled?, to: :type
+ delegate :name, to: :area, prefix: true, allow_nil: true
+
belongs_to :organization,
foreign_key: "decidim_organization_id",
class_name: "Decidim::Organization"
@@ -35,10 +40,6 @@ class Initiative < ApplicationRecord
class_name: "Decidim::InitiativesTypeScope",
inverse_of: :initiatives
- delegate :type, :scope, :scope_name, :supports_required, to: :scoped_type, allow_nil: true
- delegate :attachments_enabled?, :promoting_committee_enabled?, :custom_signature_end_date_enabled?, :area_enabled?, to: :type
- delegate :name, to: :area, prefix: true, allow_nil: true
-
has_many :votes,
foreign_key: "decidim_initiative_id",
class_name: "Decidim::InitiativesVote",
@@ -162,9 +163,6 @@ def self.ransackable_scopes(_auth_object = nil)
[:with_any_state, :with_any_type, :with_any_scope, :with_any_area]
end
- delegate :document_number_authorization_handler, :promoting_committee_enabled?, to: :type
- delegate :type, :scope, :scope_name, to: :scoped_type, allow_nil: true
-
# Public: Overrides participatory space's banner image with the banner image defined
# for the initiative type.
#
diff --git a/decidim-initiatives/app/packs/src/decidim/initiatives/scoped_type.js b/decidim-initiatives/app/packs/src/decidim/initiatives/scoped_type.js
index 5045322ef65e0..bc3969e21dce7 100644
--- a/decidim-initiatives/app/packs/src/decidim/initiatives/scoped_type.js
+++ b/decidim-initiatives/app/packs/src/decidim/initiatives/scoped_type.js
@@ -1,5 +1,5 @@
/* eslint-disable camelcase */
-const controlSelector = function(source, prefix, currentValueKey) {
+const controlSelector = function (source, prefix, currentValueKey) {
if (source.length) {
let currentValue = source.data(currentValueKey),
searchUrl = source.data(`${prefix}-search-url`),
diff --git a/decidim-initiatives/app/queries/decidim/initiatives/similar_initiatives.rb b/decidim-initiatives/app/queries/decidim/initiatives/similar_initiatives.rb
index b817f2fd26cae..bb94459beb3d3 100644
--- a/decidim-initiatives/app/queries/decidim/initiatives/similar_initiatives.rb
+++ b/decidim-initiatives/app/queries/decidim/initiatives/similar_initiatives.rb
@@ -31,8 +31,8 @@ def query
.where(organization: @organization)
.where(
Arel.sql("GREATEST(#{title_similarity}, #{description_similarity}) >= ?").to_s,
- form.title,
- form.description,
+ translated_attribute(form.title),
+ translated_attribute(form.description),
Decidim::Initiatives.similarity_threshold
)
.limit(Decidim::Initiatives.similarity_limit)
diff --git a/decidim-initiatives/app/views/decidim/initiatives/create_initiative/_share_committee_link.html.erb b/decidim-initiatives/app/views/decidim/initiatives/create_initiative/_share_committee_link.html.erb
index 6caf0a7179623..0046f84482fd5 100644
--- a/decidim-initiatives/app/views/decidim/initiatives/create_initiative/_share_committee_link.html.erb
+++ b/decidim-initiatives/app/views/decidim/initiatives/create_initiative/_share_committee_link.html.erb
@@ -18,7 +18,7 @@
- <%= link_to t(".continue"), next_wizard_path, class: "button expanded" %>
+ <%= link_to t(".continue"), finish_create_initiative_index_path, class: "button expanded" %>
<%= javascript_pack_tag "decidim_initiatives_admin" %>
diff --git a/decidim-initiatives/app/views/decidim/initiatives/create_initiative/fill_data.html.erb b/decidim-initiatives/app/views/decidim/initiatives/create_initiative/fill_data.html.erb
index c228420d7897d..09da6d6a905ce 100644
--- a/decidim-initiatives/app/views/decidim/initiatives/create_initiative/fill_data.html.erb
+++ b/decidim-initiatives/app/views/decidim/initiatives/create_initiative/fill_data.html.erb
@@ -18,7 +18,7 @@
- <%= decidim_form_for(@form, url: next_wizard_path, method: :put, html: { class: "form new_initiative_form" }) do |f| %>
+ <%= decidim_form_for(@form, url: fill_data_create_initiative_index_path, method: :put, html: { class: "form new_initiative_form", novalidate: false }) do |f| %>
<%= form_required_explanation %>
<% if single_initiative_type? %>
@@ -30,22 +30,22 @@
{},
{
disabled: !@form.signature_type_updatable?,
- "data-scope-selector": "initiative_decidim_scope_id",
+ "data-scope-selector": "initiative_scope_id",
"data-scope-id": f.object.scope_id.to_s,
"data-scope-search-url": decidim_initiatives.initiative_type_scopes_search_url,
"data-signature-types-selector": "initiative_signature_type",
- "data-signature-type": current_initiative&.signature_type,
+ "data-signature-type": current_initiative.signature_type,
"data-signature-types-search-url": decidim_initiatives.initiative_type_signature_types_search_url
} %>
<% end %>
- <%= f.text_field :title, autofocus: true %>
+ <%= f.text_field :title, autofocus: true, value: translated_attribute(f.object.title) %>
- <%= text_editor_for(f, :description, lines: 8, toolbar: :content) %>
+ <%= text_editor_for(f, :description, lines: 8, toolbar: :content, value: translated_attribute(f.object.description)) %>
diff --git a/decidim-initiatives/app/views/decidim/initiatives/create_initiative/previous_form.html.erb b/decidim-initiatives/app/views/decidim/initiatives/create_initiative/previous_form.html.erb
index daf3ff9ecbc0f..c7d3009843219 100644
--- a/decidim-initiatives/app/views/decidim/initiatives/create_initiative/previous_form.html.erb
+++ b/decidim-initiatives/app/views/decidim/initiatives/create_initiative/previous_form.html.erb
@@ -18,7 +18,7 @@
- <%= decidim_form_for(@form, url: next_wizard_path, method: :put, html: { class: "form new_initiative_previous_form" }) do |f| %>
+ <%= decidim_form_for(@form, url: previous_form_create_initiative_index_path, method: :put, html: { class: "form new_initiative_previous_form" }) do |f| %>
<%= form_required_explanation %>
<%= f.hidden_field :type_id %>
diff --git a/decidim-initiatives/app/views/decidim/initiatives/create_initiative/select_initiative_type.html.erb b/decidim-initiatives/app/views/decidim/initiatives/create_initiative/select_initiative_type.html.erb
index 28c47b0350a2c..b4869f03fc0e1 100644
--- a/decidim-initiatives/app/views/decidim/initiatives/create_initiative/select_initiative_type.html.erb
+++ b/decidim-initiatives/app/views/decidim/initiatives/create_initiative/select_initiative_type.html.erb
@@ -40,8 +40,8 @@
<% if allowed_to?(:create, :initiative, { initiative_type: type }) %>
- <%= decidim_form_for(@form, url: next_wizard_path, method: :put, html: { id: "new_initiative_#{type.id}", class: "form select-initiative_type-form" }) do |f| %>
- <%= f.hidden_field :type_id, value: type.id, id: "initiative_type_id_#{ type.id }" %>
+ <%= decidim_form_for(@form, url: select_initiative_type_create_initiative_index_path, method: :put, html: { id: "new_initiative_#{type.id}", class: "form select-initiative_type-form" }) do |f| %>
+ <%= f.hidden_field :type_id, value: type.id, id: "initiative_type_id_#{type.id}" %>
<%= f.submit t(".select"), class: "button" %>
<% end %>
<% else %>
diff --git a/decidim-initiatives/app/views/decidim/initiatives/create_initiative/show_similar_initiatives.html.erb b/decidim-initiatives/app/views/decidim/initiatives/create_initiative/show_similar_initiatives.html.erb
index d1476186d06fd..1fcbe59a6ed80 100644
--- a/decidim-initiatives/app/views/decidim/initiatives/create_initiative/show_similar_initiatives.html.erb
+++ b/decidim-initiatives/app/views/decidim/initiatives/create_initiative/show_similar_initiatives.html.erb
@@ -18,6 +18,6 @@
- <%= link_to t(".continue"), next_wizard_path, class: "button expanded" %>
+ <%= link_to t(".continue"), fill_data_create_initiative_index_path, class: "button expanded" %>
diff --git a/decidim-initiatives/app/views/decidim/initiatives/initiatives/_form.html.erb b/decidim-initiatives/app/views/decidim/initiatives/initiatives/_form.html.erb
index 2c361d1353a1a..53fe912361d4d 100644
--- a/decidim-initiatives/app/views/decidim/initiatives/initiatives/_form.html.erb
+++ b/decidim-initiatives/app/views/decidim/initiatives/initiatives/_form.html.erb
@@ -7,7 +7,7 @@
{},
{
disabled: !@form.signature_type_updatable?,
- "data-scope-selector": "initiative_decidim_scope_id",
+ "data-scope-selector": "initiative_scope_id",
"data-scope-id": form.object.scope_id.to_s,
"data-scope-search-url": decidim_initiatives.initiative_type_scopes_search_url,
"data-signature-types-selector": "initiative_signature_type",
@@ -114,7 +114,3 @@
<% if current_initiative.type.promoting_committee_enabled? %>
<%= render partial: "committee_members" %>
<% end %>
-
-<% content_for :js_content do %>
- <%= javascript_pack_tag "decidim_initiatives" %>
-<% end %>
diff --git a/decidim-initiatives/app/views/decidim/initiatives/initiatives_type_scopes/search.html.erb b/decidim-initiatives/app/views/decidim/initiatives/initiatives_type_scopes/search.html.erb
index e006ff8d9a34b..9feac8880456e 100644
--- a/decidim-initiatives/app/views/decidim/initiatives/initiatives_type_scopes/search.html.erb
+++ b/decidim-initiatives/app/views/decidim/initiatives/initiatives_type_scopes/search.html.erb
@@ -1 +1,2 @@
-<%= options_for_select scoped_types.map { |s| [translated_attribute(s.scope_name), s&.scope&.id] }, params[:selected] %>
+<% blank = [t("select_scope", scope: "decidim.initiatives.create_initiative.fill_data"), ""] %>
+<%= options_for_select scoped_types.map { |s| [translated_attribute(s.scope_name), s&.scope&.id] }.prepend(blank), params[:selected] %>
diff --git a/decidim-initiatives/app/views/layouts/decidim/_initiative_creation_header.html.erb b/decidim-initiatives/app/views/layouts/decidim/_initiative_creation_header.html.erb
index ca68128fb01ba..f1c24cb29dc85 100644
--- a/decidim-initiatives/app/views/layouts/decidim/_initiative_creation_header.html.erb
+++ b/decidim-initiatives/app/views/layouts/decidim/_initiative_creation_header.html.erb
@@ -11,19 +11,16 @@
- <% wizard_steps.each do |wizard_step| %>
- <% next if wizard_step.to_s == "promotal_committee" && !promotal_committee_required? %>
- <% next if wizard_step.to_s == "select_initiative_type" && single_initiative_type? %>
- <% if step == wizard_step %>
- -
- <%= t(".#{wizard_step}") %>
-
- <% else %>
- -
- <%= t(".#{wizard_step}") %>
-
- <% end %>
+ <% unless single_initiative_type? %>
+ <%= content_tag :li, t(".select_initiative_type"), class: action_name == "select_initiative_type" ? "step--active" : nil %>
<% end %>
+ <%= content_tag :li, t(".previous_form"), class: action_name == "previous_form" ? "step--active" : nil %>
+ <%= content_tag :li, t(".show_similar_initiatives"), class: action_name == "show_similar_initiatives" ? "step--active" : nil %>
+ <%= content_tag :li, t(".fill_data"), class: action_name == "fill_data" ? "step--active" : nil %>
+ <% if promotal_committee_required? %>
+ <%= content_tag :li, t(".promotal_committee"), class: action_name == "promotal_committee" ? "step--active" : nil %>
+ <% end %>
+ <%= content_tag :li, t(".finish"), class: action_name == "finish" ? "step--active" : nil %>
diff --git a/decidim-initiatives/app/views/layouts/decidim/initiative_creation.html.erb b/decidim-initiatives/app/views/layouts/decidim/initiative_creation.html.erb
index ca22981332549..b2972b1c7422a 100644
--- a/decidim-initiatives/app/views/layouts/decidim/initiative_creation.html.erb
+++ b/decidim-initiatives/app/views/layouts/decidim/initiative_creation.html.erb
@@ -1,5 +1,5 @@
<%= render "layouts/decidim/application" do %>
- <% if wizard_steps.first == step %>
+ <% if action_name == "select_initiative_type" %>
<%= yield %>
diff --git a/decidim-initiatives/config/locales/en.yml b/decidim-initiatives/config/locales/en.yml
index 10cc29a12ae5b..6f954afaa5bb0 100644
--- a/decidim-initiatives/config/locales/en.yml
+++ b/decidim-initiatives/config/locales/en.yml
@@ -634,7 +634,6 @@ en:
promotal_committee: Promoter committee
select_initiative_type: Choose
show_similar_initiatives: Compare
- step: Step %{current} of %{total}
title: Create new initiative
initiative_header:
initiative_menu_item: Initiative
diff --git a/decidim-initiatives/lib/decidim/initiatives/engine.rb b/decidim-initiatives/lib/decidim/initiatives/engine.rb
index 2c77478413280..1bd50c74f5e5e 100644
--- a/decidim-initiatives/lib/decidim/initiatives/engine.rb
+++ b/decidim-initiatives/lib/decidim/initiatives/engine.rb
@@ -19,7 +19,22 @@ class Engine < ::Rails::Engine
get "/initiative_type_scopes/search", to: "initiatives_type_scopes#search", as: :initiative_type_scopes_search
get "/initiative_type_signature_types/search", to: "initiatives_type_signature_types#search", as: :initiative_type_signature_types_search
- resources :create_initiative
+ resources :create_initiative do
+ collection do
+ get :select_initiative_type
+ put :select_initiative_type, to: "create_initiative#store_initiative_type"
+
+ get :previous_form
+ put :previous_form, to: "create_initiative#store_initial_data"
+
+ get :show_similar_initiatives
+
+ get :fill_data
+ put :fill_data, to: "create_initiative#store_data"
+ get :promotal_committee
+ get :finish
+ end
+ end
get "initiatives/:initiative_id", to: redirect { |params, _request|
initiative = Decidim::Initiative.find(params[:initiative_id])
diff --git a/decidim-initiatives/spec/commands/decidim/initiatives/update_initiative_spec.rb b/decidim-initiatives/spec/commands/decidim/initiatives/update_initiative_spec.rb
index cbf124e67b621..041b19c28ef13 100644
--- a/decidim-initiatives/spec/commands/decidim/initiatives/update_initiative_spec.rb
+++ b/decidim-initiatives/spec/commands/decidim/initiatives/update_initiative_spec.rb
@@ -72,6 +72,57 @@ module Initiatives
expect(initiative.description["en"]).to eq description
end
+ context "when the initiative type enables custom signature end date" do
+ let(:initiative_type) { create(:initiatives_type, :custom_signature_end_date_enabled, organization: organization) }
+ let(:scoped_type) { create(:initiatives_type_scope, type: initiative_type) }
+ let!(:initiative) { create(:initiative, :created, organization: organization, scoped_type: scoped_type) }
+
+ let(:form_params) do
+ {
+ title: title,
+ description: description,
+ signature_type: signature_type,
+ type_id: initiative_type.id,
+ attachment: attachment,
+ add_documents: uploaded_files,
+ documents: current_files,
+ signature_end_date: Date.tomorrow
+ }
+ end
+
+ it "sets the signature end date" do
+ command.call
+ initiative = Decidim::Initiative.last
+
+ expect(initiative.signature_end_date).to eq(Date.tomorrow)
+ end
+ end
+
+ context "when the initiative type enables area" do
+ let(:initiative_type) { create(:initiatives_type, :area_enabled, organization: organization) }
+ let(:scoped_type) { create(:initiatives_type_scope, type: initiative_type) }
+ let!(:initiative) { create(:initiative, :created, organization: organization, scoped_type: scoped_type) }
+ let(:area) { create(:area, organization: initiative_type.organization) }
+
+ let(:form_params) do
+ {
+ title: "A reasonable initiative title",
+ description: "A reasonable initiative description",
+ type_id: initiative_type.id,
+ signature_type: "online",
+ decidim_user_group_id: nil,
+ area_id: area.id
+ }
+ end
+
+ it "sets the area" do
+ command.call
+ initiative = Decidim::Initiative.last
+
+ expect(initiative.decidim_area_id).to eq(area.id)
+ end
+ end
+
context "when attachments are allowed" do
let(:uploaded_files) do
[
diff --git a/decidim-initiatives/spec/shared/create_initiative_example.rb b/decidim-initiatives/spec/shared/create_initiative_example.rb
index 77d9a2c32b386..adaeac7118190 100644
--- a/decidim-initiatives/spec/shared/create_initiative_example.rb
+++ b/decidim-initiatives/spec/shared/create_initiative_example.rb
@@ -58,40 +58,6 @@
end.to change(Decidim::Initiative, :count).by(1)
end
- context "when attachment is present" do
- let(:uploaded_files) do
- [
- upload_test_file(Decidim::Dev.test_file("Exampledocument.pdf", "application/pdf"))
- ]
- end
-
- it "creates an attachment for the proposal" do
- expect { command.call }.to change(Decidim::Attachment, :count).by(1)
- last_initiative = Decidim::Initiative.last
- last_attachment = Decidim::Attachment.last
- expect(last_attachment.attached_to).to eq(last_initiative)
- end
-
- context "when attachment is left blank" do
- it "broadcasts ok" do
- expect { command.call }.to broadcast(:ok)
- end
- end
- end
-
- context "when has multiple attachments" do
- let(:uploaded_files) do
- [
- upload_test_file(Decidim::Dev.test_file("city.jpeg", "image/jpeg")),
- upload_test_file(Decidim::Dev.test_file("Exampledocument.pdf", "application/pdf"))
- ]
- end
-
- it "creates multiple attachments for the initiative" do
- expect { command.call }.to change(Decidim::Attachment, :count).by(2)
- end
- end
-
it "sets the author" do
command.call
initiative = Decidim::Initiative.last
@@ -144,53 +110,6 @@
expect(initiative.signature_end_date).to be_nil
end
end
-
- context "when the initiative type enables custom signature end date" do
- let(:initiative_type) { create(:initiatives_type, :custom_signature_end_date_enabled) }
-
- let(:form_params) do
- {
- title: "A reasonable initiative title",
- description: "A reasonable initiative description",
- type_id: scoped_type.type.id,
- signature_type: "online",
- scope_id: scoped_type.scope.id,
- decidim_user_group_id: nil,
- signature_end_date: Date.tomorrow
- }
- end
-
- it "sets the signature end date" do
- command.call
- initiative = Decidim::Initiative.last
-
- expect(initiative.signature_end_date).to eq(Date.tomorrow)
- end
- end
-
- context "when the initiative type enables area" do
- let(:initiative_type) { create(:initiatives_type, :area_enabled) }
- let(:area) { create(:area, organization: initiative_type.organization) }
-
- let(:form_params) do
- {
- title: "A reasonable initiative title",
- description: "A reasonable initiative description",
- type_id: scoped_type.type.id,
- signature_type: "online",
- scope_id: scoped_type.scope.id,
- decidim_user_group_id: nil,
- area_id: area.id
- }
- end
-
- it "sets the area" do
- command.call
- initiative = Decidim::Initiative.last
-
- expect(initiative.decidim_area_id).to eq(area.id)
- end
- end
end
end
end
diff --git a/decidim-initiatives/spec/system/create_initiative_spec.rb b/decidim-initiatives/spec/system/create_initiative_spec.rb
index 1499404c75283..87e7f68946de2 100644
--- a/decidim-initiatives/spec/system/create_initiative_spec.rb
+++ b/decidim-initiatives/spec/system/create_initiative_spec.rb
@@ -9,7 +9,6 @@
let!(:authorized_user) { create(:user, :confirmed, organization: organization) }
let!(:authorization) { create(:authorization, user: authorized_user) }
let(:login) { true }
-
let(:initiative_type_minimum_committee_members) { 2 }
let(:signature_type) { "any" }
let(:initiative_type_promoting_committee_enabled) { true }
@@ -559,6 +558,27 @@
context "when create initiative" do
let(:initiative) { build(:initiative) }
+ context "when only one signature collection and scope are available" do
+ let(:signature_type) { "offline" }
+ let!(:other_initiative_type) { nil }
+ let!(:other_initiative_type_scope) { nil }
+ let(:initiative_type_scope2) { nil }
+ let(:initiative_type) { create(:initiatives_type, organization: organization, minimum_committee_members: initiative_type_minimum_committee_members, signature_type: signature_type) }
+
+ before do
+ fill_in "Title", with: translated(initiative.title, locale: :en)
+ fill_in "initiative_description", with: translated(initiative.description, locale: :en)
+ find_button("Continue").click
+ end
+
+ it "hides and automatically selects the values" do
+ expect(page).not_to have_content("Signature collection type")
+ expect(page).not_to have_content("Scope")
+ expect(find(:xpath, "//input[@id='initiative_type_id']", visible: :all).value).to eq(initiative_type.id.to_s)
+ expect(find(:xpath, "//input[@id='initiative_signature_type']", visible: :all).value).to eq("offline")
+ end
+ end
+
context "when there is only one initiative type" do
let!(:other_initiative_type) { nil }
let!(:other_initiative_type_scope) { nil }
@@ -612,7 +632,7 @@
it "shows input for signature collection type" do
expect(page).to have_content("Signature collection type")
- expect(find(:xpath, "//select[@id='initiative_signature_type']", visible: :all).value).to eq("online")
+ expect(find(:xpath, "//select[@id='initiative_signature_type']", visible: :all).value).to eq(signature_type)
end
it "shows input for hashtag" do
@@ -632,14 +652,6 @@
end
end
- context "when the scope is not selected" do
- it "shows an error" do
- select("Online", from: "Signature collection type")
- find_button("Continue").click
- expect(page).to have_content("There's an error in this field")
- end
- end
-
context "when the initiative type does not enable custom signature end date" do
it "does not show the signature end date" do
expect(page).not_to have_content("End of signature collection period")
@@ -647,7 +659,8 @@
end
context "when the initiative type enables custom signature end date" do
- let(:initiative_type) { create(:initiatives_type, :custom_signature_end_date_enabled, organization: organization, minimum_committee_members: initiative_type_minimum_committee_members, signature_type: "offline") }
+ let(:signature_type) { "offline" }
+ let(:initiative_type) { create(:initiatives_type, :custom_signature_end_date_enabled, organization: organization, minimum_committee_members: initiative_type_minimum_committee_members, signature_type: signature_type) }
it "shows the signature end date" do
expect(page).to have_content("End of signature collection period")
@@ -661,7 +674,8 @@
end
context "when the initiative type enables area" do
- let(:initiative_type) { create(:initiatives_type, :area_enabled, organization: organization, minimum_committee_members: initiative_type_minimum_committee_members, signature_type: "offline") }
+ let(:signature_type) { "offline" }
+ let(:initiative_type) { create(:initiatives_type, :area_enabled, organization: organization, minimum_committee_members: initiative_type_minimum_committee_members, signature_type: signature_type) }
it "shows the area" do
expect(page).to have_content("Area")
@@ -681,7 +695,7 @@
end
end
- context "when there's a promoter committee" do
+ context "when there is a promoter committee" do
let(:initiative) { build(:initiative, organization: organization, scoped_type: initiative_type_scope) }
before do
@@ -693,7 +707,6 @@
find_button("Continue").click
select("Online", from: "Signature collection type")
- select(translated(initiative_type_scope.scope.name, locale: :en), from: "Scope")
find_button("Continue").click
end
@@ -726,7 +739,7 @@
end
end
- context "and it's disabled at the type scope" do
+ context "and it is disabled at the type scope" do
let(:initiative_type) { create(:initiatives_type, organization: organization, promoting_committee_enabled: false, signature_type: signature_type) }
it "skips the promoting committee settings" do
@@ -736,6 +749,30 @@
end
end
+ context "when the initiative is created by an user group" do
+ let(:organization) { create(:organization, available_authorizations: authorizations, user_groups_enabled: true) }
+ let(:initiative) { build(:initiative) }
+ let!(:user_group) { create(:user_group, :verified, organization: organization, users: [authorized_user]) }
+
+ before do
+ authorized_user.reload
+ find_button("I want to promote this initiative").click
+
+ fill_in "Title", with: translated(initiative.title, locale: :en)
+ fill_in "initiative_description", with: translated(initiative.description, locale: :en)
+ find_button("Continue").click
+
+ select("Online", from: "Signature collection type")
+ select(user_group.name, from: "Author")
+ end
+
+ it "shows the user group as author" do
+ expect(Decidim::Initiative.where(decidim_user_group_id: user_group.id).count).to eq(0)
+ find_button("Continue").click
+ expect(Decidim::Initiative.where(decidim_user_group_id: user_group.id).count).to eq(1)
+ end
+ end
+
context "when finish" do
let(:initiative) { build(:initiative) }
@@ -746,7 +783,6 @@
fill_in "initiative_description", with: translated(initiative.description, locale: :en)
find_button("Continue").click
- select(translated(initiative_type_scope.scope.name, locale: :en), from: "Scope")
select("Online", from: "Signature collection type")
dynamically_attach_file(:initiative_documents, Decidim::Dev.asset("Exampledocument.pdf"))
find_button("Continue").click