diff --git a/app/controllers/admin/photos_controller.rb b/app/controllers/admin/photos_controller.rb new file mode 100644 index 00000000..fc598d09 --- /dev/null +++ b/app/controllers/admin/photos_controller.rb @@ -0,0 +1,65 @@ +module Admin + class PhotosController < ApplicationController + before_action :set_conference + before_action :set_photo, only: [:edit, :update, :destroy] + +# GET /admin/photos + def index + @photos = @conference.photos.all + end + +# GET /admin/photos/new + def new + @photo = @conference.photos.build + end + +# GET /admin/photos/1/edit + def edit + end + +# POST /admin/photos + def create + @photo = @conference.photos.build(photo_params) + if @photo.save + redirect_to admin_conference_photos_path, notice: 'Photo was successfully created.' + else + flash[:alert] = "A error prohibited this Photo from being saved: #{@photo.errors.full_messages.join('. ')}." + render :new + end + end + +# PATCH/PUT /admin/photos/1 + def update + if @photo.update(photo_params) + redirect_to admin_conference_photos_path, notice: 'Photo was successfully updated.' + else + flash[:alert] = "A error prohibited this Photo from being saved: #{@photo.errors.full_messages.join('. ')}." + render :edit + end + end + +# DELETE /admin/photos/1 + def destroy + @photo.destroy + redirect_to admin_conference_photos_path, notice: 'Photo was successfully destroyed.' + end + + private + +# Use callbacks to share common setup or constraints between actions. + def set_conference + @conference = Conference.find_by(short_title: params[:conference_id]) + end + +# Use callbacks to share common setup or constraints between actions. + def set_photo + @photo = Photo.find_by(id: params[:id]) + end + +# Only allow a trusted parameter "white list" through. + def photo_params + params[:photo] + end + end +end + diff --git a/app/views/admin/conference/_edit_form.html.haml b/app/views/admin/conference/_edit_form.html.haml index 11e7a513..ed26829b 100644 --- a/app/views/admin/conference/_edit_form.html.haml +++ b/app/views/admin/conference/_edit_form.html.haml @@ -27,6 +27,4 @@ = f.input :sponsor_description, hint: markdown_hint("This will appear in the sponsor segment of the splash."), input_html: { rows: 5, data: { provide: "markdown-editable" } } = f.input :sponsor_email, hint: 'This will appear in the sponsor segment of the splash for the sponsors to contact to the organizers' = f.input :lodging_description, hint: markdown_hint("This will appear in the lodging segment of the splash."), input_html: { rows: 5, data: { provide: "markdown-editable" } } - - = dynamic_association :photos, "Photos", f = f.action :submit, :as => :button, :button_html => {:class => "btn btn-primary"} diff --git a/app/views/admin/conference/_photo_fields.html.erb b/app/views/admin/conference/_photo_fields.html.erb deleted file mode 100644 index 29a1f16b..00000000 --- a/app/views/admin/conference/_photo_fields.html.erb +++ /dev/null @@ -1,10 +0,0 @@ -
- <%= f.inputs do %> - <%= image_tag(f.object.picture(:thumb)) unless f.object.picture.blank? %> - <%= f.input :picture, hint: 'This photo will appear in the gallery of the splash - so please give photos of banner sizes' %> - <%= f.input :description, :input_html => {:rows => 2 }, hint: 'This description will appear - at the bottom of each photo' %> - <%= remove_association_link :photo, f %> - <% end %> -
diff --git a/app/views/admin/photos/_form.html.haml b/app/views/admin/photos/_form.html.haml new file mode 100644 index 00000000..2c01af4c --- /dev/null +++ b/app/views/admin/photos/_form.html.haml @@ -0,0 +1,7 @@ += f.inputs do + - if !f.object.errors + = image_tag(f.object.picture(:thumb)) unless f.object.picture.blank? + = f.input :picture, hint: 'This photo will appear in the gallery of the splash so please give photos of banner sizes.' + = f.input :description, :input_html => {:rows => 2 }, hint: 'This description will appear at the bottom of each photo.' + .actions + = f.button 'Save Photo', :class => 'btn btn-primary' diff --git a/app/views/admin/photos/edit.html.haml b/app/views/admin/photos/edit.html.haml new file mode 100644 index 00000000..9b87054b --- /dev/null +++ b/app/views/admin/photos/edit.html.haml @@ -0,0 +1,6 @@ +%h1 Editing Photo + += semantic_form_for @photo, url: admin_conference_photo_path(conference_id: @conference.short_title, id: @photo.id) do |f| + = render 'form', f: f + += link_to 'Back', admin_conference_photos_path diff --git a/app/views/admin/photos/index.html.haml b/app/views/admin/photos/index.html.haml new file mode 100644 index 00000000..77f4f5d7 --- /dev/null +++ b/app/views/admin/photos/index.html.haml @@ -0,0 +1,22 @@ +%h1 Photos +%p.text-muted + Photo's will appear in the gallery of the conference splash page. +- @photos.each_slice(3) do |slice| + .row.row-flex.row-flex-wrap + - slice.each do |photo| + .col-md-4 + .thumbnail.flex-col + %h3.text-center + = photo.picture_file_name + = image_tag(photo.picture(:large), class: 'img-responsive', title: photo.description) + .caption.flex-grow + .caption + = link_to edit_admin_conference_photo_path(@conference.short_title, photo.id), class: 'btn btn-primary' do + %i.fa.fa-pencil-square-o + Edit + = link_to admin_conference_photo_path(@conference.short_title, photo.id), method: :delete, class: 'btn btn-danger' do + %i.fa.fa-times-circle + Delete +.row{'style'=>'padding-top: 10px;'} + .col-md-12 + = link_to 'New Photo', new_admin_conference_photo_path, class: 'btn btn-primary' diff --git a/app/views/admin/photos/new.html.haml b/app/views/admin/photos/new.html.haml new file mode 100644 index 00000000..68115b49 --- /dev/null +++ b/app/views/admin/photos/new.html.haml @@ -0,0 +1,6 @@ +%h1 New Photo + += semantic_form_for @photo, url: admin_conference_photos_path(conference_id: @conference.short_title) do |f| + = render 'form', f: f + += link_to 'Back', admin_conference_photos_path diff --git a/app/views/layouts/_admin_sidebar.html.haml b/app/views/layouts/_admin_sidebar.html.haml index b9f5e5db..31f8397b 100644 --- a/app/views/layouts/_admin_sidebar.html.haml +++ b/app/views/layouts/_admin_sidebar.html.haml @@ -35,8 +35,12 @@ Contact %li{:class=> "#{active_nav_li(admin_conference_commercials_path(@conference.short_title))}"} = link_to(admin_conference_commercials_path(@conference.short_title)) do - %span.fa.fa-comment + %span.fa.fa-film Commercials + %li{:class=> "#{active_nav_li(admin_conference_photos_path(@conference.short_title))}"} + = link_to(admin_conference_photos_path(@conference.short_title)) do + %span.fa.fa-picture-o + Photos %li{:class=> active_nav_li(admin_conference_events_path(@conference.short_title))} = link_to(admin_conference_events_path(@conference.short_title)) do %span.glyphicon.glyphicon-comment diff --git a/config/routes.rb b/config/routes.rb index c8bc7a05..030a4bb0 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -9,6 +9,7 @@ Osem::Application.routes.draw do resources :people resources :conference do resource :contact, except: [:index, :new, :create, :show, :destroy] + resources :photos, except: [:show] resource :schedule, only: [:show, :update] resources :commercials, except: [:show] get '/stats' => 'stats#index' diff --git a/spec/factories/photos.rb b/spec/factories/photos.rb index 49180a0b..c3e69721 100644 --- a/spec/factories/photos.rb +++ b/spec/factories/photos.rb @@ -1,7 +1,9 @@ # Read about factories at https://github.com/thoughtbot/factory_girl +include ActionDispatch::TestProcess FactoryGirl.define do factory :photo do + picture { fixture_file_upload(Rails.root.join('app', 'assets', 'images', 'rails.png'), 'image/png') } picture_file_name 'rails.png' picture_content_type 'image/png' picture_file_size '1024' diff --git a/spec/features/photo_spec.rb b/spec/features/photo_spec.rb new file mode 100644 index 00000000..c9150b30 --- /dev/null +++ b/spec/features/photo_spec.rb @@ -0,0 +1,75 @@ +require 'spec_helper' + +feature Photo do + + # It is necessary to use bang version of let to build roles before user + let!(:organizer_role) { create(:organizer_role) } + let!(:participant_role) { create(:participant_role) } + let!(:admin_role) { create(:admin_role) } + + shared_examples 'add and update photo' do |user| + scenario 'adds a new photo', feature: true, js: true do + expected_count = Photo.count + 1 + conference = create(:conference) + sign_in create(user) + + visit new_admin_conference_photo_path(conference.short_title) + + file_path = Rails.root.join('app', 'assets', 'images', 'rails.png') + attach_file('photo_picture', file_path) + fill_in 'photo_description', with: 'Lorem ipsum dolorem...' + + click_button 'Save Photo' + + expect(flash). + to eq('Photo was successfully created.') + expect(Photo.count).to eq(expected_count) + end + + scenario 'updates a photo', feature: true, js: true do + expected_count = Photo.count + 1 + conference = create(:conference) + photo = create(:photo) + sign_in create(user) + + visit edit_admin_conference_photo_path(conference.short_title, photo.id) + + file_path = Rails.root.join('app', 'assets', 'images', 'person_large.png') + attach_file('photo_picture', file_path) + fill_in 'photo_description', with: 'Lorem ipsum dolorem...' + + click_button 'Save Photo' + + expect(flash). + to eq('Photo was successfully updated.') + expect(Photo.count).to eq(expected_count) + end + + scenario 'adds a text file', feature: true, js: true do + expected_count = Photo.count + conference = create(:conference) + sign_in create(user) + + visit new_admin_conference_photo_path(conference.short_title) + + file_path = Rails.root + 'spec/fixtures/test.txt' + attach_file('photo_picture', file_path) + fill_in 'photo_description', with: 'Lorem ipsum dolorem...' + + click_button 'Save Photo' + + expect(flash). + to eq("A error prohibited this Photo from being saved: Picture content type is invalid. Picture is invalid.") + expect(Photo.count).to eq(expected_count) + end + end + + describe 'admin' do + it_behaves_like 'add and update photo', :admin + end + + describe 'organizer' do + it_behaves_like 'add and update photo', :organizer + end + +end diff --git a/spec/fixtures/test.txt b/spec/fixtures/test.txt new file mode 100644 index 00000000..7dc5f421 --- /dev/null +++ b/spec/fixtures/test.txt @@ -0,0 +1 @@ +Lorem ipsum dolorem... \ No newline at end of file