From 1c04e820b839b17fe0b0ffc7d56dc2892ef94ed3 Mon Sep 17 00:00:00 2001 From: Rahul Date: Sat, 10 Aug 2019 14:35:07 +0530 Subject: [PATCH] add invites actions in controller and views Index is added so organizer can see who they have invited. Oganizers will now be able to invite users with their email.Organizer will be able to delete and edit a invite.Add test for actions. --- app/assets/javascripts/osem-datepickers.js | 4 +- app/controllers/admin/invites_controller.rb | 61 ++++++- app/views/admin/booths/index.html.haml | 1 + app/views/admin/invites/edit.html.haml | 11 ++ app/views/admin/invites/index.html.haml | 42 +++++ app/views/admin/invites/new.html.haml | 1 + app/views/admin/tracks/index.html.haml | 1 + .../admin/invites_controller_spec.rb | 152 ++++++++++++++++++ spec/factories/invites.rb | 9 ++ 9 files changed, 279 insertions(+), 3 deletions(-) create mode 100644 app/views/admin/invites/edit.html.haml create mode 100644 app/views/admin/invites/index.html.haml create mode 100644 spec/controllers/admin/invites_controller_spec.rb create mode 100644 spec/factories/invites.rb diff --git a/app/assets/javascripts/osem-datepickers.js b/app/assets/javascripts/osem-datepickers.js index 22604449..4f92dfaa 100644 --- a/app/assets/javascripts/osem-datepickers.js +++ b/app/assets/javascripts/osem-datepickers.js @@ -36,8 +36,8 @@ $(function () { format: 'YYYY-MM-DD', maxDate : $("#invitation-end-date").attr('end_date'), minDate : today - }); - + }).keypress(function(event) {event.preventDefault();}); + $("#registration-arrival-datepicker").on("dp.change",function (e) { // departure_date > start_date,arrival_date if ((new Date(e.date).getTime()) > (new Date($("#registration-arrival-datepicker").attr('start_date')).getTime())){ diff --git a/app/controllers/admin/invites_controller.rb b/app/controllers/admin/invites_controller.rb index 02bb4706..d0172da3 100644 --- a/app/controllers/admin/invites_controller.rb +++ b/app/controllers/admin/invites_controller.rb @@ -2,10 +2,69 @@ module Admin class InvitesController < Admin::BaseController load_and_authorize_resource :conference, find_by: :short_title + def index + @invites = Invite.where(conference_id: @conference.id) + @invites.each do |invite| + invite.emails = User.find(invite.user_id).email + end + end + def new @invite = @conference.invites.new end - def create; end + def create + emails_array = invite_params[:emails].split(',') + invite_count = 0 + flag = 0 + emails_array.each do |email| + @invite = @conference.invites.new(invite_params) + new_user = User.find_by(email: email) + new_user = User.invite!({ email: email }, current_user) if new_user.nil? + @invite.user_id = new_user.id + invite_count += 1 + unless @invite.save + flash.now[:error] = "#{(invite_count - 1)} invitations created. Creating invitation failed. #{@invite.errors.full_messages.to_sentence}." + flag = 1 + break + end + end + if flag.zero? + redirect_to admin_conference_invites_path, notice: "#{invite_count.to_s + ' invitation'.pluralize(invite_count)} successfully created." + else + render 'new' + end + end + + def edit + @invite = Invite.find(params[:id]) + end + + def update + @invite = Invite.find(params[:id]) + if @invite.update_attributes(invite_params) + redirect_to admin_conference_invites_path, + notice: 'Invitation successfully updated.' + else + flash.now[:error] = "Creating invitation failed. #{@invite.errors.full_messages.to_sentence}." + render 'edit' + end + end + + def destroy + if Invite.find(params[:id]).destroy + redirect_to admin_conference_invites_path, + notice: 'Invitation deleted.' + else + redirect_to admin_conference_invites_path, + notice: 'Unable to delete the invitation.' + end + end + + private + + def invite_params + params.require(:invite).permit(:emails, :end_date, :invite_for) + end end end diff --git a/app/views/admin/booths/index.html.haml b/app/views/admin/booths/index.html.haml index d5c02bdc..e38c5163 100644 --- a/app/views/admin/booths/index.html.haml +++ b/app/views/admin/booths/index.html.haml @@ -100,3 +100,4 @@ .col-md-12.text-right - if can? :create, Booth = link_to 'New Booth', new_admin_conference_booth_path(@conference.short_title), class: 'button btn btn-primary' + = link_to 'Late Submission Invite', new_admin_conference_invite_path(@conference.short_title), class: 'button btn btn-success' diff --git a/app/views/admin/invites/edit.html.haml b/app/views/admin/invites/edit.html.haml new file mode 100644 index 00000000..ab465b73 --- /dev/null +++ b/app/views/admin/invites/edit.html.haml @@ -0,0 +1,11 @@ +.row + .col-md-12 + .page-header + %h1 Edit Invitation + +.row + .col-md-8 + = semantic_form_for(@invite, url: admin_conference_invite_path(@conference.short_title), html: { multipart: true }) do |f| + = f.input :invite_for, as: :select, collection: ['Track', (t 'booth').capitalize] + = f.input :end_date, as: :string, input_html: { id: 'invitation-end-date', end_date: @conference.end_date } + = f.action :submit, as: :button, button_html: { class: 'btn btn-primary' } diff --git a/app/views/admin/invites/index.html.haml b/app/views/admin/invites/index.html.haml new file mode 100644 index 00000000..7f1a28dc --- /dev/null +++ b/app/views/admin/invites/index.html.haml @@ -0,0 +1,42 @@ +.row + .col-md-12 + .page-header + %h1 + Invitations + +.row + .col-md-12 + - if @invites.present? + %table.datatable + %thead + %th + %b ID + %th + %b User + %th + %b Invited for + %th + %b Invitation validity + %th + %b Action + + - @invites.each do |invite| + %tr + %td + = invite.id + %td + = invite.emails + %td + = invite.invite_for + %td + = invite.end_date + %td + = link_to 'Edit', edit_admin_conference_invite_path(@conference.short_title, invite.id), + class: 'btn btn-primary' + = link_to 'Delete', admin_conference_invite_path(@conference.short_title, invite.id), method: :delete, + data: { confirm: 'Are you sure?' }, class: 'btn btn-danger' + +.row + .col-md-12.text-right + - if can? :create, Invite + = link_to 'Late Submission Invite', new_admin_conference_invite_path(@conference.short_title), class: 'button btn btn-success' diff --git a/app/views/admin/invites/new.html.haml b/app/views/admin/invites/new.html.haml index a921d532..b3abeebc 100644 --- a/app/views/admin/invites/new.html.haml +++ b/app/views/admin/invites/new.html.haml @@ -8,6 +8,7 @@ = f.input :end_date, as: :string, input_html: { id: 'invitation-end-date', end_date: @conference.end_date } %p.text-right = f.submit 'Submit', class: 'btn btn-success' + = link_to 'View Invitations', admin_conference_invites_path, class: 'btn btn-primary' :javascript $(document).ready(function() { diff --git a/app/views/admin/tracks/index.html.haml b/app/views/admin/tracks/index.html.haml index acdbfe0d..bf006e94 100644 --- a/app/views/admin/tracks/index.html.haml +++ b/app/views/admin/tracks/index.html.haml @@ -100,3 +100,4 @@ .row .col-md-12.text-right = link_to 'New Track', new_admin_conference_program_track_path(@conference.short_title), class: 'btn btn-primary' + = link_to 'Late Submission Invite', new_admin_conference_invite_path(@conference.short_title), class: 'button btn btn-success' diff --git a/spec/controllers/admin/invites_controller_spec.rb b/spec/controllers/admin/invites_controller_spec.rb new file mode 100644 index 00000000..cb599843 --- /dev/null +++ b/spec/controllers/admin/invites_controller_spec.rb @@ -0,0 +1,152 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Admin::InvitesController do + + let(:admin) { create(:admin) } + let(:conference) { create(:conference) } + let(:invite) { create(:invite, user_id: 1, end_date: '2019-08-12', invite_for: (t 'booth').capitalize, conference: conference) } + + context 'not logged in user' do + + describe 'GET index' do + it 'does not render admin/invites#index' do + get :index, params: { conference_id: conference.short_title } + expect(response).to redirect_to(user_session_path) + end + end + + describe 'GET new' do + it 'does not render admin/invites#new' do + get :new, params: { conference_id: conference.short_title } + expect(response).to redirect_to(user_session_path) + end + end + end + + context 'user is admin' do + before :each do + sign_in admin + end + + describe 'GET index' do + before { get :index, params: { conference_id: conference.short_title } } + + it 'renders index template' do + expect(response).to render_template('index') + end + end + + describe 'GET new' do + before { get :new, params: { conference_id: conference.short_title } } + + it 'assigns attributes for invite' do + expect(assigns(:invite)).to be_a_new(Invite) + end + + it 'renders new template' do + expect(response).to render_template('new') + end + end + + describe 'POST #create' do + context 'successfully created' do + before { post :create, params: { invite: attributes_for(:invite), conference_id: conference.short_title } } + + it 'creates a new invite' do + expected = expect do + post :create, params: { invite: { emails: 'user1@example.com', end_date: Date.today, invite_for: (t 'booth').pluralize.to_s }, conference_id: conference.short_title } + end + expected.to change(Invite, :count).by(1) + end + + it 'redirects to admin booth index' do + expect(response).to redirect_to(admin_conference_invites_path) + end + + it 'creates a new user on inviting for late submission' do + expect(User.where(email: 'user@example.com')).to exist + end + + it 'does not create a user with invalid email on inviting booth responsible' do + expect(User.where(email: 'example')).not_to exist + end + + it 'invited user should be a part of invites' do + expect(Invite.pluck(:user_id)).to include(User.find_by(email: 'user@example.com').id) + end + end + + context 'create action fails' do + before { post :create, params: { invite: attributes_for(:invite, emails: 'example'), conference_id: conference.short_title } } + + it 'does not create any invite on invalid email' do + expected = expect do + post :create, params: { invite: attributes_for(:invite, emails: 'example'), conference_id: conference.short_title } + end + expected.to_not change(Invite, :count) + end + + it 'does not create a duplicate invite' do + post :create, params: { invite: attributes_for(:invite), conference_id: conference.short_title } + expected = expect do + post :create, params: { invite: attributes_for(:invite), conference_id: conference.short_title } + end + expected.to change(Invite, :count).by(0) + end + + it 'redirects to new' do + expect(response).to render_template('new') + end + end + end + + describe 'GET #edit' do + before { get :edit, params: { id: invite.id, conference_id: conference.short_title } } + + it 'renders edit template' do + expect(response).to render_template('edit') + end + + it 'assigns booth variable' do + expect(assigns(:invite)).to eq invite + end + end + + describe 'PATCH #update' do + context 'updates suchessfully' do + before { patch :update, params: { id: invite.id, invite: attributes_for(:invite, end_date: '2019-08-13'), conference_id: conference.short_title } } + + it 'redirects to admin invite index path' do + expect(response).to redirect_to admin_conference_invites_path + end + + it 'shows success message' do + expect(flash[:notice]).to match 'Invitation successfully updated.' + end + + it 'updates invite' do + invite.reload + expect(invite.end_date).to eq(Date.parse('2019-08-13')) + end + end + end + + describe 'DELETE #destroy' do + before { delete :destroy, params: { conference_id: conference.short_title, id: invite.id } } + + it 'redirects to admin room index path' do + expect(response).to redirect_to admin_conference_invites_path(conference_id: conference.short_title) + end + + it 'shows success message in flash notice' do + expect(flash[:notice]).to match('Invitation deleted.') + end + + it 'deletes the room' do + expect(Invite.count).to eq 0 + end + end + end +end diff --git a/spec/factories/invites.rb b/spec/factories/invites.rb new file mode 100644 index 00000000..92365b25 --- /dev/null +++ b/spec/factories/invites.rb @@ -0,0 +1,9 @@ +FactoryBot.define do + factory :invite do + conference + emails { 'user@example.com' } + end_date { '2019-08-12' } + invite_for { (I18n.t 'booth').capitalize.to_s } + user_id { 1 } + end +end