User-facing volunteership functionality

This commit is contained in:
Petko Bordjukov 2015-09-02 00:07:50 +03:00
parent bcc8678548
commit b9c4670f17
17 changed files with 178 additions and 4 deletions

View File

@ -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

View File

@ -4,4 +4,9 @@ class PropositionMailer < ActionMailer::Base
@proposition = proposition @proposition = proposition
mail(to: proposition.proposable.conference.email, subject: "Ново предложение за #{@proposition.proposable_type}: #{@proposition.proposable_title}") mail(to: proposition.proposable.conference.email, subject: "Ново предложение за #{@proposition.proposable_type}: #{@proposition.proposable_title}")
end end
def proposition_withdrawal_notification(proposition)
@proposition = proposition
mail(to: proposition.proposable.conference.email, subject: "Оттеглено е предложение за #{@proposition.proposable_type}: #{@proposition.proposable_title}")
end
end end

View File

@ -2,7 +2,7 @@ module Proposable
extend ActiveSupport::Concern extend ActiveSupport::Concern
included do included do
has_one :proposition, as: :proposable has_one :proposition, as: :proposable, dependent: :destroy
has_one :proposer, through: :proposition has_one :proposer, through: :proposition
delegate :email, to: :proposer, prefix: true delegate :email, to: :proposer, prefix: true

View File

@ -5,8 +5,13 @@ class Proposition < ActiveRecord::Base
delegate :proposable_title, :proposable_type, :proposable_description, to: :proposable delegate :proposable_title, :proposable_type, :proposable_description, to: :proposable
after_create :send_creation_notification after_create :send_creation_notification
before_destroy :send_withdrawal_notification
def send_creation_notification def send_creation_notification
PropositionMailer.new_proposition_notification(self).deliver_later PropositionMailer.new_proposition_notification(self).deliver_later
end end
def send_withdrawal_notification
PropositionMailer.proposition_withdrawal_notification(self).deliver_later
end
end end

View File

@ -9,6 +9,7 @@ class User < ActiveRecord::Base
has_many :workshops has_many :workshops
has_many :propositions, foreign_key: :proposer_id has_many :propositions, foreign_key: :proposer_id
has_many :events, through: :propositions, source: :proposable, source_type: 'Event' 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 = {}) def find_or_build_personal_profile(conference, params = {})
current_profile = personal_profile(conference) current_profile = personal_profile(conference)

View File

@ -1,5 +1,7 @@
class VolunteerTeam < ActiveRecord::Base class VolunteerTeam < ActiveRecord::Base
belongs_to :conference belongs_to :conference
has_many :volunteerships
has_many :volunteers, through: :volunteerships
validates :name, presence: true validates :name, presence: true
validates :color, presence: true, format: {with: /\A#?[a-f0-9]{6}\z/i} validates :color, presence: true, format: {with: /\A#?[a-f0-9]{6}\z/i}
@ -7,6 +9,10 @@ class VolunteerTeam < ActiveRecord::Base
translates :name, :description translates :name, :description
def include?(volunteer)
volunteers.include? volunteer
end
def color=(hex_triplet) def color=(hex_triplet)
write_attribute :color, hex_triplet.gsub(/\A#/,'') if hex_triplet write_attribute :color, hex_triplet.gsub(/\A#/,'') if hex_triplet
end end

View File

@ -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

View File

@ -0,0 +1,8 @@
Здравейте,
Беше оттеглено следното предложение за <%= @proposition.proposable_type %>:
<% @proposition.proposable_description.each do |key, value| %>
<%= @proposition.proposable.class.human_attribute_name(key) %>: <%= value %>
<% end %>

View File

@ -205,7 +205,7 @@ bg:
forgotten_password: "Забравена парола" forgotten_password: "Забравена парола"
new_password: "Нова парола" new_password: "Нова парола"
send_instructions: "Изпрати инструкции" send_instructions: "Изпрати инструкции"
please_fill_in_your_speaker_profile: "Моля, попълнете данните в лекторския си профил." please_fill_in_your_speaker_profile: "Моля, попълнете данните в личния си профил."
registration: "Регистрация" registration: "Регистрация"
registrations: registrations:
account_cancelation: "Изтриване на акаунт" account_cancelation: "Изтриване на акаунт"
@ -272,7 +272,7 @@ bg:
text: "Задължително поле" text: "Задължително поле"
'yes': "Да" 'yes': "Да"
someone_requested_passreset: "Някой поиска линк за промяна на парола на акаунта Ви. Паролата може да бъде променена от линкът отдолу." someone_requested_passreset: "Някой поиска линк за промяна на парола на акаунта Ви. Паролата може да бъде променена от линкът отдолу."
speaker_profile: екторски профил" speaker_profile: ичен профил"
submit_talk_header: "Предложи нова лекция" submit_talk_header: "Предложи нова лекция"
suggestion_and_speaker_count: "%{suggestions} предложения от %{speakers} лектори" suggestion_and_speaker_count: "%{suggestions} предложения от %{speakers} лектори"
talks: "Лекции" talks: "Лекции"
@ -300,6 +300,12 @@ bg:
info: "Информация за потребител" info: "Информация за потребител"
welcome: welcome:
submit_event: "Предложи %{event_type}" 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}" welcome: "Добре дошли, %{name}"
what_we_ask: "Бихме искали да получим предложенията Ви за лекции и уъркшопи, принадлежащи към следните категории до 30 септември 2015г.:" what_we_ask: "Бихме искали да получим предложенията Ви за лекции и уъркшопи, принадлежащи към следните категории до 30 септември 2015г.:"
workshop_was_successfully_confirmed: "Уъркшопът беше потвърден успешно" workshop_was_successfully_confirmed: "Уъркшопът беше потвърден успешно"

View File

@ -293,6 +293,11 @@ en:
info: User details info: User details
welcome: welcome:
submit_event: Submit %{event_type} 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} 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 30.09.2015:'
workshop_was_successfully_confirmed: The workshop was successfully confirmed workshop_was_successfully_confirmed: The workshop was successfully confirmed

View File

@ -5,6 +5,10 @@ Rails.application.routes.draw do
root to: 'home#index' root to: 'home#index'
resource :personal_profile, path: 'profile' resource :personal_profile, path: 'profile'
resources :events resources :events
resources :volunteerships, only: [:index, :destroy]
resources :volunteer_teams, only: [] do
resource :volunteership, only: :create
end
end end
namespace :management do namespace :management do

View File

@ -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

View File

@ -140,3 +140,25 @@
display: inline-block; display: inline-block;
margin: 20px; margin: 20px;
} }
.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;
}

View File

@ -1,10 +1,15 @@
@import "font-awesome-sprockets"; @import "font-awesome-sprockets";
@import "font-awesome"; @import "font-awesome";
@import 'bootstrap/variables';
@import 'bootstrap/mixins';
@import 'bootstrap/grid';
@import 'initfest/styles'; @import 'initfest/styles';
@import 'initfest/forms'; @import 'initfest/forms';
@import 'initfest/flash_messages'; @import 'initfest/flash_messages';
nav { background-image: image-url('initfest/navbg.jpg'); } nav { background-image: image-url('initfest/navbg.jpg'); }
html { html {

View File

@ -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']

View File

@ -0,0 +1,7 @@
FactoryGirl.define do
factory :volunteership do
volunteer_team nil
volunteer nil
end
end

View File

@ -0,0 +1,5 @@
require 'rails_helper'
RSpec.describe Volunteership, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end