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