From b9c4670f17afe3a6cc4b2832795b22674f77f8c7 Mon Sep 17 00:00:00 2001 From: Petko Bordjukov Date: Wed, 2 Sep 2015 00:07:50 +0300 Subject: [PATCH] User-facing volunteership functionality --- .../public/volunteerships_controller.rb | 51 +++++++++++++++++++ app/mailers/proposition_mailer.rb | 5 ++ app/models/concerns/proposable.rb | 2 +- app/models/proposition.rb | 5 ++ app/models/user.rb | 1 + app/models/volunteer_team.rb | 6 +++ app/models/volunteership.rb | 18 +++++++ ...oposition_withdrawal_notification.text.erb | 8 +++ config/locales/bg.yml | 10 +++- config/locales/en.yml | 5 ++ config/routes.rb | 4 ++ .../20150901091814_create_volunteerships.rb | 12 +++++ .../assets/stylesheets/initfest/_forms.scss | 24 ++++++++- .../stylesheets/initfest/application.scss | 5 ++ .../views/public/volunteerships/index.slim | 14 +++++ spec/factories/volunteerships.rb | 7 +++ spec/models/volunteership_spec.rb | 5 ++ 17 files changed, 178 insertions(+), 4 deletions(-) create mode 100644 app/controllers/public/volunteerships_controller.rb create mode 100644 app/models/volunteership.rb create mode 100644 app/views/proposition_mailer/proposition_withdrawal_notification.text.erb create mode 100644 db/migrate/20150901091814_create_volunteerships.rb create mode 100644 lib/initfest/views/public/volunteerships/index.slim create mode 100644 spec/factories/volunteerships.rb create mode 100644 spec/models/volunteership_spec.rb diff --git a/app/controllers/public/volunteerships_controller.rb b/app/controllers/public/volunteerships_controller.rb new file mode 100644 index 0000000..a8a62aa --- /dev/null +++ b/app/controllers/public/volunteerships_controller.rb @@ -0,0 +1,51 @@ +module Public + class VolunteershipsController < Public::ApplicationController + before_filter :authenticate_user! + + 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..2bc23a4 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,6 +300,12 @@ 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г.:" workshop_was_successfully_confirmed: "Уъркшопът беше потвърден успешно" diff --git a/config/locales/en.yml b/config/locales/en.yml index 7580dc3..67cc193 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -293,6 +293,11 @@ 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:' workshop_was_successfully_confirmed: The workshop was successfully confirmed 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..ef387a3 100644 --- a/lib/initfest/assets/stylesheets/initfest/application.scss +++ b/lib/initfest/assets/stylesheets/initfest/application.scss @@ -1,10 +1,15 @@ @import "font-awesome-sprockets"; @import "font-awesome"; +@import 'bootstrap/variables'; +@import 'bootstrap/mixins'; +@import 'bootstrap/grid'; + @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/index.slim b/lib/initfest/views/public/volunteerships/index.slim new file mode 100644 index 0000000..2db5855 --- /dev/null +++ b/lib/initfest/views/public/volunteerships/index.slim @@ -0,0 +1,14 @@ +- 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 + - @volunteer_teams.each do |vt| + .col-lg-3 + h2 = vt.name + p + = vt.description + - if vt.include? current_user + = button_to t('views.volunteerships.withdraw_application'), volunteership_path(vt.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(vt), class: ['btn-link'] 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