diff --git a/.gitignore b/.gitignore index 3c5ca93..03b6b8b 100644 --- a/.gitignore +++ b/.gitignore @@ -38,3 +38,5 @@ yarn-debug.log* # these images are copied in at install time /public/leaflet +*.dump +.envrc diff --git a/app/controllers/districts_controller.rb b/app/controllers/districts_controller.rb index 439d34e..a82f182 100644 --- a/app/controllers/districts_controller.rb +++ b/app/controllers/districts_controller.rb @@ -6,7 +6,7 @@ class DistrictsController < ApplicationController def show @district = District.find(params['id']) initiatives = - Initiative.includes(parish: %i[ward]).where( + Initiative.published.includes(parish: %i[ward]).where( parishes: { wards: { district_id: @district.id } } ) @map_data = MapData.new(initiatives) diff --git a/app/controllers/home_controller.rb b/app/controllers/home_controller.rb index cbdae07..0ae4187 100644 --- a/app/controllers/home_controller.rb +++ b/app/controllers/home_controller.rb @@ -7,7 +7,7 @@ class HomeController < ApplicationController def index @initiatives_json = Initiative.approved.to_json - initiatives = Initiative.all + initiatives = Initiative.published @map_data = MapData.new(initiatives) @sectors = Sector.all @districts = District.all diff --git a/app/controllers/initiatives_controller.rb b/app/controllers/initiatives_controller.rb index 9c686fd..6f12d9e 100644 --- a/app/controllers/initiatives_controller.rb +++ b/app/controllers/initiatives_controller.rb @@ -8,11 +8,16 @@ class InitiativesController < ApplicationController helper_method :can_edit? def can_edit?(initiative) - initiative.owner == current_user + initiative.owner == current_user || current_user&.role == 'admin' end def index - @initiatives = Initiative.all + current_users_initiatives = current_user&.initiatives || [] + @initiatives = if current_user&.role == 'admin' + Initiative.all.sort_by(&:name) + else + (Initiative.published + current_users_initiatives).uniq.sort_by(&:name) + end end def show @@ -37,12 +42,11 @@ def edit; end # rubocop:disable Metrics/MethodLength def create create_proposed_solutions - @initiative = Initiative.new(initiative_params) - @initiative.owner = current_user + @initiative = Initiative.new(initiative_params.merge(owner: current_user)) find_or_create_group @initiative.update_location_from_postcode - if @initiative.save + if @initiative.save(validate: @initiative.publication_status != 'draft') redirect_to edit_initiative_path(@initiative), notice: 'Initiative was successfully created.' else @@ -51,15 +55,23 @@ def create end # rubocop:enable Metrics/MethodLength - # rubocop:disable Metrics/MethodLength + # rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity def update + publication_status = @initiative.publication_status + if publication_status == 'archived' + redirect_to initiatives_path, notice: "'#{@initiative.name}' has been archived and cannot be edited" + return + end + + initiative_params.delete(:publication_status) if publication_status == 'rejected' && current_user.role != 'admin' + clear_solutions_and_themes && create_proposed_solutions images = initiative_params.delete 'images' find_or_create_group @initiative.assign_attributes initiative_params @initiative.update_location_from_postcode - if @initiative.save + if @initiative.save(validate: publication_status != 'draft') @initiative.images.attach images if images redirect_to edit_initiative_path(@initiative), notice: 'Initiative was successfully updated.' @@ -67,7 +79,7 @@ def update render :edit end end - # rubocop:enable Metrics/MethodLength + # rubocop:enable Metrics/MethodLength, Metrics/AbcSize, Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity private @@ -182,6 +194,7 @@ def initiative_params :contact_phone, :partner_groups_role, :status_id, + :publication_status, :consent_to_share, :related_initiatives, :administrative_notes, diff --git a/app/controllers/parishes_controller.rb b/app/controllers/parishes_controller.rb index c966837..234157c 100644 --- a/app/controllers/parishes_controller.rb +++ b/app/controllers/parishes_controller.rb @@ -7,7 +7,7 @@ def show @parish = Parish.find(params['id']) @ward = @parish.ward @district = @ward.district - initiatives = Initiative.where(parish_id: @parish.id) + initiatives = Initiative.published.where(parish_id: @parish.id) @map_data = MapData.new(initiatives) @sectors = Sector.all end diff --git a/app/controllers/wards_controller.rb b/app/controllers/wards_controller.rb index 487396e..a87f884 100644 --- a/app/controllers/wards_controller.rb +++ b/app/controllers/wards_controller.rb @@ -6,7 +6,7 @@ class WardsController < ApplicationController def show @ward = Ward.find(params['id']) initiatives = - Initiative.includes(parish: %i[ward]).where( + Initiative.published.includes(parish: %i[ward]).where( parishes: { ward_id: @ward.id } ) @district = @ward.district diff --git a/app/helpers/initiatives_helper.rb b/app/helpers/initiatives_helper.rb index 36ee937..30888f4 100644 --- a/app/helpers/initiatives_helper.rb +++ b/app/helpers/initiatives_helper.rb @@ -18,4 +18,12 @@ def solutions_as_json(initiative) solution_map.to_json end + + def publication_statuses + statuses = Initiative.publication_statuses.to_h + statuses.reject! { |status| %w[rejected archived].include?(status) } unless user_is_admin? + statuses.map do |key, value| + [value.titlecase, key] + end + end end diff --git a/app/models/initiative.rb b/app/models/initiative.rb index cc6d3fa..3e29f36 100644 --- a/app/models/initiative.rb +++ b/app/models/initiative.rb @@ -4,17 +4,26 @@ # rubocop:disable Metrics/ClassLength class Initiative < ApplicationRecord + after_initialize :set_default_location + after_initialize :set_default_publication_status + belongs_to :owner, class_name: 'User' belongs_to :lead_group, class_name: 'Group' belongs_to :status, class_name: 'InitiativeStatus' belongs_to :parish + delegate :name, prefix: true, to: :status delegate :name, prefix: true, to: :lead_group - after_initialize :set_default_location + delegate :ward, to: :parish + delegate :district, to: :ward + delegate :county, to: :district + delegate :region, to: :county + has_many :solutions, class_name: 'InitiativeSolution', dependent: :destroy has_many :themes, class_name: 'InitiativeTheme', dependent: :destroy has_many_attached :images has_many :websites, class_name: 'InitiativeWebsite', dependent: :destroy + accepts_nested_attributes_for :solutions accepts_nested_attributes_for :themes accepts_nested_attributes_for :lead_group @@ -29,14 +38,13 @@ class Initiative < ApplicationRecord :contact_email, :contact_phone, :lead_group, + :publication_status, presence: true validate :at_least_one_solution_or_theme validate :validate_postcode - def website_empty?(attributes) - attributes['url'].blank? - end + enum publication_status: { draft: 'draft', published: 'published', archived: 'archived', rejected: 'rejected' } def validate_postcode ukpc = UKPostcode.parse(postcode) @@ -51,11 +59,6 @@ def at_least_one_solution_or_theme errors.add(:solution, 'at least one equired') if solutions.empty? && themes.empty? end - def set_default_location - self.latitude ||= 51.742 - self.longitude ||= -2.222 - end - def public_attributes if consent_to_share attributes @@ -65,6 +68,8 @@ def public_attributes end def fetch_location + return unless postcode + postcodes_url = "https://api.postcodes.io/postcodes/#{postcode.delete(' ')}" json_response = Net::HTTP.get(URI(postcodes_url)) JSON.parse(json_response)['result'] @@ -91,21 +96,13 @@ def create_location(location) end def self.approved - Initiative.all.map(&:to_public_initiative) + Initiative.published.map(&:to_public_initiative) end def to_public_initiative PublicInitiative.new(self) end - delegate :ward, to: :parish - - delegate :district, to: :ward - - delegate :county, to: :district - - delegate :region, to: :county - def location return unless parish @@ -129,5 +126,20 @@ def location_attributes } end # rubocop:enable Metrics/MethodLength + + private + + def set_default_location + self.latitude ||= 51.742 + self.longitude ||= -2.222 + end + + def set_default_publication_status + self.publication_status = 'draft' if publication_status.blank? + end + + def website_empty?(attributes) + attributes['url'].blank? + end end # rubocop:enable Metrics/ClassLength diff --git a/app/views/initiatives/_form.html.erb b/app/views/initiatives/_form.html.erb index 5f80ca2..8c4d484 100644 --- a/app/views/initiatives/_form.html.erb +++ b/app/views/initiatives/_form.html.erb @@ -170,6 +170,13 @@ <%= f.text_area :administrative_notes %> <% end %> + <% if publication_statuses.map {|s| s[1]}.include?(initiative.publication_status) %> + <%= f.form_field :publication_status, required: true do %> + <%= f.label :publication_status, 'Publication Status' %> + <%= f.select :publication_status, publication_statuses %> + <% end %> + <% end %> +