Skip to content

Commit

Permalink
Merge branch 'dev' of github.com:hpi-swt2/workshop-portal into 155_fi…
Browse files Browse the repository at this point in the history
…x_event_range_datepicker
  • Loading branch information
tom95 committed Dec 10, 2016
2 parents 6b29e82 + 80f71c5 commit c40bb0f
Show file tree
Hide file tree
Showing 26 changed files with 312 additions and 13 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,6 @@ config/database.yml
/nbproject/private/
/.DS_Store
.vagrant

# Ignore application configuration
/config/application.yml
3 changes: 3 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ gem 'rubocop', '~> 0.29.1'
# coveralls.io
gem 'coveralls', require: false

# Simple, Heroku-friendly Rails app configuration using ENV and a single YAML file
gem 'figaro'

group :development, :test do
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
gem 'byebug'
Expand Down
6 changes: 6 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ GEM
factory_girl_rails (4.7.0)
factory_girl (~> 4.7.0)
railties (>= 3.0.0)
figaro (1.1.1)
thor (~> 0.14)
globalid (0.3.7)
activesupport (>= 4.1.0)
has_scope (0.7.0)
Expand Down Expand Up @@ -282,6 +284,7 @@ DEPENDENCIES
devise-bootstrap-views
devise_openid_authenticatable
factory_girl_rails
figaro
has_scope
jquery-rails
jquery-turbolinks
Expand All @@ -303,5 +306,8 @@ DEPENDENCIES
twitter-bootstrap-rails
web-console (~> 2.0)

RUBY VERSION
ruby 2.2.2p95

BUNDLED WITH
1.13.6
41 changes: 41 additions & 0 deletions app/assets/javascripts/events.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,47 @@
// Place all the behaviors and hooks related to the matching controller here.
// All this logic will automatically be available in application.js.

jQuery(function() {

$('#send-emails-modal').on('show.bs.modal', function (event) {
var button = $(event.relatedTarget);
var header = button.data('title');
var list = button.data('list');
var modal = $(this);
modal.find('.modal-title').text(header);
modal.find('#send-emails-mailto').attr('href', 'mailto:' + list);
modal.find('#send-emails-list').val(list);
});

$('#send-emails-clipboard').click(function () {
var $temp = $("<input>");
$('body').append($temp);
$temp.val($('#send-emails-list').val()).select();
try {
var successful = document.execCommand('copy');
var msg = successful ? 'successful' : 'unsuccessful';
console.log('Copying emails to the clipboard was ' + msg);
}
catch (err) {
console.log('Unable to copy emails to the clipboard');
}
$temp.remove();
});
});

$(document).on('turbolinks:load', function() {
$('#event-add-date-picker').bind('click', function() {
// insert our template to the ui and add a remove button
$(EVENT_DATE_PICKER_TEMPLATE)
.insertBefore(this)
.append(' <a style="float: none" class="close">&times;</a>')
.find('.close')
.click(function() {
$(this).parent('div').remove();
});
});
});

function addEventDatePicker() {
var picker = $('#event-add-date-picker');

Expand Down
7 changes: 7 additions & 0 deletions app/assets/stylesheets/events.css
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,10 @@
#applicants_overview {
margin-bottom: 20px;
}

.tooltip-wrapper {
display: inline-block;
}
.tooltip .btn[disabled] {
pointer-events: none;
}
2 changes: 2 additions & 0 deletions app/helpers/application_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ def dropdown_items
# everyone gets their profile, if it exists
if current_user.profile.present?
o << (menu_item t(:profile, scope: 'navbar'), profile_path(current_user.profile))
else
o << (menu_item t(:create_profile, scope: 'navbar'), new_profile_path)
end
# pupils get their applications
if current_user.role == "pupil"
Expand Down
4 changes: 4 additions & 0 deletions app/mailers/application_mailer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
class ApplicationMailer < ActionMailer::Base
default from: "workshop.portal@gmail.com"
layout 'mailer'
end
17 changes: 17 additions & 0 deletions app/mailers/portal_mailer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
class PortalMailer < ApplicationMailer

# @param hide_recipients [Boolean] - identify whether recipients should be hidden from each other (true) or not (false)
# @param recipients [Array<String>] - email addresses of recipients
# @param reply_to [Array<String>] - email addresses of recipient of the answer
# @param subject [String] - subject of the mail
# @param content [String] - content of the mail
# @return [ActionMailer::MessageDelivery] a mail object with the given parameters.
def generic_email(hide_recipients, recipients, reply_to, subject, content)
@content = content
if (hide_recipients)
mail(bcc: recipients, reply_to: reply_to, subject: subject)
else
mail(to: recipients, reply_to: reply_to, subject: subject)
end
end
end
2 changes: 2 additions & 0 deletions app/models/application_letter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ class ApplicationLetter < ActiveRecord::Base
enum status: {accepted: 1, rejected: 0, pending: 2}

