diff --git a/.gitignore b/.gitignore index 9c78fbf9..e61e2744 100644 --- a/.gitignore +++ b/.gitignore @@ -45,3 +45,6 @@ config/database.yml # Ignore application configuration /config/application.yml + +# Ignore image uplaods +/public/uploads diff --git a/Gemfile b/Gemfile index f37c413e..f64b1b56 100644 --- a/Gemfile +++ b/Gemfile @@ -108,6 +108,10 @@ gem 'will_paginate-bootstrap' # Markdown renderer gem 'redcarpet' +# Image Upload and Processing +gem 'carrierwave' +gem 'mini_magick' + # Ical generator gem 'icalendar' diff --git a/Gemfile.lock b/Gemfile.lock index 507c39c7..51449fb0 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -73,6 +73,10 @@ GEM rack (>= 1.0.0) rack-test (>= 0.5.4) xpath (~> 2.0) + carrierwave (1.0.0) + activemodel (>= 4.0.0) + activesupport (>= 4.0.0) + mime-types (>= 1.16) cliver (0.3.2) codeclimate-test-reporter (1.0.3) simplecov @@ -149,6 +153,7 @@ GEM mime-types (3.1) mime-types-data (~> 3.2015) mime-types-data (3.2016.0521) + mini_magick (4.6.0) mini_portile2 (2.1.0) minitest (5.10.1) nokogiri (1.6.8.1) @@ -318,6 +323,7 @@ DEPENDENCIES byebug cancancan capybara (~> 2.5) + carrierwave codeclimate-test-reporter (~> 1.0.0) combine_pdf coveralls @@ -335,6 +341,7 @@ DEPENDENCIES jquery-turbolinks jquery-ui-rails less-rails + mini_magick parser (~> 2.2.2.5) pdf-inspector pg @@ -361,5 +368,8 @@ DEPENDENCIES web-console (~> 2.0) will_paginate-bootstrap +RUBY VERSION + ruby 2.2.2p95 + BUNDLED WITH 1.13.7 diff --git a/Vagrantfile b/Vagrantfile index a10d0831..7849879b 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -26,5 +26,6 @@ Vagrant.configure("2") do |config| config.vm.provision "shell", inline: <<-SHELL apt-get update apt-get install -y phantomjs + apt-get install -y imagemagick SHELL -end \ No newline at end of file +end diff --git a/app/assets/stylesheets/events.css b/app/assets/stylesheets/events.css index 7298c069..aa6de49a 100644 --- a/app/assets/stylesheets/events.css +++ b/app/assets/stylesheets/events.css @@ -48,9 +48,6 @@ margin: 15px 0; padding-bottom: 15px; } -.event-preview.event-past { - opacity: 0.7; -} .front-section:nth-child(even) .event-preview { border-bottom: 1px solid rgba(255, 255, 255, 0.3); } @@ -108,4 +105,4 @@ width: 100%; height: 150px; margin-bottom: 15px; -} \ No newline at end of file +} diff --git a/app/controllers/emails_controller.rb b/app/controllers/emails_controller.rb index 0dfa8ef4..2a91e49d 100644 --- a/app/controllers/emails_controller.rb +++ b/app/controllers/emails_controller.rb @@ -6,7 +6,7 @@ def show @templates = EmailTemplate.with_status(get_email_template_status) application_letter_status = get_corresponding_application_letter_status - @addresses = @event.email_addresses_of_type(application_letter_status) + @addresses = @event.email_addresses_of_type_without_notification_sent(application_letter_status) @email = Email.new(hide_recipients: true, reply_to: Rails.configuration.reply_to_address, recipients: @addresses.join(','), subject: '', content: '') @@ -29,24 +29,26 @@ def submit def send_email @email = Email.new(email_params) @event = Event.find(params[:event_id]) - + status = get_email_template_status if @email.valid? - if get_corresponding_application_letter_status == :accepted + application_letter_status = get_corresponding_application_letter_status + if application_letter_status == :accepted @email.send_email_with_ical @event else @email.send_email end - if get_email_template_status == :acceptance + @event.set_status_notification_flag_for_applications_with_status(application_letter_status) + if status == :acceptance @event.acceptances_have_been_sent = true - elsif get_email_template_status == :rejection + elsif status == :rejection @event.rejections_have_been_sent = true end @event.save redirect_to @event, notice: t('.sending_successful') else - @templates = EmailTemplate.with_status(get_email_template_status) + @templates = EmailTemplate.with_status(status) flash.now[:alert] = t('.sending_failed') render :email diff --git a/app/controllers/events_controller.rb b/app/controllers/events_controller.rb index 1a98d5bc..5763a6fe 100644 --- a/app/controllers/events_controller.rb +++ b/app/controllers/events_controller.rb @@ -3,6 +3,7 @@ require 'pdf_generation/participants_pdf' require 'rubygems' require 'zip' +require 'carrierwave' class EventsController < ApplicationController @@ -252,7 +253,7 @@ def set_event end def event_params - params.require(:event).permit(:name, :description, :max_participants, :organizer, :knowledge_level, :application_deadline, :published, :hidden, :custom_application_fields => [], date_ranges_attributes: [:start_date, :end_date, :id]) + params.require(:event).permit(:name, :description, :image, :max_participants, :organizer, :knowledge_level, :application_deadline, :published, :hidden, :custom_application_fields => [], date_ranges_attributes: [:start_date, :end_date, :id]) end def add_event_query_conditions(query) diff --git a/app/controllers/requests_controller.rb b/app/controllers/requests_controller.rb index 532bd630..366da9b7 100644 --- a/app/controllers/requests_controller.rb +++ b/app/controllers/requests_controller.rb @@ -25,8 +25,9 @@ def edit # POST /requests def create @request = Request.new(request_params) - if @request.save + Mailer.send_generic_email(false, @request.email, Rails.configuration.reply_to_address, I18n.t('requests.email.topic'), + I18n.t('requests.email.content')) redirect_to root_path, notice: I18n.t('requests.notice.was_created') else render :new diff --git a/app/models/application_letter.rb b/app/models/application_letter.rb index 425a777c..e186df9d 100644 --- a/app/models/application_letter.rb +++ b/app/models/application_letter.rb @@ -25,13 +25,22 @@ class ApplicationLetter < ActiveRecord::Base validates_inclusion_of :grade, in: (VALID_GRADES.to_a.push(0)) validates :vegetarian, :vegan, :allergic, inclusion: { in: [true, false] } validates :vegetarian, :vegan, :allergic, exclusion: { in: [nil] } - validate :deadline_cannot_be_in_the_past, :if => Proc.new { |letter| !(letter.status_changed?) } - validate :status_cannot_be_changed, :if => Proc.new { |letter| letter.status_changed?} + validate :deadline_cannot_be_in_the_past, :if => Proc.new { |letter| !(letter.status_changed? || letter.status_notification_sent_changed?) } + validate :status_notification_sent_cannot_be_changed, :if => Proc.new { |letter| letter.status_notification_sent_changed? } + validate :status_cannot_be_changed, :if => Proc.new { |letter| letter.status_changed? } - enum status: {accepted: 1, rejected: 0, pending: 2, alternative: 3} + enum status: {accepted: 1, rejected: 0, pending: 2, alternative: 3, canceled: 4} validates :status, inclusion: { in: statuses.keys } + # Returns an array of selectable statuses + # + # @param none + # @return [Array ] array of selectable statuses + def self.selectable_statuses + ["accepted","rejected","pending","alternative"] + end + # Checks if the deadline is over # additionally only return if event and event.application_deadline is present # @@ -46,7 +55,21 @@ def after_deadline? # @param none # @return [Boolean] true if status changes are allowed def status_change_allowed? - !event.participant_selection_locked + if event.phase == :execution + (status_was == 'accepted' && status == 'canceled') || (status_was == 'alternative' && status == 'accepted') + elsif event.phase == :selection && event.participant_selection_locked + false + else + true + end + end + + # Checks if it is allowed to set the status_notification_sent flag + # + # @param none + # @return [Boolean] true if it can be changed + def status_notification_sent_change_allowed? + event.phase == :selection || event.phase == :execution end # Validator for after_deadline? @@ -85,6 +108,8 @@ def status_type else return I18n.t("application_status.pending_before_deadline") end + when ApplicationLetter.statuses[:canceled] + return I18n.t("application_status.canceled") else return I18n.t("application_status.alternative") end @@ -94,7 +119,15 @@ def status_type # Adds error def status_cannot_be_changed unless status_change_allowed? - errors.add(:event, "Die Bewerbungen wurden bereits bearbeitet, eine Statusänderung ist nicht mehr erlaubt.") + errors.add(:event, I18n.t('application_letters.validation.status_cannot_be_changed')) + end + end + + # Validator for status_change_allowed? + # Adds error + def status_notification_sent_cannot_be_changed + unless status_notification_sent_change_allowed? + errors.add(:event, I18n.t('application_letters.validation.status_notification_sent_cannot_be_changed')) end end diff --git a/app/models/event.rb b/app/models/event.rb index e71a441c..3873a9f9 100644 --- a/app/models/event.rb +++ b/app/models/event.rb @@ -21,6 +21,8 @@ class Event < ActiveRecord::Base serialize :custom_application_fields, Array + mount_uploader :image, EventImageUploader + has_many :application_letters has_many :agreement_letters has_many :participant_groups @@ -34,6 +36,13 @@ class Event < ActiveRecord::Base validates :hidden, exclusion: { in: [nil] } validates :published, inclusion: { in: [true, false] } validates :published, exclusion: { in: [nil] } + validate :check_image_dimensions + + # Use the image dimensions as returned from our uploader + # to verify that the image has sufficient size + def check_image_dimensions + errors.add(:image, I18n.t("events.errors.image_too_small")) if image.upload_width.present? && image.upload_height.present? && (image.upload_width < 200 || image.upload_height < 155) + end # Returns all participants for this event in following order: @@ -145,17 +154,26 @@ def send_mails_tooltip # @param none # @return none def accept_all_application_letters - application_letters.each do |application_letter| - application_letter.update(status: :accepted) + application_letters.map { |application| application.update(status: :accepted) } + end + + # Sets the status_notification_sent flag for all application letters of the given type + # + # @param status [Type] the desired application status the flag should be set for + # @return none + def set_status_notification_flag_for_applications_with_status(status) + applications = application_letters.select {|application| application.status == status.to_s} + applications.each do |application_letter| + application_letter.update(status_notification_sent: true) end end # Returns an array of strings of all email addresses of applications with a given status type # # @param type [Type] the status type of the email addresses that will be returned - # @return [Array] Array of all email addresses of applications with given type - def email_addresses_of_type(type) - applications = application_letters.where(status: ApplicationLetter.statuses[type]) + # @return [Array] Array of all email addresses of applications with given type, that don't have status_notification_sent set + def email_addresses_of_type_without_notification_sent(type) + applications = application_letters.where(status: ApplicationLetter.statuses[type], status_notification_sent: false) applications.collect { |a| a.user.email } end diff --git a/app/models/user.rb b/app/models/user.rb index 49fe92c2..a6d7ed3e 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -119,15 +119,16 @@ def older_than_required_age_at_start_date_of_event?(given_event, age) # @param [Event] current event (which application status will be excluded) # @return [Int] of number of currently accepted applications def accepted_applications_count(event) - ApplicationLetter.where(user_id: id, status: true).where.not(event: event).count() + ApplicationLetter.where(user_id: id, status: ApplicationLetter.statuses[:accepted]) + .where.not(event: event).count() end - # Returns the number of accepted applications from the user without counting status of current event application + # Returns the number of rejected applications from the user without counting status of current event application # # @param current event (which application status will be excluded) - # @return [Int] of number of currently accepted applications + # @return [Int] of number of currently rejected applications def rejected_applications_count(event) - ApplicationLetter.where(user_id: id, status: false).where.not(event: event).count() + ApplicationLetter.where(user_id: id, status: ApplicationLetter.statuses[:rejected]).where.not(event: event).count() end # Searches all users with last/first_name containing pattern diff --git a/app/uploaders/event_image_uploader.rb b/app/uploaders/event_image_uploader.rb new file mode 100644 index 00000000..1383f8a1 --- /dev/null +++ b/app/uploaders/event_image_uploader.rb @@ -0,0 +1,43 @@ +class EventImageUploader < CarrierWave::Uploader::Base + attr_reader :upload_width, :upload_height + + # image processing + include CarrierWave::MiniMagick + + storage :file + + # Return the directory that images will be uploaded to + # @return [String] the path relative to the `public` folder + def store_dir + "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" + end + + before :cache, :capture_size_before_cache + + # Fill in the upload sizes once the image has been uploaded, so that + # our model can use them for validation + def capture_size_before_cache(new_file) + # Only do this once, to the original version + if version_name.blank? + @upload_width, @upload_height = `identify -format "%wx %h" #{new_file.path}`.split(/x/).map { |dim| dim.to_i } + end + end + + version :list_view do + process resize_to_fill: [200, 155] + end + + version :detail_view do + process resize_to_fill: [1140, 200] + end + + version :thumb do + process resize_to_fill: [50, 50] + end + + # white list of extensions which are allowed to be uploaded + def extension_whitelist + %w(jpg jpeg gif png) + end + +end diff --git a/app/views/application_letters/_application_selective.html.erb b/app/views/application_letters/_application_selective.html.erb index c4d97515..be8e15e8 100644 --- a/app/views/application_letters/_application_selective.html.erb +++ b/app/views/application_letters/_application_selective.html.erb @@ -2,7 +2,7 @@ <%= form_for :application_letter, url: update_application_letter_status_path(application_letter), html: {method: :put} do |f| %>
- <% ApplicationLetter.statuses.keys.each do |key| %> + <% ApplicationLetter.selectable_statuses.each do |key| %>
<% if (can? :send_email, Email) && (@event.phase == :selection) %> -
- <%= form_tag event_email_show_path(@event), method: :get do %> - <%= hidden_field_tag "status", "acceptance" %> - <%= button_tag t('.sending_acceptances'), class: 'send-emails-button btn btn-default', disabled: @event.send_mails_tooltip.present? %> + <% if not @event.acceptances_have_been_sent %> +
+ <%= form_tag event_email_show_path(@event), method: :get do %> + <%= hidden_field_tag "status", "acceptance" %> + <%= button_tag t('.sending_acceptances'), class: 'send-emails-button btn btn-default', disabled: @event.send_mails_tooltip.present? %> + <% end %> +
<% end %> - <%= form_tag event_email_show_path(@event), method: :get do %> - <%= hidden_field_tag "status", "rejection" %> - <%= button_tag t('.sending_rejections'), class: 'send-emails-button btn btn-default', disabled: @event.send_mails_tooltip.present? %> + <% if not @event.rejections_have_been_sent %> +
+ <%= form_tag event_email_show_path(@event), method: :get do %> + <%= hidden_field_tag "status", "rejection" %> + <%= button_tag t('.sending_rejections'), class: 'send-emails-button btn btn-default', disabled: @event.send_mails_tooltip.present? %> + <% end %> +
<% end %> - -
<% end %> + <% if (can? :view_participants, Event) && (@event.phase == :execution) %> <%= link_to t('events.participants.show_participants'), event_path(@event) + "/participants" , :class => 'btn btn-primary btn-sm pull-right' %> <% end %> -
diff --git a/app/views/events/_event.html.erb b/app/views/events/_event.html.erb index 7e0ba54d..7a1272d0 100644 --- a/app/views/events/_event.html.erb +++ b/app/views/events/_event.html.erb @@ -1,5 +1,5 @@ -
- <%= image_tag "example.png", class: "img-rounded img-responsive img-float-corner-tr center-block" %> +
+ <%= image_tag event.image_url(:list_view), class: "img-rounded img-responsive img-float-corner-tr center-block" if event.image_url%>
<%= render "events/event_date_large", event: event %>
diff --git a/app/views/events/_form.html.erb b/app/views/events/_form.html.erb index 2125b27d..2677eec4 100644 --- a/app/views/events/_form.html.erb +++ b/app/views/events/_form.html.erb @@ -51,63 +51,73 @@
- <%= f.label :max_participants, :class => 'control-label col-lg-2' %> + <%= f.label :image, :class => 'control-label col-lg-2' %> + <%= image_tag(@event.image_url) if @event.image? %>
- <%= f.text_field :max_participants, :class => 'form-control' %> - <%=f.error_span(:max_participants) %> + <%= f.error_span(:image) %> + <%= I18n.t :"events.image_upload.upload_local_file" %>
+ <%= f.file_field :image %>
-
- <%= f.label :date_ranges, :class => 'control-label col-lg-2' %> -
- <% def date_picker_template(start_date = Date.current, end_date = Date.current) - start_picker = text_field_tag "event[date_ranges_attributes][][start_date]", (I18n.l start_date), - class: 'form-control', :"data-enable-datepicker" => 'true' - end_picker = text_field_tag "event[date_ranges_attributes][][end_date]", (I18n.l end_date), - class: 'form-control', :"data-enable-datepicker" => 'true' - "
#{start_picker} #{t 'date_range.to'} #{end_picker} "+ - "×
" - end %> +
+ <%= f.label :max_participants, :class => 'control-label col-lg-2' %> +
+ <%= f.text_field :max_participants, :class => 'form-control' %> + <%= f.error_span(:max_participants) %> +
+
+
+ <%= f.label :date_ranges, :class => 'control-label col-lg-2' %> +
+ <% def date_picker_template(start_date = Date.current, end_date = Date.current) + start_picker = text_field_tag "event[date_ranges_attributes][][start_date]", (I18n.l start_date), + class: 'form-control', :"data-enable-datepicker" => 'true' + end_picker = text_field_tag "event[date_ranges_attributes][][end_date]", (I18n.l end_date), + class: 'form-control', :"data-enable-datepicker" => 'true' + + "
#{start_picker} #{t 'date_range.to'} #{end_picker} "+ + "×
" + end %> - <%= - if @event.date_ranges.blank? - date_picker_template.html_safe - else - @event.date_ranges - .map { |d| date_picker_template d.start_date, d.end_date } - .reduce(:+) - .html_safe - end - %> - - <%= t 'events.form.add_timespan' %> - - <%=f.error_span(:date_ranges) %> + <%= + if @event.date_ranges.blank? + date_picker_template.html_safe + else + @event.date_ranges + .map { |d| date_picker_template d.start_date, d.end_date } + .reduce(:+) + .html_safe + end + %> + + <%= t 'events.form.add_timespan' %> + + <%=f.error_span(:date_ranges) %> +
+
- -
-
- <%= f.label :organizer, :class => 'control-label col-lg-2' %> -
- <%= f.text_field :organizer, :class => 'form-control', :placeholder => 'optional' %> - <%=f.error_span(:organizer) %> +
+ <%= f.label :organizer, :class => 'control-label col-lg-2' %> +
+ <%= f.text_field :organizer, :class => 'form-control', :placeholder => 'optional' %> + <%=f.error_span(:organizer) %> +
-
-
- <%= f.label :knowledge_level, :class => 'control-label col-lg-2' %> -
- <%= f.text_field :knowledge_level, :class => 'form-control', :placeholder => 'optional' %> - <%=f.error_span(:knowledge_level) %> +
+ <%= f.label :knowledge_level, :class => 'control-label col-lg-2' %> +
+ <%= f.text_field :knowledge_level, :class => 'form-control', :placeholder => 'optional' %> + <%=f.error_span(:knowledge_level) %> +
-
-
- <%= f.label :application_deadline, :class => 'control-label col-lg-2' %> -
- <%= f.text_field :application_deadline, :"data-enable-datepicker" => 'true', value: ((I18n.l @event.application_deadline) if @event.application_deadline.present?), class: "form-control" %> - <%=f.error_span(:application_deadline) %> +
+ <%= f.label :application_deadline, :class => 'control-label col-lg-2' %> +
+ <%= f.text_field :application_deadline, :"data-enable-datepicker" => 'true', value: ((I18n.l @event.application_deadline) if @event.application_deadline.present?), class: "form-control" %> + <%=f.error_span(:application_deadline) %> +
-
<%= (render 'custom_application_fields_input', form: f) if @event.new_record? %>
@@ -123,6 +133,7 @@ :data => { :confirm => t('.confirm', :default => t("events.confirmation_prompts.confirm_delete", :default => 'Are you sure?')) }, :class => 'btn btn-danger' %> <% end %> +
diff --git a/config/locales/de.application_letters.yml b/config/locales/de.application_letters.yml index b27d5acd..bab7ff6c 100644 --- a/config/locales/de.application_letters.yml +++ b/config/locales/de.application_letters.yml @@ -40,6 +40,9 @@ de: submit: create: "Anmelden" update: "Anmeldung aktualisieren" + validation: + status_cannot_be_changed: "Die Bewerbungen wurden bereits bearbeitet, eine Statusänderung ist nicht mehr erlaubt." + status_notification_sent_cannot_be_changed: "Das Status-Benachrichtungsflag kann noch nicht gesetzt werden" fields_filled_in: "Wir haben einige Felder bereits für dich ausgefüllt. Falls sich seit deiner letzten Bewerbung etwas geändert hat, kannst du es jetzt anpassen." @@ -74,6 +77,7 @@ de: pending: "Ausstehend" pending_before_deadline: "Beworben" pending_after_deadline: "In Bearbeitung" + canceled: "Abgesagt" alternative: "Nachrücker" diff --git a/config/locales/de.events.yml b/config/locales/de.events.yml index fbfe2b2d..55e65f38 100644 --- a/config/locales/de.events.yml +++ b/config/locales/de.events.yml @@ -138,6 +138,10 @@ de: page: "Seite" errors: application_deadline_before_start_of_event: "Bewerbungsschluss muss vor Beginn der Veranstaltung liegen" + image_too_small: "Das ausgewählte Bild muss mindestens 200 x 155 Pixel groß sein" + + image_upload: + upload_local_file: "Lokale Datei hochladen" activerecord: models: @@ -148,6 +152,7 @@ de: event: name: "Name" description: "Beschreibung" + image: "Bild" max_participants: "Maximale Teilnehmerzahl" kind: "Art" active: "Aktiv" diff --git a/config/locales/de.requests.yml b/config/locales/de.requests.yml index a53ad0b6..1490cbbf 100644 --- a/config/locales/de.requests.yml +++ b/config/locales/de.requests.yml @@ -23,6 +23,10 @@ de: was_updated: "Die Anfrage wurde aktualisiert" was_accepted: "Die Anfrage wurde angenommen" was_deleted: "Die Anfrage wurde gelöscht" + email: + topic: "Ihre Anfrage auf dem HPI Workshop-Portal" + content: "Hallo! + Ihre Anfrage ist bei uns eingegangen und wir melden uns schnellstmöglich bei Ihnen, um weitere Details abzustimmen." activerecord: models: request: diff --git a/db/migrate/20170125201341_add_image_to_events.rb b/db/migrate/20170125201341_add_image_to_events.rb new file mode 100644 index 00000000..818ecb51 --- /dev/null +++ b/db/migrate/20170125201341_add_image_to_events.rb @@ -0,0 +1,5 @@ +class AddImageToEvents < ActiveRecord::Migration + def change + add_column :events, :image, :string + end +end diff --git a/db/migrate/20170203180638_add_status_notification_sent_to_application_letters.rb b/db/migrate/20170203180638_add_status_notification_sent_to_application_letters.rb new file mode 100644 index 00000000..3eb46f1e --- /dev/null +++ b/db/migrate/20170203180638_add_status_notification_sent_to_application_letters.rb @@ -0,0 +1,5 @@ +class AddStatusNotificationSentToApplicationLetters < ActiveRecord::Migration + def change + add_column :application_letters, :status_notification_sent, :boolean, default: false, null: false + end +end diff --git a/db/sample_data.rb b/db/sample_data.rb index c5e2f2e4..902dc364 100644 --- a/db/sample_data.rb +++ b/db/sample_data.rb @@ -10,12 +10,15 @@ def add_sample_data events[:programmierkurs] = event_programmierkurs events[:mintcamp] = event_mintcamp - events[:bechersaeuberungsevent] = event_bechersaeuberungsevent events[:gongakrobatik] = event_gongakrobatik events[:batterie_akustik] = event_batterie_akustik events[:bachlorpodium] = event_bachlorpodium events[:past_deadline_event] = event_gongakrobatik + # past events are not valid by definition, however we + # would like to pretend to have some old ones + event_bechersaeuberungsevent.save!(validate: false) + users = Hash.new users[:pupil] = user_pupil users[:teacher] = user_teacher diff --git a/db/sample_data/events.rb b/db/sample_data/events.rb index efc32f7a..07119cff 100644 --- a/db/sample_data/events.rb +++ b/db/sample_data/events.rb @@ -40,10 +40,11 @@ def event_mintcamp end def event_bechersaeuberungsevent - date_range_singleday = DateRange.create!( - start_date: Date.new(2017, 04, 04), - end_date: Date.new(2017, 04, 05) + date_range_singleday = DateRange.new( + start_date: Date.yesterday, + end_date: Date.yesterday ) + date_range_singleday.save!(validate: false) Event.new( name: 'Bechersäuberungsevent', description: 'Es dreht sich den ganzen Tag um das Säubern von Bechern. Wie säubert man einen Becher am effizientesten oder am schnellsten? Wie immer bieten wir eine Reihe an Expertenvorträgen an. Dieses Mal erfahrt ihr unter anderem wie ihr Edding-Markierungen selbst nach einer Spülmaschinen-Reinigung noch entfernen könnt oder wie man die richtige Größe für Becher-Stapel herausfindet und anwendet.', @@ -51,7 +52,7 @@ def event_bechersaeuberungsevent organizer: 'FSR', knowledge_level: 'Anfänger', date_ranges: [date_range_singleday], - application_deadline: Date.tomorrow, + application_deadline: Date.yesterday.prev_day(2), published: true, hidden: false, custom_application_fields: ['Lieblings-Becherart', 'Kannst du eine eigene Spülmaschine mitbringen?'] diff --git a/db/schema.rb b/db/schema.rb index 52c0aff1..43294350 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20170201201932) do +ActiveRecord::Schema.define(version: 20170203180638) do create_table "agreement_letters", force: :cascade do |t| t.integer "user_id", null: false @@ -26,11 +26,11 @@ create_table "application_letters", force: :cascade do |t| t.string "motivation" - t.integer "user_id", null: false - t.integer "event_id", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.integer "status", default: 2, null: false + t.integer "user_id", null: false + t.integer "event_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.integer "status", default: 2, null: false t.integer "grade" t.string "coding_skills" t.string "emergency_number" @@ -40,6 +40,7 @@ t.text "custom_application_fields" t.text "annotation" t.string "organisation" + t.boolean "status_notification_sent", default: false, null: false end add_index "application_letters", ["event_id"], name: "index_application_letters_on_event_id" @@ -83,6 +84,7 @@ t.date "application_deadline" t.text "custom_application_fields" t.boolean "hidden", default: false + t.string "image" t.boolean "rejections_have_been_sent", default: false t.boolean "acceptances_have_been_sent", default: false end diff --git a/spec/controllers/email_controller_spec.rb b/spec/controllers/email_controller_spec.rb index db2d23e9..25d6b4aa 100644 --- a/spec/controllers/email_controller_spec.rb +++ b/spec/controllers/email_controller_spec.rb @@ -25,7 +25,7 @@ expect(assigns(:email).recipients).to eq(@application.user.email) end - it "sets @template with template for accepted emails" do + it "sets @template with template for acceptance emails" do get :show, event_id: @event.id, status: :acceptance expect(assigns(:templates)).to eq([@template]) end @@ -43,7 +43,7 @@ expect(assigns(:email).recipients).to eq(@application.user.email) end - it "sets @template with template for rejected emails" do + it "sets @template with template for rejection emails" do get :show, event_id: @event.id, status: :rejection expect(assigns(:templates)).to eq([@template]) end @@ -145,4 +145,4 @@ end end end -end \ No newline at end of file +end diff --git a/spec/controllers/requests_controller_spec.rb b/spec/controllers/requests_controller_spec.rb index 90ef6544..b856fbff 100644 --- a/spec/controllers/requests_controller_spec.rb +++ b/spec/controllers/requests_controller_spec.rb @@ -188,6 +188,10 @@ expect(assigns(:request)).to be_persisted end + it "sends an email" do + expect{ post :create, request: valid_attributes, session: valid_session }.to change{ ActionMailer::Base.deliveries.count }.by(1) + end + it "redirects to the homepage" do post :create, request: valid_attributes, session: valid_session expect(response).to redirect_to(root_path) @@ -200,6 +204,10 @@ expect(assigns(:request)).to be_a_new(Request) end + it "does not send an email" do + expect{ post :create, request: invalid_attributes, session: valid_session }.not_to change{ ActionMailer::Base.deliveries.count } + end + it "re-renders the 'new' template" do post :create, request: invalid_attributes, session: valid_session expect(response).to render_template("new") diff --git a/spec/factories/application_letters.rb b/spec/factories/application_letters.rb index c7c6fb31..16c5f624 100644 --- a/spec/factories/application_letters.rb +++ b/spec/factories/application_letters.rb @@ -24,6 +24,7 @@ event annotation "Some" custom_application_fields ["Value 1", "Value 2", "Value 3"] + status_notification_sent false end factory :application_letter2, parent: :application_letter do @@ -53,6 +54,10 @@ status :alternative end + factory :application_letter_canceled, parent: :application_letter do + status :canceled + end + factory :accepted_application_with_agreement_letters, parent: :application_letter do status :accepted after(:build) do |application_letter| diff --git a/spec/factories/events.rb b/spec/factories/events.rb index 3af49db6..314f4518 100644 --- a/spec/factories/events.rb +++ b/spec/factories/events.rb @@ -130,7 +130,7 @@ end end - trait :in_selection_phase do + trait :in_selection_phase_with_no_mails_sent do after(:build) do |event| event.published = true event.application_deadline = Date.yesterday @@ -139,6 +139,33 @@ end end + trait :in_selection_phase_with_participants_locked do + after(:build) do |event| + event.published = true + event.application_deadline = Date.yesterday + event.acceptances_have_been_sent = true + event.rejections_have_been_sent = false + end + end + + trait :in_selection_phase_with_acceptances_sent do + after(:build) do |event| + event.published = true + event.application_deadline = Date.yesterday + event.acceptances_have_been_sent = true + event.rejections_have_been_sent = false + end + end + + trait :in_selection_phase_with_rejections_sent do + after(:build) do |event| + event.published = true + event.application_deadline = Date.yesterday + event.acceptances_have_been_sent = false + event.rejections_have_been_sent = true + end + end + trait :in_execution_phase do after(:build) do |event| event.published = true @@ -148,6 +175,15 @@ end end + trait :with_no_status_notification_sent_yet do + after(:create) do |event| + event.application_letters.each do |application| + application.status_notification_sent = false + application.save! if application.changed? + end + end + end + factory :event_with_accepted_applications do name "Event-Name" description "Event-Description" @@ -161,7 +197,7 @@ organizer "Workshop-Organizer" knowledge_level "Workshop-Knowledge Level" application_deadline Date.current - + after(:create) do |event, evaluator| create_list(:application_letter_accepted, evaluator.accepted_application_letters_count, event: event) create_list(:application_letter_rejected, evaluator.rejected_application_letters_count, event: event) @@ -172,7 +208,31 @@ create_list(:accepted_application_with_agreement_letters, evaluator.accepted_application_letters_count, event: event) end end + end + + factory :event_with_applications_in_various_states do + name "Event-Name" + description "Event-Description" + max_participants 20 + date_ranges { build_list :date_range, 1 } + transient do + accepted_application_letters_count 5 + rejected_application_letters_count 5 + alternative_application_letters_count 2 + canceled_application_letters_count 1 + pending_application_letters_count 0 + end + organizer "Workshop-Organizer" + knowledge_level "Workshop-Knowledge Level" + application_deadline Date.current + after(:create) do |event, evaluator| + create_list(:application_letter_accepted, evaluator.accepted_application_letters_count, event: event) + create_list(:application_letter_rejected, evaluator.rejected_application_letters_count, event: event) + create_list(:application_letter_alternative, evaluator.alternative_application_letters_count, event: event) + create_list(:application_letter_canceled, evaluator.canceled_application_letters_count, event: event) + create_list(:application_letter_pending, evaluator.pending_application_letters_count, event: event) + end end end end diff --git a/spec/features/event_spec.rb b/spec/features/event_spec.rb index bd2e5cb3..09a1ea02 100644 --- a/spec/features/event_spec.rb +++ b/spec/features/event_spec.rb @@ -241,6 +241,31 @@ visit edit_event_path(event) expect(page).to_not have_text(I18n.t "events.form.add_field") end + + it "should allow uploading images" do + visit new_event_path + + fill_in "Maximale Teilnehmerzahl", :with => 25 + fill_in "event[date_ranges_attributes][][start_date]", :with => I18n.l(Date.tomorrow.next_day(2)) + fill_in "event[date_ranges_attributes][][end_date]", :with => I18n.l(Date.tomorrow.next_day(3)) + fill_in "event_application_deadline", :with => I18n.l(Date.tomorrow) + + attach_file "Bild", File.join(Rails.root + 'spec/testfiles/image_upload_test.png') + click_button I18n.t(".events.form.create") + end + + it "should not allow uploading images that are too small" do + visit new_event_path + + fill_in "Maximale Teilnehmerzahl", :with => 25 + fill_in "event[date_ranges_attributes][][start_date]", :with => I18n.l(Date.tomorrow.next_day(2)) + fill_in "event[date_ranges_attributes][][end_date]", :with => I18n.l(Date.tomorrow.next_day(3)) + fill_in "event_application_deadline", :with => I18n.l(Date.tomorrow) + + attach_file "Bild", File.join(Rails.root + 'spec/testfiles/too_small_image.png') + click_button I18n.t(".events.form.create") + expect(page).to have_text(I18n.t "events.errors.image_too_small") + end end describe "show page" do diff --git a/spec/features/events_spec.rb b/spec/features/events_spec.rb index 7cf9ea01..7eaeefe5 100644 --- a/spec/features/events_spec.rb +++ b/spec/features/events_spec.rb @@ -49,7 +49,7 @@ end scenario "logged in as Organizer I want to be unable to send emails if there is any unclassified application left" do - @event = FactoryGirl.build(:event, :with_diverse_open_applications, :in_selection_phase) + @event = FactoryGirl.build(:event, :with_diverse_open_applications, :in_selection_phase_with_no_mails_sent) login(:organizer) @event.update!(max_participants: 1) visit event_path(@event) @@ -58,7 +58,7 @@ end scenario "logged in as Organizer I want to be unable to send emails if there is a negative number of free places left" do - @event = FactoryGirl.create(:event, :in_selection_phase) + @event = FactoryGirl.create(:event, :in_selection_phase_with_no_mails_sent) login(:organizer) @event.update!(max_participants: 1) 2.times do |n| @@ -71,8 +71,9 @@ expect(page).to have_css('button[disabled]', text: I18n.t('events.applicants_overview.sending_rejections')) end - scenario "logged in as Organizer I want to be able to send an email to all accepted applicants" do - @event = FactoryGirl.create(:event, :in_selection_phase) + + scenario "logged in as Organizer I want to be able to send an email to all accepted applicants in selection phase" do + @event = FactoryGirl.create(:event, :in_selection_phase_with_no_mails_sent) login(:organizer) @event.update!(max_participants: 2) 2.times do |n| @@ -89,8 +90,8 @@ expect{click_button I18n.t('emails.email_form.send')}.to change{ActionMailer::Base.deliveries.count}.by(1) end - scenario "logged in as Organizer I want to be able to send an email to all rejected applicants" do - @event = FactoryGirl.create(:event, :in_selection_phase) + scenario "logged in as Organizer I want to be able to send an email to all rejected applicants in selection phase" do + @event = FactoryGirl.create(:event, :in_selection_phase_with_no_mails_sent) login(:organizer) @event.update!(max_participants: 2) 2.times do |n| @@ -125,9 +126,9 @@ scenario "logged in as Organizer I can change application status with radio buttons in selection phase" do login(:organizer) - @event = FactoryGirl.create(:event, :with_open_application, :in_selection_phase) + @event = FactoryGirl.create(:event, :with_open_application, :in_selection_phase_with_no_mails_sent) visit event_path(@event) - ApplicationLetter.statuses.keys.each do |new_status| + ApplicationLetter.selectable_statuses.each do |new_status| choose(I18n.t "application_status.#{new_status}") expect(ApplicationLetter.where(id: @event.application_letters.first.id)).to exist end @@ -135,7 +136,7 @@ scenario "logged in as Organizer I can change application status with radio buttons without the page reloading in selection phase", js: true do login(:organizer) - @event = FactoryGirl.create(:event, :with_open_application, :in_selection_phase) + @event = FactoryGirl.create(:event, :with_open_application, :in_selection_phase_with_no_mails_sent) visit event_path(@event) find('label', text: I18n.t('application_status.accepted')).click check_values = lambda { @@ -166,8 +167,29 @@ end end + scenario "logged in as Organizer I can send acceptance and then rejection emails and by that change the status notification flag" do + login(:organizer) + event = FactoryGirl.create(:event_with_accepted_applications, :in_selection_phase_with_no_mails_sent, :with_no_status_notification_sent_yet) + + %w[accepted rejected].each do |status| + applications = event.application_letters.select { | application_letter | application_letter.status == status } + expect(applications.size).to be > 0 + visit event_path(event) + send_email_button_label = (status == 'accepted') ? 'sending_acceptances' : 'sending_rejections' + click_button(I18n.t("events.applicants_overview.#{send_email_button_label}")) + expect(page).to have_current_path(event_email_show_path(event_id: event.id), only_path: true) + fill_in :email_subject, with: "Subject" + fill_in :email_content, with: "Content" + click_button I18n.t('.emails.email_form.send') + applications.each do |letter| + letter.reload + expect(letter.status_notification_sent).to be true + end + end + end + scenario "logged in as Organizer I can push the accept all button to accept all applicants" do - @event = FactoryGirl.create(:event, :with_diverse_open_applications, :in_selection_phase) + @event = FactoryGirl.create(:event, :with_diverse_open_applications, :in_selection_phase_with_no_mails_sent) @event.max_participants = @event.application_letters.size + 1 @event.save login(:organizer) @@ -275,7 +297,7 @@ scenario "logged in as Organizer I can filter displayed application letters by their status and simultaneously sort them", js: true do login(:organizer) - @event = FactoryGirl.create(:event_with_accepted_applications) + @event = FactoryGirl.create(:event_with_applications_in_various_states) @event.application_letters.each do |letter| letter.user.profile = FactoryGirl.build(:profile, user: letter.user) end @@ -302,11 +324,13 @@ .map {|letter| letter.user.profile.name } expect(page).to contain_ordered(sorted_accepted_names) - # list rejected, pending + # list all others click_button I18n.t 'events.applicants_overview.filter_by' uncheck I18n.t 'application_status.accepted' check I18n.t 'application_status.rejected' check I18n.t 'application_status.pending' + check I18n.t 'application_status.alternative' + check I18n.t 'application_status.canceled' click_button I18n.t 'events.applicants_overview.filter' expect(page).to have_every_text(not_accepted_names) diff --git a/spec/models/application_letter_spec.rb b/spec/models/application_letter_spec.rb index b306b5e4..6b08fa6c 100644 --- a/spec/models/application_letter_spec.rb +++ b/spec/models/application_letter_spec.rb @@ -70,17 +70,59 @@ end it "can not be updated after event application deadline" do - application = FactoryGirl.build(:application_letter_deadline_over) - expect(application).to_not be_valid + application = FactoryGirl.build(:application_letter) + %i[in_selection_phase_with_no_mails_sent in_execution_phase].each do | phase | + application.event = FactoryGirl.create(:event, phase) + expect(application).to_not be_valid + end end - it "can not be updated if status is changed and participant selection is locked" do + %i[accepted canceled alternative pending].each do | new_status | + it "cannot update the status in execution phase from rejected into #{new_status}" do + application = FactoryGirl.create(:application_letter_rejected) + application.event = FactoryGirl.create(:event, :in_execution_phase) + application.status = new_status + expect(application).to_not be_valid + end + end + + it "can be canceled (only) if it was accepted before in execution phase" do + application = FactoryGirl.create(:application_letter_accepted) + application.event = FactoryGirl.create(:event, :in_execution_phase) + %i[accepted alternative pending rejected].each do | new_status | + application.status = new_status + expect(application).to_not be_valid + end + application.status = :canceled + expect(application).to be_valid + end + + it "can be promoted to accepted if it was alternative before in execution phase" do + application = FactoryGirl.create(:application_letter_alternative) + application.event = FactoryGirl.create(:event, :in_execution_phase) + %i[alternative canceled pending rejected].each do | new_status | + application.status = new_status + expect(application).to_not be_valid + end + application.status = :accepted + expect(application).to be_valid + end + + it "can update the status in selection phase" do application = FactoryGirl.build(:application_letter) - application.event.acceptances_have_been_sent = true - application.event.rejections_have_been_sent = true - expect(application.event.participant_selection_locked).to be(true) + application.event = FactoryGirl.create(:event, :in_selection_phase_with_no_mails_sent) application.status = :rejected - expect(application).to_not be_valid + expect(application).to be_valid + end + + it "can not be updated if status is changed and participant selection is locked" do + application = FactoryGirl.build(:application_letter) + %i[in_selection_phase_with_participants_locked in_execution_phase].each do |phase| + application.event = FactoryGirl.create(:event, phase) + expect(application.event.participant_selection_locked).to be(true) + application.status = :rejected + expect(application).to_not be_valid + end end it "can be updated if status is changed and participant selection is not locked" do diff --git a/spec/models/email_template_spec.rb b/spec/models/email_template_spec.rb index eaf98e2f..9247e177 100644 --- a/spec/models/email_template_spec.rb +++ b/spec/models/email_template_spec.rb @@ -34,9 +34,9 @@ end it "returns correct templates by status" do - @accepted_template = FactoryGirl.create(:email_template, :acceptance) - @rejected_template = FactoryGirl.create(:email_template, :rejection) - expect(EmailTemplate.with_status(:acceptance)).to eq([@accepted_template]) - expect(EmailTemplate.with_status(:rejection)).to eq([@rejected_template]) + accepted_template = FactoryGirl.create(:email_template, :acceptance) + rejected_template = FactoryGirl.create(:email_template, :rejection) + expect(EmailTemplate.with_status(:acceptance)).to eq([accepted_template]) + expect(EmailTemplate.with_status(:rejection)).to eq([rejected_template]) end -end \ No newline at end of file +end diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb index fdeff7a0..6d67f34e 100644 --- a/spec/models/event_spec.rb +++ b/spec/models/event_spec.rb @@ -85,14 +85,18 @@ end it "computes the email addresses of the accepted and the rejected applications" do - event = FactoryGirl.create(:event) + event = FactoryGirl.create(:event, :in_selection_phase_with_no_mails_sent) accepted_application_letter_1 = FactoryGirl.create(:application_letter_accepted, :event => event, :user => FactoryGirl.create(:user)) accepted_application_letter_2 = FactoryGirl.create(:application_letter_accepted, :event => event, :user => FactoryGirl.create(:user)) accepted_application_letter_3 = FactoryGirl.create(:application_letter_accepted, :event => event, :user => FactoryGirl.create(:user)) - rejected_application_letter = FactoryGirl.create(:application_letter_rejected, :event => event, :user => FactoryGirl.create(:user)) - [accepted_application_letter_1, accepted_application_letter_2, accepted_application_letter_3, rejected_application_letter].each { |letter| event.application_letters.push(letter) } - expect(event.email_addresses_of_type(:accepted)).to contain_exactly(accepted_application_letter_1.user.email, accepted_application_letter_2.user.email, accepted_application_letter_3.user.email) - expect(event.email_addresses_of_type(:rejected)).to contain_exactly(rejected_application_letter.user.email) + accepted_application_letter_4 = FactoryGirl.create(:application_letter_accepted, status_notification_sent: true, event: event, user: FactoryGirl.create(:user)) + rejected_application_letter_1 = FactoryGirl.create(:application_letter_rejected, :event => event, :user => FactoryGirl.create(:user)) + rejected_application_letter_2 = FactoryGirl.create(:application_letter_rejected, status_notification_sent: true, :event => event, :user => FactoryGirl.create(:user)) + + [accepted_application_letter_1, accepted_application_letter_2, accepted_application_letter_3, accepted_application_letter_4, rejected_application_letter_1, rejected_application_letter_2].each { |letter| event.application_letters.push(letter) } + + expect(event.email_addresses_of_type_without_notification_sent(:accepted)).to contain_exactly(accepted_application_letter_1.user.email, accepted_application_letter_2.user.email, accepted_application_letter_3.user.email) + expect(event.email_addresses_of_type_without_notification_sent(:rejected)).to contain_exactly(rejected_application_letter_1.user.email) end it "is either a public or private" do @@ -174,9 +178,9 @@ it "computes the number of occupied places" do event = FactoryGirl.create(:event) application_letter = FactoryGirl.create(:application_letter, user: FactoryGirl.create(:user), event: event) - application_letter_accepted = FactoryGirl.create(:application_letter_accepted, user: FactoryGirl.create(:user), event: event) + FactoryGirl.create(:application_letter_accepted, user: FactoryGirl.create(:user), event: event) expect(event.compute_occupied_places).to eq(1) - application_letter_accepted_2 = FactoryGirl.create(:application_letter_accepted, user: FactoryGirl.create(:user), event: event) + FactoryGirl.create(:application_letter_accepted, user: FactoryGirl.create(:user), event: event) expect(event.compute_occupied_places).to eq(2) end @@ -190,20 +194,6 @@ expect(Event.future).to include(event_future) end - describe "returns applicants email list" do - before :each do - @event = FactoryGirl.create(:event) - end - - it "returns email address only of the given type" do - @accepted_application = FactoryGirl.create(:application_letter_accepted, event: @event, user: FactoryGirl.create(:user)) - @rejected_application = FactoryGirl.create(:application_letter_rejected, event: @event, user: FactoryGirl.create(:user)) - expect(@event.email_addresses_of_type(:accepted)).to contain_exactly(@accepted_application.user.email) - expect(@event.email_addresses_of_type(:rejected)).to contain_exactly(@rejected_application.user.email) - end - - end - it "generates an application letter list ordered by first name" do @event = FactoryGirl.create(:event) @user1 = FactoryGirl.create(:user, email:'a@b.com') @@ -233,12 +223,29 @@ end it "accepts all its application letters" do - event = FactoryGirl.create :event, :with_diverse_open_applications + event = FactoryGirl.create :event, :with_diverse_open_applications, :in_selection_phase_with_no_mails_sent event.accept_all_application_letters application_letters = ApplicationLetter.where(event: event.id) expect(application_letters.all? { |application_letter| application_letter.status == 'accepted' }).to eq(true) end + %i[accepted rejected].each do |status| + it "sets the status notification flag for all #{status} applications" do + event = FactoryGirl.create :event_with_accepted_applications, :in_selection_phase_with_no_mails_sent + application_letters = event.application_letters.select{ |application_letter| application_letter.status == status.to_s } + application_letters.each do |application| + application.status_notification_sent = false + application.save! if application.changed? + end + event.set_status_notification_flag_for_applications_with_status(status) + expect(application_letters.count).to be > 0 + application_letters.each do |application| + application.reload + expect(application.status_notification_sent).to be true + end + end + end + it "is in draft phase" do event = FactoryGirl.build(:event, :in_draft_phase) expect(event.phase).to eq(:draft) @@ -250,7 +257,11 @@ end it "is in selection phase" do - event = FactoryGirl.build(:event, :in_selection_phase) + event = FactoryGirl.build(:event, :in_selection_phase_with_no_mails_sent) + expect(event.phase).to eq(:selection) + event = FactoryGirl.build(:event, :in_selection_phase_with_acceptances_sent) + expect(event.phase).to eq(:selection) + event = FactoryGirl.build(:event, :in_selection_phase_with_rejections_sent) expect(event.phase).to eq(:selection) end diff --git a/spec/testfiles/image_upload_test.png b/spec/testfiles/image_upload_test.png new file mode 100644 index 00000000..cd2f7e49 Binary files /dev/null and b/spec/testfiles/image_upload_test.png differ diff --git a/spec/testfiles/too_small_image.png b/spec/testfiles/too_small_image.png new file mode 100644 index 00000000..dba9cfaf Binary files /dev/null and b/spec/testfiles/too_small_image.png differ diff --git a/spec/views/application_letters/index.html.erb_spec.rb b/spec/views/application_letters/index.html.erb_spec.rb index 76d8db29..bb0f57af 100644 --- a/spec/views/application_letters/index.html.erb_spec.rb +++ b/spec/views/application_letters/index.html.erb_spec.rb @@ -29,6 +29,11 @@ render expect(rendered).to have_content(I18n.t("application_status.alternative")) end + it "checks if page displays canceled status application letter" do + @application_letters = [FactoryGirl.create(:application_letter_canceled)] + render + expect(rendered).to have_content(I18n.t("application_status.canceled")) + end end it "should display the name of the event" do diff --git a/spec/views/application_letters/show.html.erb_spec.rb b/spec/views/application_letters/show.html.erb_spec.rb index d02f6eb6..851de593 100644 --- a/spec/views/application_letters/show.html.erb_spec.rb +++ b/spec/views/application_letters/show.html.erb_spec.rb @@ -6,17 +6,29 @@ @application_letter = assign(:application_letter, FactoryGirl.create(:application_letter)) @application_note = assign(:application_note, FactoryGirl.create(:application_note, application_letter: @application_letter)) @application_letter.user.profile = FactoryGirl.build(:profile) + profile = FactoryGirl.create(:profile, user: (FactoryGirl.create :user, role: :organizer)) + sign_in profile.user + end + it "renders radio buttons for accept reject pending and alternative, but not canceled in selection phase" do + @application_letter.event = FactoryGirl.create(:event, :in_selection_phase_with_no_mails_sent) render + expect(rendered).to have_css("label", text: I18n.t('application_status.accepted')) + expect(rendered).to have_css("label", text: I18n.t('application_status.rejected')) + expect(rendered).to have_css("label", text: I18n.t('application_status.pending')) + expect(rendered).to have_css("label", text: I18n.t('application_status.alternative')) + expect(rendered).to_not have_css("label", text: I18n.t('application_status.canceled')) end it "renders application's attributes" do + render expect(rendered).to have_text(@application_letter.event.name) expect(rendered).to have_text(@application_letter.motivation) expect(rendered).to have_text(@application_letter.annotation) end it "renders applicant's attributes" do + render expect(rendered).to have_text(@application_letter.user.profile.name) expect(rendered).to have_text(@application_letter.user.profile.gender) expect(rendered).to have_text(@application_letter.user.profile.age_at_time(@application_letter.event.start_date)) diff --git a/spec/views/events/participants.html.erb_spec.rb b/spec/views/events/participants.html.erb_spec.rb index 2308fd03..d50dee64 100644 --- a/spec/views/events/participants.html.erb_spec.rb +++ b/spec/views/events/participants.html.erb_spec.rb @@ -77,7 +77,7 @@ end it "does not show the print badges button when the event is in selection phase" do - @event = assign(:event, FactoryGirl.create(:event_with_accepted_applications, :in_selection_phase)) + @event = assign(:event, FactoryGirl.create(:event_with_accepted_applications, :in_selection_phase_with_no_mails_sent)) @participants = assign(:participants, @event.participants) render expect(rendered).to_not have_link(t(:print_button_label, scope: 'events.badges')) diff --git a/spec/views/events/show.html.erb_spec.rb b/spec/views/events/show.html.erb_spec.rb index c40d61c1..f761f03d 100644 --- a/spec/views/events/show.html.erb_spec.rb +++ b/spec/views/events/show.html.erb_spec.rb @@ -76,6 +76,18 @@ expect(rendered).to have_css("td", :text => @application_letter.user.profile.age_at_time(@event.start_date)) end + it "logged in as organizer it renders radio buttons for accept reject pending and alternative, but not canceled in selection phase" do + sign_in(FactoryGirl.create(:user, role: :organizer)) + @event = assign(:event, FactoryGirl.create(:event, :with_diverse_open_applications, :in_selection_phase_with_no_mails_sent)) + @application_letters = @event.application_letters #TODO I couldnt find a assign(:application_letters), still this gives the view access to it. + render + expect(rendered).to have_css("label", text: I18n.t('application_status.accepted')) + expect(rendered).to have_css("label", text: I18n.t('application_status.rejected')) + expect(rendered).to have_css("label", text: I18n.t('application_status.pending')) + expect(rendered).to have_css("label", text: I18n.t('application_status.alternative')) + expect(rendered).to_not have_css("label", text: I18n.t('application_status.canceled')) + end + it "displays application details button" do render expect(rendered).to have_link(t(:details, scope: 'events.applicants_overview')) @@ -98,7 +110,7 @@ end it "should not display accept-all-button for non-organizers" do - @event = assign(:event, FactoryGirl.create(:event, :in_selection_phase)) + @event = assign(:event, FactoryGirl.create(:event, :in_selection_phase_with_no_mails_sent)) @event.max_participants = @event.application_letters.size + 1 @event.save [:coach, :pupil].each do | each | @@ -109,7 +121,7 @@ end it "should display accept-all-button for organizers if there are enough free places" do - @event = assign(:event, FactoryGirl.create(:event, :with_diverse_open_applications, :in_selection_phase)) + @event = assign(:event, FactoryGirl.create(:event, :with_diverse_open_applications, :in_selection_phase_with_no_mails_sent)) @event.max_participants = @event.application_letters.size + 1 @event.save sign_in(FactoryGirl.create(:user, role: :organizer)) @@ -118,7 +130,7 @@ end it "should not display accept-all-button if there are not enough free places" do - @event = assign(:event, FactoryGirl.create(:event, :with_diverse_open_applications, :in_selection_phase)) + @event = assign(:event, FactoryGirl.create(:event, :with_diverse_open_applications, :in_selection_phase_with_no_mails_sent)) sign_in(FactoryGirl.create(:user, role: :organizer)) @event.max_participants = 1 render @@ -144,7 +156,7 @@ end end - it "displays a button to view the application if application deadline if over for an event where the pupil has applied" do + it "displays a button to view the application if application deadline is over for an event where the pupil has applied" do pupil = FactoryGirl.create(:user, role: :pupil) application_letter = FactoryGirl.create(:application_letter, user: pupil, event: @event) @event.application_deadline = Date.yesterday @@ -165,7 +177,7 @@ end end end - + it "displays correct buttons in draft phase" do @event = assign(:event, FactoryGirl.create(:event, :in_draft_phase)) sign_in(FactoryGirl.create(:user, role: :organizer)) @@ -201,7 +213,7 @@ end it "displays correct buttons in selection phase" do - @event = assign(:event, FactoryGirl.create(:event, :in_selection_phase)) + @event = assign(:event, FactoryGirl.create(:event, :in_selection_phase_with_no_mails_sent)) sign_in(FactoryGirl.create(:user, role: :organizer)) render expect(rendered).to have_link(t(:print_all, scope: 'events.applicants_overview')) @@ -211,8 +223,22 @@ expect(rendered).to_not have_link(t(:show_participants, scope: 'events.participants')) end + it "does not display send acceptances button after acceptances have been sent in selection phase" do + @event = assign(:event, FactoryGirl.create(:event, :in_selection_phase_with_acceptances_sent)) + sign_in(FactoryGirl.create(:user, role: :organizer)) + render + expect(rendered).to_not have_button(t(:sending_acceptances, scope: 'events.applicants_overview')) + end + + it "does not display send acceptances button after acceptances have been sent in selection phase" do + @event = assign(:event, FactoryGirl.create(:event, :in_selection_phase_with_rejections_sent)) + sign_in(FactoryGirl.create(:user, role: :organizer)) + render + expect(rendered).to_not have_button(t(:sending_rejections, scope: 'events.applicants_overview')) + end + it "displays the disabled send email buttons in selection phase (when there are unclassified applications)" do - @event = assign(:event, FactoryGirl.create(:event, :with_diverse_open_applications, :in_selection_phase)) + @event = assign(:event, FactoryGirl.create(:event, :with_diverse_open_applications, :in_selection_phase_with_no_mails_sent)) sign_in(FactoryGirl.create(:user, role: :organizer)) render expect(rendered).to have_button(t(:sending_acceptances, scope: 'events.applicants_overview'), disabled: true) @@ -220,7 +246,7 @@ end it "displays the disabled send email buttons in selection phase (when there are too many accepted applications)" do - @event = assign(:event, FactoryGirl.create(:event_with_accepted_applications, :in_selection_phase, max_participants: 1)) + @event = assign(:event, FactoryGirl.create(:event_with_accepted_applications, :in_selection_phase_with_no_mails_sent, max_participants: 1)) sign_in(FactoryGirl.create(:user, role: :organizer)) render expect(rendered).to have_button(t(:sending_acceptances, scope: 'events.applicants_overview'), disabled: true) @@ -247,8 +273,8 @@ expect(rendered).to have_link(t('events.participants.show_participants')) end - it "should not display particiants button when email were not already sent as organizer" do - @event = assign(:event, FactoryGirl.create(:event, :in_selection_phase)) + it "should not display particiants button when emails have not been sent as organizer" do + @event = assign(:event, FactoryGirl.create(:event, :in_selection_phase_with_no_mails_sent)) sign_in(FactoryGirl.create(:user, role: :organizer)) render expect(rendered).not_to have_link(t('events.participants.show_participants'))