diff --git a/Gemfile.lock b/Gemfile.lock index 84c4926..4e35970 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -50,7 +50,7 @@ GEM thread_safe (~> 0.3, >= 0.3.4) tzinfo (~> 1.1) arel (6.0.3) - autoprefixer-rails (5.2.1.3) + autoprefixer-rails (6.0.2) execjs json awesome_print (1.6.1) @@ -148,7 +148,7 @@ GEM guard (~> 2.1) guard-compat (~> 1.1) rspec (>= 2.99.0, < 4.0) - highline (1.7.3) + highline (1.7.5) hirb (0.7.3) i18n (0.7.0) i18n-tasks (0.8.7) @@ -164,7 +164,7 @@ GEM jquery-rails railties (>= 3.1) sass-rails - jquery-rails (4.0.4) + jquery-rails (4.0.5) rails-dom-testing (~> 1.0) railties (>= 4.2.0) thor (>= 0.14, < 2.0) @@ -179,7 +179,7 @@ GEM mail (2.6.3) mime-types (>= 1.16, < 3) method_source (0.8.2) - mime-types (2.6.1) + mime-types (2.6.2) mini_portile (0.6.2) minitest (5.8.0) morrisjs-rails (0.5.1) @@ -191,12 +191,12 @@ GEM net-ssh (2.9.2) nokogiri (1.6.6.2) mini_portile (~> 0.6.0) - notiffany (0.0.7) + notiffany (0.0.8) nenv (~> 0.1) shellany (~> 0.0) orm_adapter (0.5.0) - pg (0.18.2) - phony (2.14.14) + pg (0.18.3) + phony (2.15.1) phony_rails (0.12.10) activesupport (>= 3.0) phony (~> 2.12) @@ -236,7 +236,7 @@ GEM ruby-graphviz (~> 1.2) rails-html-sanitizer (1.0.2) loofah (~> 2.0) - rails-i18n (4.0.4) + rails-i18n (4.0.5) i18n (~> 0.6) railties (~> 4.0) railties (4.2.4) @@ -246,7 +246,7 @@ GEM thor (>= 0.18.1, < 2.0) rake (10.4.2) raphael-rails (2.1.2) - rb-fsevent (0.9.5) + rb-fsevent (0.9.6) rb-inotify (0.9.5) ffi (>= 0.5.0) ref (2.0.0) @@ -275,12 +275,12 @@ GEM rspec-support (3.3.0) ruby-graphviz (1.2.2) sass (3.4.18) - sass-rails (5.0.3) + sass-rails (5.0.4) railties (>= 4.0.0, < 5.0) sass (~> 3.1) sprockets (>= 2.8, < 4.0) sprockets-rails (>= 2.0, < 4.0) - tilt (~> 1.1) + tilt (>= 1.1, < 3) shellany (0.0.1) simple_form (3.1.1) actionpack (~> 4.0) @@ -300,12 +300,12 @@ GEM railties (>= 3.1, < 5.0) slim (~> 3.0) slop (3.6.0) - spring (1.3.6) + spring (1.4.0) spring-commands-rspec (1.0.4) spring (>= 0.9.1) - sprockets (3.3.3) + sprockets (3.3.4) rack (~> 1.0) - sprockets-rails (2.3.2) + sprockets-rails (2.3.3) actionpack (>= 3.0) activesupport (>= 3.0) sprockets (>= 2.8, < 4.0) @@ -324,7 +324,7 @@ GEM thor (0.19.1) thread (0.2.2) thread_safe (0.3.5) - tilt (1.4.1) + tilt (2.0.1) tins (1.6.0) tzinfo (1.2.2) thread_safe (~> 0.1) @@ -389,4 +389,4 @@ DEPENDENCIES yaml_db! BUNDLED WITH - 1.10.5 + 1.10.6 diff --git a/app/controllers/public/volunteerships_controller.rb b/app/controllers/public/volunteerships_controller.rb new file mode 100644 index 0000000..efe28c3 --- /dev/null +++ b/app/controllers/public/volunteerships_controller.rb @@ -0,0 +1,51 @@ +module Public + class VolunteershipsController < Public::ApplicationController + before_filter :authenticate_user!, only: [:create, :destroy] + + def index + @volunteer_teams = current_conference.volunteer_teams + end + + def create + @volunteer_team = current_conference.volunteer_teams.find params[:volunteer_team_id] + @volunteership = @volunteer_team.volunteerships.build volunteer: current_user + @volunteership.build_proposition proposer: current_user, status: :undecided + + if @volunteership.save + flash[:notice] = I18n.t('views.volunteerships.you_successfully_applied_for', team: @volunteership.volunteer_team.name) + else + flash[:error] = I18n.t('views.volunteerships.an error_occurred_while_applying') + end + + after_save_redirect + end + + def destroy + @volunteership = current_user.volunteerships.find params[:id] + + if @volunteership.destroy + flash[:notice] = I18n.t('views.volunteerships.you_successfully_retracted_your_application_for', team: @volunteership.volunteer_team.name) + end + + redirect_to volunteerships_path + end + + private + + def volunteership_params + params.require(:volunteership).permit( + :title, :subtitle, :track_id, :length, :language, + :abstract, :description, :notes, :agreement, + :volunteership_type_id + ) + end + + def after_save_redirect + if current_user.personal_profile(current_conference).present? + redirect_to volunteerships_path + else + redirect_to edit_personal_profile_path, alert: I18n.t(:please_fill_in_your_speaker_profile) + end + end + end +end diff --git a/app/mailers/proposition_mailer.rb b/app/mailers/proposition_mailer.rb index bd043b7..07829f3 100644 --- a/app/mailers/proposition_mailer.rb +++ b/app/mailers/proposition_mailer.rb @@ -4,4 +4,9 @@ class PropositionMailer < ActionMailer::Base @proposition = proposition mail(to: proposition.proposable.conference.email, subject: "Ново предложение за #{@proposition.proposable_type}: #{@proposition.proposable_title}") end + + def proposition_withdrawal_notification(proposition) + @proposition = proposition + mail(to: proposition.proposable.conference.email, subject: "Оттеглено е предложение за #{@proposition.proposable_type}: #{@proposition.proposable_title}") + end end diff --git a/app/models/concerns/proposable.rb b/app/models/concerns/proposable.rb index 6da37b1..190a1d8 100644 --- a/app/models/concerns/proposable.rb +++ b/app/models/concerns/proposable.rb @@ -2,7 +2,7 @@ module Proposable extend ActiveSupport::Concern included do - has_one :proposition, as: :proposable + has_one :proposition, as: :proposable, dependent: :destroy has_one :proposer, through: :proposition delegate :email, to: :proposer, prefix: true diff --git a/app/models/proposition.rb b/app/models/proposition.rb index 95a9910..97b54be 100644 --- a/app/models/proposition.rb +++ b/app/models/proposition.rb @@ -5,8 +5,13 @@ class Proposition < ActiveRecord::Base delegate :proposable_title, :proposable_type, :proposable_description, to: :proposable after_create :send_creation_notification + before_destroy :send_withdrawal_notification def send_creation_notification PropositionMailer.new_proposition_notification(self).deliver_later end + + def send_withdrawal_notification + PropositionMailer.proposition_withdrawal_notification(self).deliver_later + end end diff --git a/app/models/user.rb b/app/models/user.rb index 3b6fdca..f414e79 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -9,6 +9,7 @@ class User < ActiveRecord::Base has_many :workshops has_many :propositions, foreign_key: :proposer_id has_many :events, through: :propositions, source: :proposable, source_type: 'Event' + has_many :volunteerships, foreign_key: :volunteer_id def find_or_build_personal_profile(conference, params = {}) current_profile = personal_profile(conference) diff --git a/app/models/volunteer_team.rb b/app/models/volunteer_team.rb index 183685c..46f3dad 100644 --- a/app/models/volunteer_team.rb +++ b/app/models/volunteer_team.rb @@ -1,5 +1,7 @@ class VolunteerTeam < ActiveRecord::Base belongs_to :conference + has_many :volunteerships + has_many :volunteers, through: :volunteerships validates :name, presence: true validates :color, presence: true, format: {with: /\A#?[a-f0-9]{6}\z/i} @@ -7,6 +9,10 @@ class VolunteerTeam < ActiveRecord::Base translates :name, :description + def include?(volunteer) + volunteers.include? volunteer + end + def color=(hex_triplet) write_attribute :color, hex_triplet.gsub(/\A#/,'') if hex_triplet end diff --git a/app/models/volunteership.rb b/app/models/volunteership.rb new file mode 100644 index 0000000..ce03c1a --- /dev/null +++ b/app/models/volunteership.rb @@ -0,0 +1,18 @@ +class Volunteership < ActiveRecord::Base + include Proposable + + belongs_to :volunteer_team + belongs_to :volunteer, class_name: 'User' + has_one :conference, through: :volunteer_team + + def proposable_title + volunteer.email + end + + def proposable_description + { + volunteer_email: volunteer.email, + volunteer_team: volunteer_team.name, + } + end +end diff --git a/app/views/proposition_mailer/proposition_withdrawal_notification.text.erb b/app/views/proposition_mailer/proposition_withdrawal_notification.text.erb new file mode 100644 index 0000000..7e1e059 --- /dev/null +++ b/app/views/proposition_mailer/proposition_withdrawal_notification.text.erb @@ -0,0 +1,8 @@ +Здравейте, + +Беше оттеглено следното предложение за <%= @proposition.proposable_type %>: + +<% @proposition.proposable_description.each do |key, value| %> +<%= @proposition.proposable.class.human_attribute_name(key) %>: <%= value %> + +<% end %> diff --git a/config/locales/bg.yml b/config/locales/bg.yml index b6b5f49..e00be93 100644 --- a/config/locales/bg.yml +++ b/config/locales/bg.yml @@ -205,7 +205,7 @@ bg: forgotten_password: "Забравена парола" new_password: "Нова парола" send_instructions: "Изпрати инструкции" - please_fill_in_your_speaker_profile: "Моля, попълнете данните в лекторския си профил." + please_fill_in_your_speaker_profile: "Моля, попълнете данните в личния си профил." registration: "Регистрация" registrations: account_cancelation: "Изтриване на акаунт" @@ -272,7 +272,7 @@ bg: text: "Задължително поле" 'yes': "Да" someone_requested_passreset: "Някой поиска линк за промяна на парола на акаунта Ви. Паролата може да бъде променена от линкът отдолу." - speaker_profile: "Лекторски профил" + speaker_profile: "Личен профил" submit_talk_header: "Предложи нова лекция" suggestion_and_speaker_count: "%{suggestions} предложения от %{speakers} лектори" talks: "Лекции" @@ -300,7 +300,13 @@ bg: info: "Информация за потребител" welcome: submit_event: "Предложи %{event_type}" + volunteerships: + apply: Кандидатствай + withdraw_application: Оттегли кандидатурата си + you_successfully_applied_for: "Успешно изпратихте кандидатура за екип „%{team}“" + error_occurred_while_applying: "Възникна грешка и кандидатурата Ви не беше изпратена" + you_successfully_retracted_your_application_for: "Успешно оттеглихте кандидатурата си за екип „%{team}“" welcome: "Добре дошли, %{name}" - what_we_ask: "Бихме искали да получим предложенията Ви за лекции и уъркшопи, принадлежащи към следните категории до 30 септември 2015г.:" + what_we_ask: "Бихме искали да получим предложенията Ви за лекции и уъркшопи, принадлежащи към следните категории до 4 октомври 2015г.:" workshop_was_successfully_confirmed: "Уъркшопът беше потвърден успешно" workshops: "Уъркшопи" diff --git a/config/locales/en.yml b/config/locales/en.yml index 7580dc3..8be9ba8 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -293,7 +293,12 @@ en: info: User details welcome: submit_event: Submit %{event_type} + volunteerships: + apply: Apply + withdraw_application: Withraw your application + you_successfully_applied_for: "You successfully applied for the %{team} team" + error_occurred_while_applying: "There was an error and your application could not be sent" welcome: Welcome, %{name} - what_we_ask: 'We would like to receive your lecture and workshop submissions that belong to the following tracks until 30.09.2015:' + what_we_ask: 'We would like to receive your lecture and workshop submissions that belong to the following tracks until 04.10.2015:' workshop_was_successfully_confirmed: The workshop was successfully confirmed workshops: Workshops diff --git a/config/routes.rb b/config/routes.rb index a1641a6..02ca330 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -5,6 +5,10 @@ Rails.application.routes.draw do root to: 'home#index' resource :personal_profile, path: 'profile' resources :events + resources :volunteerships, only: [:index, :destroy] + resources :volunteer_teams, only: [] do + resource :volunteership, only: :create + end end namespace :management do diff --git a/db/migrate/20150901091814_create_volunteerships.rb b/db/migrate/20150901091814_create_volunteerships.rb new file mode 100644 index 0000000..250ad70 --- /dev/null +++ b/db/migrate/20150901091814_create_volunteerships.rb @@ -0,0 +1,12 @@ +class CreateVolunteerships < ActiveRecord::Migration + def change + create_table :volunteerships do |t| + t.references :volunteer_team, index: true, foreign_key: true + t.references :volunteer, index: true + + t.timestamps null: false + end + + add_foreign_key :volunteerships, :users, column: :volunteer_id + end +end diff --git a/lib/initfest/assets/stylesheets/initfest/_forms.scss b/lib/initfest/assets/stylesheets/initfest/_forms.scss index 1cdbc56..9b1be94 100644 --- a/lib/initfest/assets/stylesheets/initfest/_forms.scss +++ b/lib/initfest/assets/stylesheets/initfest/_forms.scss @@ -139,4 +139,26 @@ .blocky { display: inline-block; margin: 20px; -} \ No newline at end of file +} + +.volunteer_teams { + @media (min-width: $screen-lg-min) { + + .btn-link { + display: block; + } + } +} + +.btn-link-red { + background: #833e23; + border-bottom: 0.2em solid #DC957A; +} + +.btn-link-red:hover { + background: #512515; +} + +.btn-link-red:active { + background: #D27A59; +} diff --git a/lib/initfest/assets/stylesheets/initfest/application.scss b/lib/initfest/assets/stylesheets/initfest/application.scss index df8c8dc..41d685a 100644 --- a/lib/initfest/assets/stylesheets/initfest/application.scss +++ b/lib/initfest/assets/stylesheets/initfest/application.scss @@ -1,10 +1,16 @@ @import "font-awesome-sprockets"; @import "font-awesome"; +@import 'bootstrap/variables'; +@import 'bootstrap/mixins'; +@import 'bootstrap/grid'; +@import 'bootstrap/utilities'; + @import 'initfest/styles'; @import 'initfest/forms'; @import 'initfest/flash_messages'; + nav { background-image: image-url('initfest/navbg.jpg'); } html { diff --git a/lib/initfest/views/public/volunteerships/_volunteer_team.slim b/lib/initfest/views/public/volunteerships/_volunteer_team.slim new file mode 100644 index 0000000..4767ca5 --- /dev/null +++ b/lib/initfest/views/public/volunteerships/_volunteer_team.slim @@ -0,0 +1,10 @@ +- if volunteer_team_counter % 3 == 0 + .clearfix.visible-lg-block +.col-lg-3 + h2 = volunteer_team.name + .description + = simple_format volunteer_team.description + - if signed_in? and volunteer_team.include? current_user + = button_to t('views.volunteerships.withdraw_application'), volunteership_path(volunteer_team.volunteerships.where(volunteer: current_user).first), class: ['btn-link', 'btn-link-red'], method: :delete + - else + = button_to t('views.volunteerships.apply'), volunteer_team_volunteership_path(volunteer_team), class: ['btn-link'] diff --git a/lib/initfest/views/public/volunteerships/index.slim b/lib/initfest/views/public/volunteerships/index.slim new file mode 100644 index 0000000..957d8c2 --- /dev/null +++ b/lib/initfest/views/public/volunteerships/index.slim @@ -0,0 +1,6 @@ +- content_for(:title) { VolunteerTeam.model_name.human(count: 2).mb_chars.capitalize.to_s } + +h1 = VolunteerTeam.model_name.human(count: 2).mb_chars.capitalize + +.container.volunteer_teams + = render partial: 'volunteer_team', collection: @volunteer_teams diff --git a/spec/factories/volunteerships.rb b/spec/factories/volunteerships.rb new file mode 100644 index 0000000..7ef6f12 --- /dev/null +++ b/spec/factories/volunteerships.rb @@ -0,0 +1,7 @@ +FactoryGirl.define do + factory :volunteership do + volunteer_team nil +volunteer nil + end + +end diff --git a/spec/models/volunteership_spec.rb b/spec/models/volunteership_spec.rb new file mode 100644 index 0000000..e8bb454 --- /dev/null +++ b/spec/models/volunteership_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe Volunteership, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end