# Checks if the deadline is over
# additionally only return if event and event.application_deadline is present
# TODO: 'event.application_deadline' should never be nil, when #18 is finished. Please remove this in #18.
#
# @param none
# @return [Boolean] true if deadline is over
Expand Down
26 changes: 26 additions & 0 deletions app/models/event.rb
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,32 @@ def agreement_letter_for(user)

enum kind: [ :workshop, :camp ]

# Returns whether all application_letters are classified or not
#
# @param none
# @return [Boolean] if status of all application_letters is not pending
def applications_classified?
application_letters.all? { |application_letter| application_letter.status != 'pending' }
end

# Returns a string of all email addresses of rejected applications
#
# @param none
# @return [String] Concatenation of all email addresses of rejected applications, seperated by ','
def email_adresses_of_rejected_applicants
rejected_applications = application_letters.where(status: ApplicationLetter.statuses[:rejected])
rejected_applications.map{ |applications_letter| applications_letter.user.email }.join(',')
end

# Returns a string of all email addresses of accepted applications
#
# @param none
# @return [String] Concatenation of all email addresses of accepted applications, seperated by ','
def email_adresses_of_accepted_applicants
accepted_applications = application_letters.where(status: ApplicationLetter.statuses[:accepted])
accepted_applications.map{ |application_letter| application_letter.user.email }.join(',')
end

# Returns the number of free places of the event, this value may be negative
#
# @param none
Expand Down
53 changes: 44 additions & 9 deletions app/views/events/_applicants_overview.html.erb
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
<div class="container-fluid" id="applicants_overview">

<h3><%= t('.title', title: @event.name) %></h3>
<h3><%= t '.title', title: @event.name %></h3>
<div id="free_places"><%= t '.free_places', count: @free_places %></div>
<div id="occupied_places"><%= t '.occupied_places', count: @occupied_places %></div>

Expand Down Expand Up @@ -41,18 +40,54 @@
<div class="container-fluid no-padding">
<div class="btn-group" role="group">
<%= link_to "Alle annehmen",
events_path, :class => 'btn btn-default'%>
events_path, :class => 'btn btn-default'%>
<%= link_to "Alle drucken",
events_path, :class => 'btn btn-default'%>
events_path, :class => 'btn btn-default'%>
</div>
<div class="btn-group pull-right" role="group">
<%= link_to "Zusagen verschicken",
events_path, :class => 'btn btn-default'%>
<%= link_to "Absagen verschicken",
events_path, :class => 'btn btn-default'%>
<% if (!@event.applications_classified?) %>
<div class="tooltip-wrapper disabled has-tooltip" data-toggle="tooltip" title="<%= t '.unclassified_applications_left' %>">
<%= button_tag t('.sending_acceptances'), type: 'button', class: 'send-emails-button btn btn-default', disabled: true %>
</div>
<div class="tooltip-wrapper disabled has-tooltip" data-toggle="tooltip" title="<%= t '.unclassified_applications_left' %>">
<%= button_tag t('.sending_rejections'), type: 'button', class: 'send-emails-button btn btn-default', disabled: true %>
</div>
<% elsif (@event.compute_free_places < 0)%>
<div class="tooltip-wrapper disabled has-tooltip" data-toggle="tooltip" title="<%= t '.maximum_number_of_participants_exeeded' %>">
<%= button_tag t('.sending_acceptances'), type: 'button', class: 'send-emails-button btn btn-default', disabled: true %>
</div>
<div class="tooltip-wrapper disabled has-tooltip" data-toggle="tooltip" title="<%= t '.maximum_number_of_participants_exeeded' %>">
<%= button_tag t('.sending_rejections'), type: 'button', class: 'send-emails-button btn btn-default', disabled: true %>
</div>
<% else %>
<%= button_tag t('.sending_acceptances'), type: 'button', class: 'btn btn-default', data: {toggle: 'modal', target: '#send-emails-modal', title: t('.sending_acceptances'), list: @event.email_adresses_of_accepted_applicants} %>
<%= button_tag t('.sending_rejections'), type: 'button', class: 'btn btn-default', data: {toggle: 'modal', target: '#send-emails-modal', title: t('.sending_rejections'), list: @event.email_adresses_of_rejected_applicants} %>
<% end %>
</div>
</div>

</div>

<!-- Bootstrap Modal for sending emails -->
<div id="send-emails-modal" class="modal fade" role="dialog">
<div class="modal-dialog">

<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button>
<h4 class="modal-title"></h4>
</div>
<div class="modal-body">
<%= link_to "Senden", '#', :id => 'send-emails-mailto', :class => 'btn btn-default' %>
<%= button_tag "In die Zwischenablage kopieren", type: 'button', id: 'send-emails-clipboard', class: 'btn btn-default' %>
<%= text_field_tag "send-emails-list", '', :type => 'hidden' %>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>

</div>
</div>
5 changes: 5 additions & 0 deletions app/views/layouts/mailer.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<html>
<body>
<%= yield %>
</body>
</html>
1 change: 1 addition & 0 deletions app/views/layouts/mailer.text.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<%= yield %>
1 change: 1 addition & 0 deletions app/views/portal_mailer/generic_email.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<p> <%= @content %> </p>
1 change: 1 addition & 0 deletions app/views/portal_mailer/generic_email.text.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<%= @content %>
12 changes: 12 additions & 0 deletions config/environments/development.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,16 @@

# Raises error for missing translations
# config.action_view.raise_on_missing_translations = true

config.action_mailer.delivery_method = :smtp
# SMTP settings for gmail
config.action_mailer.smtp_settings = {
:address => "smtp.gmail.com",
:port => 587,
:user_name => ENV['gmail_username'],
:password => ENV['gmail_password'],
:authentication => "plain",
:enable_starttls_auto => true
}

end
12 changes: 12 additions & 0 deletions config/environments/production.rb
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,16 @@

# Do not dump schema after migrations.
config.active_record.dump_schema_after_migration = false

config.action_mailer.delivery_method = :smtp
# SMTP settings for gmail
config.action_mailer.smtp_settings = {
:address => "smtp.gmail.com",
:port => 587,
:user_name => ENV['gmail_username'],
:password => ENV['gmail_password'],
:authentication => "plain",
:enable_starttls_auto => true
}

end
4 changes: 4 additions & 0 deletions config/locales/de.events.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ de:
occupied_places:
one: '%{count} Platz belegt'
other: '%{count} Plätze belegt'
unclassified_applications_left: 'Bewerbung(en) wurden noch nicht klassifiziert'
maximum_number_of_participants_exeeded: 'Maximale Teilnehmeranzahl wurde überschritten'
sending_acceptances: 'Zusagen verschicken'
sending_rejections: 'Absagen verschicken'
participants:
participants: "Teilnehmer"
show_participants: "Teilnehmerliste"
Expand Down
1 change: 1 addition & 0 deletions config/locales/de.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ de:
user_management: "Benutzerverwaltung"
requests: "Anfragen"
profile: "Mein Profil"
create_profile: "Mein Profil anlegen"
settings: "Profilinfo"
login: "Einloggen"
logout: "Ausloggen"
Expand Down
4 changes: 2 additions & 2 deletions db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
ActiveRecord::Schema.define(version: 20161204205355) do

create_table "agreement_letters", force: :cascade do |t|
t.integer "user_id"
t.integer "event_id"
t.integer "user_id", null: false
t.integer "event_id", null: false
t.string "path", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
Expand Down
1 change: 1 addition & 0 deletions db/seeds.rb
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@
vegan: false,
allergic: false,
allergies: "",
status: ApplicationLetter.statuses[:pending],
user: applicant,
event: event
)
Expand Down
37 changes: 37 additions & 0 deletions spec/features/events_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,43 @@
expect(page).to have_css("div#occupied_places")
end

scenario "logged in as Organizer I want to be unable to send emails if there is any unclassified application left" do
login(:organizer)
@event.update!(max_participants: 1)
@pupil = FactoryGirl.create(:profile)
@pupil.user.role = :pupil
@pending_application = FactoryGirl.create(:application_letter, :event => @event, :user => @pupil.user)
visit event_path(@event)
expect(page).to have_button(I18n.t('events.applicants_overview.sending_acceptances'), disabled: true)
expect(page).to have_button(I18n.t('events.applicants_overview.sending_rejections'), disabled: true)
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
login(:organizer)
@event.update!(max_participants: 1)
2.times do |n|
@pupil = FactoryGirl.create(:profile)
@pupil.user.role = :pupil
FactoryGirl.create(:application_letter_accepted, :event => @event, :user => @pupil.user)
end
visit event_path(@event)
expect(page).to have_button(I18n.t('events.applicants_overview.sending_acceptances'), disabled: true)
expect(page).to have_button(I18n.t('events.applicants_overview.sending_rejections'), disabled: true)
end

scenario "logged in as Organizer I want to open a modal by clicking on sending emails" do
login(:organizer)
@event.update!(max_participants: 2)
2.times do |n|
@pupil = FactoryGirl.create(:profile)
@pupil.user.role = :pupil
FactoryGirl.create(:application_letter_accepted, :event => @event, :user => @pupil.user)
end
visit event_path(@event)
click_button I18n.t('events.applicants_overview.sending_acceptances')
expect(page).to have_selector('div', :id => 'send-emails-modal')
end

scenario "logged in as Organizer I can see the correct count of free/occupied places" do
login(:organizer)
@event.update!(max_participants: 1)
Expand Down

0 comments on commit c40bb0f

Please sign in to comment.