diff --git a/.ruby-version b/.ruby-version index 8f9174b..ac2cdeb 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -2.1.2 \ No newline at end of file +2.1.3 diff --git a/Gemfile b/Gemfile index 10d52dc..7f95bac 100644 --- a/Gemfile +++ b/Gemfile @@ -1,6 +1,6 @@ source 'https://rubygems.org' -gem 'rails', '4.1.5' +gem 'rails', '4.1.6' gem 'sqlite3' gem 'pg' @@ -37,6 +37,14 @@ gem 'puma' gem 'globalize', '~> 4.0.2' +gem 'yaml_db', github: 'jetthoughts/yaml_db', ref: 'fb4b6bd7e12de3cffa93e0a298a1e5253d7e92ba' + +gem 'bootstrap-sass' +gem 'bootstrap-sass-extras' +gem 'bootswatch-rails' +gem 'autoprefixer-rails' +gem 'font-awesome-rails' + group :development do gem 'spring' gem 'spring-commands-rspec' diff --git a/Gemfile.lock b/Gemfile.lock index 24c19a2..97d995f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -7,46 +7,61 @@ GIT rails (>= 4.0.0) simple_form (~> 3.0) +GIT + remote: git://github.com/jetthoughts/yaml_db.git + revision: fb4b6bd7e12de3cffa93e0a298a1e5253d7e92ba + ref: fb4b6bd7e12de3cffa93e0a298a1e5253d7e92ba + specs: + yaml_db (0.2.3) + GEM remote: https://rubygems.org/ specs: - actionmailer (4.1.5) - actionpack (= 4.1.5) - actionview (= 4.1.5) - mail (~> 2.5.4) - actionpack (4.1.5) - actionview (= 4.1.5) - activesupport (= 4.1.5) + actionmailer (4.1.6) + actionpack (= 4.1.6) + actionview (= 4.1.6) + mail (~> 2.5, >= 2.5.4) + actionpack (4.1.6) + actionview (= 4.1.6) + activesupport (= 4.1.6) rack (~> 1.5.2) rack-test (~> 0.6.2) - actionview (4.1.5) - activesupport (= 4.1.5) + actionview (4.1.6) + activesupport (= 4.1.6) builder (~> 3.1) erubis (~> 2.7.0) - activemodel (4.1.5) - activesupport (= 4.1.5) + activemodel (4.1.6) + activesupport (= 4.1.6) builder (~> 3.1) - activerecord (4.1.5) - activemodel (= 4.1.5) - activesupport (= 4.1.5) + activerecord (4.1.6) + activemodel (= 4.1.6) + activesupport (= 4.1.6) arel (~> 5.0.0) - activesupport (4.1.5) + activesupport (4.1.6) i18n (~> 0.6, >= 0.6.9) json (~> 1.7, >= 1.7.7) minitest (~> 5.1) thread_safe (~> 0.1) tzinfo (~> 1.1) arel (5.0.1.20140414130214) + autoprefixer-rails (3.1.0.20140911) + execjs bcrypt (3.1.7) + bootstrap-sass (3.2.0.2) + sass (~> 3.2) + bootstrap-sass-extras (0.0.6) + rails (>= 3.1.0) + bootswatch-rails (3.2.4) + railties (>= 3.1) builder (3.2.2) capistrano (3.2.1) i18n rake (>= 10.0.0) sshkit (~> 1.3) - capistrano-bundler (1.1.2) - capistrano (~> 3.0) + capistrano-bundler (1.1.3) + capistrano (~> 3.1) sshkit (~> 1.2) - capistrano-rails (1.1.1) + capistrano-rails (1.1.2) capistrano (~> 3.1) capistrano-bundler (~> 1.1) capistrano-rvm (0.1.1) @@ -63,8 +78,8 @@ GEM activesupport (>= 3.2.0) json (>= 1.7) mime-types (>= 1.16) - celluloid (0.15.2) - timers (~> 1.1.0) + celluloid (0.16.0) + timers (~> 4.0.0) choice (0.1.6) coderay (1.1.0) coffee-rails (4.0.1) @@ -84,7 +99,7 @@ GEM railties (>= 3.2.6, < 5) thread_safe (~> 0.1) warden (~> 1.2.3) - devise-i18n (0.11.0) + devise-i18n (0.11.1) diff-lcs (1.2.5) erubis (2.7.0) execjs (2.2.1) @@ -96,6 +111,8 @@ GEM faker (1.4.3) i18n (~> 0.5) ffi (1.9.3) + font-awesome-rails (4.2.0.0) + railties (>= 3.2, < 5.0) formatador (0.2.5) globalize (4.0.2) activemodel (>= 4.0.0, < 5) @@ -110,22 +127,22 @@ GEM guard (~> 2.1) rspec (>= 2.14, < 4.0) hike (1.2.3) + hitimes (1.2.2) i18n (0.6.11) - jquery-rails (3.1.1) + jquery-rails (3.1.2) railties (>= 3.0, < 5.0) thor (>= 0.14, < 2.0) json (1.8.1) - libv8 (3.16.14.3) + libv8 (3.16.14.7) listen (2.7.9) celluloid (>= 0.15.2) rb-fsevent (>= 0.9.3) rb-inotify (>= 0.9) lumberjack (1.0.9) - mail (2.5.4) - mime-types (~> 1.16) - treetop (~> 1.4.8) + mail (2.6.1) + mime-types (>= 1.16, < 3) method_source (0.8.2) - mime-types (1.25.1) + mime-types (2.3) mini_portile (0.6.0) minitest (5.4.1) multi_json (1.10.1) @@ -136,42 +153,41 @@ GEM mini_portile (= 0.6.0) orm_adapter (0.5.0) pg (0.17.1) - phony (2.2.15) + phony (2.3.0) phony_rails (0.6.2) activesupport (>= 3.0) countries (>= 0.8.2) phony (~> 2.1) - polyglot (0.3.5) pry (0.10.1) coderay (~> 1.1.0) method_source (~> 0.8.1) slop (~> 3.4) - puma (2.9.0) + puma (2.9.1) rack (>= 1.1, < 2.0) rack (1.5.2) rack-test (0.6.2) rack (>= 1.0) - rails (4.1.5) - actionmailer (= 4.1.5) - actionpack (= 4.1.5) - actionview (= 4.1.5) - activemodel (= 4.1.5) - activerecord (= 4.1.5) - activesupport (= 4.1.5) + rails (4.1.6) + actionmailer (= 4.1.6) + actionpack (= 4.1.6) + actionview (= 4.1.6) + activemodel (= 4.1.6) + activerecord (= 4.1.6) + activesupport (= 4.1.6) bundler (>= 1.3.0, < 2.0) - railties (= 4.1.5) + railties (= 4.1.6) sprockets-rails (~> 2.0) rails-erd (1.1.0) activerecord (>= 3.0) activesupport (>= 3.0) choice (~> 0.1.6) ruby-graphviz (~> 1.0.4) - rails-i18n (4.0.2) + rails-i18n (4.0.3) i18n (~> 0.6) - rails (>= 4.0) - railties (4.1.5) - actionpack (= 4.1.5) - activesupport (= 4.1.5) + railties (~> 4.0) + railties (4.1.6) + actionpack (= 4.1.6) + activesupport (= 4.1.6) rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) rake (10.3.2) @@ -180,26 +196,26 @@ GEM ffi (>= 0.5.0) ref (1.0.5) rmagick (2.13.3) - rspec (3.0.0) - rspec-core (~> 3.0.0) - rspec-expectations (~> 3.0.0) - rspec-mocks (~> 3.0.0) - rspec-core (3.0.4) - rspec-support (~> 3.0.0) - rspec-expectations (3.0.4) + rspec (3.1.0) + rspec-core (~> 3.1.0) + rspec-expectations (~> 3.1.0) + rspec-mocks (~> 3.1.0) + rspec-core (3.1.4) + rspec-support (~> 3.1.0) + rspec-expectations (3.1.1) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.0.0) - rspec-mocks (3.0.4) - rspec-support (~> 3.0.0) - rspec-rails (3.0.2) + rspec-support (~> 3.1.0) + rspec-mocks (3.1.1) + rspec-support (~> 3.1.0) + rspec-rails (3.1.0) actionpack (>= 3.0) activesupport (>= 3.0) railties (>= 3.0) - rspec-core (~> 3.0.0) - rspec-expectations (~> 3.0.0) - rspec-mocks (~> 3.0.0) - rspec-support (~> 3.0.0) - rspec-support (3.0.4) + rspec-core (~> 3.1.0) + rspec-expectations (~> 3.1.0) + rspec-mocks (~> 3.1.0) + rspec-support (~> 3.1.0) + rspec-support (3.1.0) ruby-graphviz (1.0.9) sass (3.2.19) sass-rails (4.0.3) @@ -227,7 +243,7 @@ GEM multi_json (~> 1.0) rack (~> 1.0) tilt (~> 1.1, != 1.3.0) - sprockets-rails (2.1.3) + sprockets-rails (2.1.4) actionpack (>= 3.0) activesupport (>= 3.0) sprockets (~> 2.8) @@ -243,10 +259,8 @@ GEM thor (0.19.1) thread_safe (0.3.4) tilt (1.4.1) - timers (1.1.0) - treetop (1.4.15) - polyglot - polyglot (>= 0.3.1) + timers (4.0.1) + hitimes tzinfo (1.2.2) thread_safe (~> 0.1) uglifier (2.5.3) @@ -261,6 +275,10 @@ PLATFORMS ruby DEPENDENCIES + autoprefixer-rails + bootstrap-sass + bootstrap-sass-extras + bootswatch-rails capistrano capistrano-rails capistrano-rvm @@ -271,13 +289,14 @@ DEPENDENCIES devise-i18n factory_girl_rails faker + font-awesome-rails globalize (~> 4.0.2) guard-rspec jquery-rails pg phony_rails puma - rails (= 4.1.5) + rails (= 4.1.6) rails-erd rails-i18n rmagick @@ -291,3 +310,4 @@ DEPENDENCIES sqlite3 therubyracer uglifier + yaml_db! diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 1ca0e3b..af0d871 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -12,4 +12,4 @@ // //= require jquery //= require jquery_ujs -//= require_tree . +//= require_directory . diff --git a/app/assets/javascripts/management/application.js b/app/assets/javascripts/management/application.js new file mode 100644 index 0000000..bffe770 --- /dev/null +++ b/app/assets/javascripts/management/application.js @@ -0,0 +1,4 @@ +//= require jquery +//= require jquery_ujs +//= require bootstrap-sprockets +//= require_directory . diff --git a/app/assets/stylesheets/management/_model_details.css.scss b/app/assets/stylesheets/management/_model_details.css.scss new file mode 100644 index 0000000..5f11cae --- /dev/null +++ b/app/assets/stylesheets/management/_model_details.css.scss @@ -0,0 +1,23 @@ +.model-details { + @extend .modal; + @extend .fade; + .center { + text-align: center; + } + + .profile-image { + @extend .img-thumbnail; + max-width: 171px; + max-height: 180px; + } + + .social { + @extend .btn-group; + margin-top: 10px; + + a { + @extend .btn; + @extend .btn-default; + } + } +} \ No newline at end of file diff --git a/app/assets/stylesheets/management/_navbar.css.scss b/app/assets/stylesheets/management/_navbar.css.scss new file mode 100644 index 0000000..e2b26c5 --- /dev/null +++ b/app/assets/stylesheets/management/_navbar.css.scss @@ -0,0 +1,3 @@ +body { + padding-top: 70px; +} diff --git a/app/assets/stylesheets/management/_record_table.css.scss b/app/assets/stylesheets/management/_record_table.css.scss new file mode 100644 index 0000000..4efd78e --- /dev/null +++ b/app/assets/stylesheets/management/_record_table.css.scss @@ -0,0 +1,62 @@ +.record-table { + @extend .table; + @extend .table-striped; + + td { + vertical-align: middle !important; + } + + th.picture, td.picture { + text-align: center; + width: 60px; + } + + th.admin, td.admin { + width: 60px; + } + + th.actions, td.actions { + width: 120px; + } + + .actions div { + @extend .pull-right; + @extend .btn-group; + white-space: nowrap; + + a { + @extend .btn; + @extend .btn-default; + } + } + + .toggle { + a { + @extend .btn; + } + + a.checked { + @extend .btn-success; + } + + a.unchecked { + @extend .btn-primary; + } + } + + .subtitle { + font-size: 0.9em; + font-style: italic; + } +} + +.picture-placeholder { + @extend .img-thumbnail; + + .glyphicon { + width: 50px; + height: 50px; + font-size: 48px; + text-align: center; + } +} diff --git a/app/assets/stylesheets/management/application.css.scss b/app/assets/stylesheets/management/application.css.scss new file mode 100644 index 0000000..6d33057 --- /dev/null +++ b/app/assets/stylesheets/management/application.css.scss @@ -0,0 +1,8 @@ +@import "bootstrap-sprockets"; +@import "bootswatch/simplex/variables"; +@import "bootstrap"; +@import "bootswatch/simplex/bootswatch"; +@import "font-awesome"; +@import "navbar"; +@import "record_table"; +@import "model_details"; \ No newline at end of file diff --git a/app/controllers/management/events_controller.rb b/app/controllers/management/events_controller.rb new file mode 100644 index 0000000..36fb081 --- /dev/null +++ b/app/controllers/management/events_controller.rb @@ -0,0 +1,18 @@ +module Management + class EventsController < ManagementController + before_action :assign_suggestion, only: [:show] + + def index + @suggestion_groups = SuggestionGroup.for_conference Conference.current + end + + def show + end + + private + + def assign_suggestion + @suggestion = Event.find params[:id] + end + end +end diff --git a/app/controllers/management/home_controller.rb b/app/controllers/management/home_controller.rb new file mode 100644 index 0000000..0d0aee3 --- /dev/null +++ b/app/controllers/management/home_controller.rb @@ -0,0 +1,6 @@ +module Management + class HomeController < ManagementController + def index + end + end +end diff --git a/app/controllers/management/management_controller.rb b/app/controllers/management/management_controller.rb new file mode 100644 index 0000000..d50b412 --- /dev/null +++ b/app/controllers/management/management_controller.rb @@ -0,0 +1,13 @@ +module Management + class ManagementController < ::ApplicationController + before_action :authenticate_user!, :authorize_user! + + layout 'management' + + private + + def authorize_user! + head :forbidden unless current_user.admin? + end + end +end diff --git a/app/controllers/management/users_controller.rb b/app/controllers/management/users_controller.rb new file mode 100644 index 0000000..c6871d9 --- /dev/null +++ b/app/controllers/management/users_controller.rb @@ -0,0 +1,22 @@ +module Management + class UsersController < ManagementController + before_action :assign_user, only: [:show, :toggle_admin] + + def index + @users = User.all + end + + def toggle_admin + @user.toggle_admin! + end + + def show + end + + private + + def assign_user + @user = User.find params[:id] + end + end +end diff --git a/app/models/conference.rb b/app/models/conference.rb index d93d3f3..224a408 100644 --- a/app/models/conference.rb +++ b/app/models/conference.rb @@ -10,6 +10,7 @@ class Conference < ActiveRecord::Base has_many :tracks, -> { order('id asc') } has_many :events, through: :tracks + has_many :candidate_speakers, through: :events scope :future, -> { where('start_date >= ?', Date.today).order('start_date ASC') } diff --git a/app/models/event.rb b/app/models/event.rb index 80460aa..7693a0f 100644 --- a/app/models/event.rb +++ b/app/models/event.rb @@ -8,7 +8,8 @@ class Event < ActiveRecord::Base belongs_to :track has_one :conference, through: :track - belongs_to :user + belongs_to :user # XXX: Transition to candidate_speaker + belongs_to :candidate_speaker, class_name: 'User', foreign_key: 'user_id' after_create :send_new_event_notification diff --git a/app/models/speaker_profile.rb b/app/models/speaker_profile.rb index 9e0ce34..c026383 100644 --- a/app/models/speaker_profile.rb +++ b/app/models/speaker_profile.rb @@ -17,4 +17,8 @@ class SpeakerProfile < ActiveRecord::Base def twitter=(handle) write_attribute :twitter, handle.gsub(/\A@/,'') if handle end + + def name + "#{first_name} #{last_name}" + end end diff --git a/app/models/suggestion_group.rb b/app/models/suggestion_group.rb new file mode 100644 index 0000000..8d09f16 --- /dev/null +++ b/app/models/suggestion_group.rb @@ -0,0 +1,14 @@ +class SuggestionGroup + include ActiveModel::Model + attr_accessor :speaker, :suggestions + + def self.where(conditions = {}) + Event.joins(:track).includes(:user).where(conditions).group_by(&:user).map do |speaker, suggestions| + SuggestionGroup.new speaker: speaker, suggestions: suggestions + end + end + + def self.for_conference(conference) + where tracks: {conference_id: conference.id} + end +end diff --git a/app/models/user.rb b/app/models/user.rb index 8ae638a..0ecaa45 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -7,6 +7,13 @@ class User < ActiveRecord::Base has_one :speaker_profile has_many :lectures has_many :workshops + has_many :events accepts_nested_attributes_for :speaker_profile, update_only: true + + default_scope { order id: :desc } + + def toggle_admin! + update admin: !admin + end end diff --git a/app/uploaders/picture_uploader.rb b/app/uploaders/picture_uploader.rb index a8c178c..5278dd1 100644 --- a/app/uploaders/picture_uploader.rb +++ b/app/uploaders/picture_uploader.rb @@ -30,6 +30,11 @@ class PictureUploader < CarrierWave::Uploader::Base # end # Create different versions of your uploaded files: + + version :medium do + process :resize_to_fit => [171, 180] + end + version :thumb do process :resize_to_fit => [50, 50] end diff --git a/app/views/layouts/management.html.slim b/app/views/layouts/management.html.slim new file mode 100644 index 0000000..da5f01f --- /dev/null +++ b/app/views/layouts/management.html.slim @@ -0,0 +1,29 @@ +doctype html + +html + head + meta charset="utf-8" + meta http-equiv="X-UA-Compatible" content="IE=edge" + meta name="viewport" content="width=device-width, initial-scale=1" + title Clarion + = stylesheet_link_tag "management/application" + = csrf_meta_tags + body + nav.navbar.navbar-default.navbar-fixed-top + .container + .navbar-header + button.navbar-toggle.collapsed type="button" data-toggle="collapse" data-target=".navbar-collapse" + span.sr-only Toggle navigation + span.icon-bar + span.icon-bar + span.icon-bar + = link_to 'Clarion', root_path, class: 'navbar-brand' + .navbar-collapse.collapse + ul.nav.navbar-nav + li class="#{'active' if controller_name == 'users'}" + = link_to User.model_name.human(count: 2), management_users_path + li class="#{'active' if controller_name == 'events'}" + = link_to Event.model_name.human(count: 2), management_events_path + div.container + == yield + = javascript_include_tag "management/application" diff --git a/app/views/management/events/_suggestion_details.html.slim b/app/views/management/events/_suggestion_details.html.slim new file mode 100644 index 0000000..204ade7 --- /dev/null +++ b/app/views/management/events/_suggestion_details.html.slim @@ -0,0 +1,54 @@ +.model-details id="suggestion-#{@suggestion.id}-details" tabindex="-1" role="dialog" aria-hidden="true" + .modal-dialog + .modal-content + .modal-header + button type="button" class="close" data-dismiss="modal" aria-hidden="true" + h4.modal-title + = @suggestion.title + small< + = @suggestion.subtitle + br + = t :meta_data, language: @suggestion.language, track: @suggestion.track.name, length: @suggestion.length + + .modal-body + .center + h4 = @suggestion.class.human_attribute_name(:user) + - unless @suggestion.user.speaker_profile.present? + div.picture-placeholder + = glyph(:user) + h3.media-heading + = @suggestion.user.email + + - else + = image_tag @suggestion.user.speaker_profile.picture.medium.url, class: "profile-image" + h3.media-heading + = @suggestion.user.speaker_profile.name + - if @suggestion.user.speaker_profile.organisation.present? + div + => fa_icon(:briefcase) + = @suggestion.user.speaker_profile.organisation + + div.social + = link_to "mailto://#{@suggestion.user.email}" + = fa_icon :envelope + - if @suggestion.user.speaker_profile.github.present? + = link_to "https://github.com/#{@suggestion.user.speaker_profile.github}" + = fa_icon :github + - if @suggestion.user.speaker_profile.twitter.present? + = link_to "https://twitter.com/#{@suggestion.user.speaker_profile.twitter}" + = fa_icon :twitter + + h4 = @suggestion.class.human_attribute_name(:abstract) + = simple_format @suggestion.abstract + + h4 = @suggestion.class.human_attribute_name(:description) + = simple_format @suggestion.description + + + - if @suggestion.notes.present? + h4 = @suggestion.class.human_attribute_name(:notes) + = simple_format @suggestion.notes + + .modal-footer + button type="button" class="btn btn-default" data-dismiss="modal" + = t(:close) diff --git a/app/views/management/events/_suggestion_group.html.slim b/app/views/management/events/_suggestion_group.html.slim new file mode 100644 index 0000000..3401027 --- /dev/null +++ b/app/views/management/events/_suggestion_group.html.slim @@ -0,0 +1,28 @@ +- suggestion_group.suggestions.each_with_index do |suggestion, index| + tr + - if index == 0 + td.picture rowspan="#{suggestion_group.suggestions.count}" + - if suggestion_group.speaker.speaker_profile.present? + = link_to management_user_path(suggestion_group.speaker), remote: true + = image_tag suggestion_group.speaker.speaker_profile.picture.thumb.url, class: 'img-thumbnail' + br + = suggestion_group.speaker.speaker_profile.name + - else + .picture-placeholder + = glyph(:user) + = suggestion_group.speaker.email + + td + span.title + = link_to management_event_path(suggestion), title: t(:view), remote: true + = suggestion.title + br + span.subtitle + = suggestion.subtitle + td = suggestion.language + td = suggestion.track.name + td = suggestion.class.model_name.human + td.actions + div + = link_to management_event_path(suggestion), title: t(:view), remote: true + = glyph(:share) diff --git a/app/views/management/events/index.html.slim b/app/views/management/events/index.html.slim new file mode 100644 index 0000000..5c1b5e3 --- /dev/null +++ b/app/views/management/events/index.html.slim @@ -0,0 +1,18 @@ +.row + .panel.panel-primary + .panel-heading + h3.panel-title + = Event.model_name.human(count: 2) + span.pull-right + = t(:suggestion_and_speaker_count, suggestions: @suggestion_groups.map(&:suggestions).flatten.count, speakers: @suggestion_groups.count) + table.record-table + thead + tr + th.picture = Event.human_attribute_name(:user) + th = Event.human_attribute_name(:title) + th = Event.human_attribute_name(:language) + th = Track.model_name.human + th = Event.human_attribute_name(:type) + th.actions + tbody + = render partial: 'suggestion_group', collection: @suggestion_groups diff --git a/app/views/management/events/show.js.erb b/app/views/management/events/show.js.erb new file mode 100644 index 0000000..6a007da --- /dev/null +++ b/app/views/management/events/show.js.erb @@ -0,0 +1,5 @@ +$('body').append('<%= j render 'suggestion_details' %>'); +$('#suggestion-<%= @suggestion.id %>-details').on('hidden.bs.modal', function () { + $(this).remove(); +}); +$('#suggestion-<%= @suggestion.id %>-details').modal('show'); diff --git a/app/views/management/home/index.html.slim b/app/views/management/home/index.html.slim new file mode 100644 index 0000000..3603360 --- /dev/null +++ b/app/views/management/home/index.html.slim @@ -0,0 +1 @@ +p Hello diff --git a/app/views/management/users/_about_user.html.slim b/app/views/management/users/_about_user.html.slim new file mode 100644 index 0000000..a10ede9 --- /dev/null +++ b/app/views/management/users/_about_user.html.slim @@ -0,0 +1,41 @@ +.model-details id="about-user-#{@user.id}" tabindex="-1" role="dialog" aria-hidden="true" + .modal-dialog + .modal-content + .modal-header + button type="button" class="close" data-dismiss="modal" aria-hidden="true" + h4.modal-title = t(:more_about_user, user: @user.speaker_profile.name) + .modal-body + .center + = image_tag @user.speaker_profile.picture.medium.url, class: "profile-image" + h3.media-heading + = @user.speaker_profile.name + - if @user.speaker_profile.organisation.present? + div + => fa_icon(:briefcase) + = @user.speaker_profile.organisation + div.social + = link_to "mailto://#{@user.email}" + = fa_icon :envelope + - if @user.speaker_profile.github.present? + = link_to "https://github.com/#{@user.speaker_profile.github}" + = fa_icon :github + - if @user.speaker_profile.twitter.present? + = link_to "https://twitter.com/#{@user.speaker_profile.twitter}" + = fa_icon :twitter + + hr + + h5 = SpeakerProfile.human_attribute_name(:biography) + = simple_format @user.speaker_profile.biography + + h5 = t :contacts + - if @user.speaker_profile.twitter.present? + p #{fa_icon(:twitter)} @#{@user.speaker_profile.twitter} + - if @user.speaker_profile.public_email.present? + p #{fa_icon(:envelope)} #{@user.speaker_profile.public_email} (#{t(:public)}) + p #{fa_icon(:envelope)} #{@user.email} (#{t(:private)}) + p #{glyph(:phone)} #{Phony.format(@user.speaker_profile.mobile_phone, format: :international)} + + .modal-footer + button type="button" class="btn btn-default" data-dismiss="modal" + = t(:close) diff --git a/app/views/management/users/_user.html.slim b/app/views/management/users/_user.html.slim new file mode 100644 index 0000000..3217d29 --- /dev/null +++ b/app/views/management/users/_user.html.slim @@ -0,0 +1,23 @@ +tr id="user-#{user.id}" + td.picture + - if user.speaker_profile.present? + = image_tag user.speaker_profile.picture.thumb.url, class: 'img-thumbnail' + - else + .picture-placeholder + = glyph(:user) + td = user.email + td = user.speaker_profile.try(:first_name) or '-' + td = user.speaker_profile.try(:last_name) or '-' + td.admin + - if user.admin? + span.toggle + = link_to glyph(:check), toggle_admin_management_user_path(user), remote: true, method: :post, data: {confirm: t(:are_you_sure)}, class: 'checked' + - else + span.toggle + = link_to glyph(:unchecked), toggle_admin_management_user_path(user), remote: true, method: :post, data: {confirm: t(:are_you_sure)}, class: 'unchecked' + td.actions + div + = link_to management_user_path(user), title: t(:view), remote: true, disabled: user.speaker_profile.blank? + = glyph(:share) + = link_to edit_management_user_path(user), title: t(:edit) + = glyph(:edit) diff --git a/app/views/management/users/index.html.slim b/app/views/management/users/index.html.slim new file mode 100644 index 0000000..720f0f4 --- /dev/null +++ b/app/views/management/users/index.html.slim @@ -0,0 +1,15 @@ +.row + .panel.panel-primary + .panel-heading + h3.panel-title = User.model_name.human(count: 2) + table.record-table + thead + tr + th.picture = SpeakerProfile.human_attribute_name(:picture) + th = User.human_attribute_name(:email) + th = SpeakerProfile.human_attribute_name(:first_name) + th = SpeakerProfile.human_attribute_name(:last_name) + th.admin = SpeakerProfile.human_attribute_name(:admin) + th.actions + tbody + = render @users diff --git a/app/views/management/users/show.js.erb b/app/views/management/users/show.js.erb new file mode 100644 index 0000000..36414ae --- /dev/null +++ b/app/views/management/users/show.js.erb @@ -0,0 +1,5 @@ +$('body').append('<%= j render 'about_user' %>'); +$('#about-user-<%= @user.id %>').on('hidden.bs.modal', function () { + $(this).remove(); +}); +$('#about-user-<%= @user.id %>').modal('show'); diff --git a/app/views/management/users/toggle_admin.js.erb b/app/views/management/users/toggle_admin.js.erb new file mode 100644 index 0000000..2dd9be2 --- /dev/null +++ b/app/views/management/users/toggle_admin.js.erb @@ -0,0 +1 @@ +$('#user-<%= @user.id %>').replaceWith('<%= j render @user %>'); diff --git a/config/deploy.rb b/config/deploy.rb index f3547de..0da1138 100644 --- a/config/deploy.rb +++ b/config/deploy.rb @@ -5,7 +5,7 @@ set :application, 'clarion' set :repo_url, 'https://github.com/ignisf/clarion.git' # Default branch is :master -# ask :branch, proc { `git rev-parse --abbrev-ref HEAD`.chomp }.call +ask :branch, proc { `git rev-parse --abbrev-ref HEAD`.chomp }.call # Default deploy_to directory is /var/www/my_app set :deploy_to, '/home/barf/clarion' @@ -34,13 +34,14 @@ set :linked_dirs, %w{bin log tmp/pids tmp/cache tmp/sockets vendor/bundle public # Default value for keep_releases is 5 # set :keep_releases, 5 +set :rvm_ruby_version, '2.1.3' + namespace :deploy do desc 'Restart application' task :restart do on roles(:app), in: :sequence, wait: 5 do - # Your restart mechanism here, for example: - execute :touch, release_path.join('tmp/restart.txt') + execute '/home/barf/restart-clarion-production-server' end end diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb index d2f4ec3..1364a3b 100644 --- a/config/initializers/assets.rb +++ b/config/initializers/assets.rb @@ -5,4 +5,4 @@ Rails.application.config.assets.version = '1.0' # Precompile additional assets. # application.js, application.css, and all non-JS/CSS in app/assets folder are already added. -# Rails.application.config.assets.precompile += %w( search.js ) +Rails.application.config.assets.precompile += %w( management/application.css management/application.js ) diff --git a/config/locales/bg.yml b/config/locales/bg.yml index 58f9c63..e50a402 100644 --- a/config/locales/bg.yml +++ b/config/locales/bg.yml @@ -31,6 +31,9 @@ bg: workshop: one: Уъркшоп other: Уъркшопи + event: + one: Предложение + other: Предложения track: Поток от лекции attributes: user: @@ -49,7 +52,7 @@ bg: biography: Биография github: Github акаунт twitter: Twitter акаунт - lecture: + event: title: Заглавие subtitle: Подзаглавие length: Продължителност @@ -59,16 +62,7 @@ bg: notes: Забележки track_id: Поток от лекции agreement: Съгласен(на) съм - workshop: - title: Заглавие - subtitle: Подзаглавие - length: Продължителност - language: Език - abstract: Резюме - description: Описание - notes: Забележки - track_id: Поток от уъркшопи - agreement: Съгласен(на) съм + user: Лектор errors: models: user: diff --git a/config/locales/en.yml b/config/locales/en.yml index 71ef1cf..ad0d7ca 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -32,6 +32,9 @@ en: one: Workshop other: Workshops track: track + event: + one: Suggestion + other: Suggestions attributes: user: email: E-mail @@ -49,7 +52,7 @@ en: biography: Short bography github: Github account twitter: Twitter account - lecture: + event: title: Title subtitle: Sub-title length: Length (should be between 40 and 45 minutes) @@ -59,16 +62,7 @@ en: notes: Notes track: Track agreement: I accept - workshop: - title: Title - subtitle: Sub-title - length: Length (should be between 30 and 120 minutes) - language: Language - abstract: Abstract (one paragraph) - description: Description (3-4 paragraphs) - notes: Notes - track: Track - agreement: I accept + user: Speaker errors: models: user: diff --git a/config/locales/management.bg.yml b/config/locales/management.bg.yml new file mode 100644 index 0000000..74757bc --- /dev/null +++ b/config/locales/management.bg.yml @@ -0,0 +1,5 @@ +bg: + are_you_sure: Сигурен ли си? + view: Преглед + home: Начало + more_about_user: "Повече информация за %{user}" \ No newline at end of file diff --git a/config/locales/management.en.yml b/config/locales/management.en.yml new file mode 100644 index 0000000..3da14eb --- /dev/null +++ b/config/locales/management.en.yml @@ -0,0 +1,4 @@ +en: + are_you_sure: Are you sure? + view: View + home: Home \ No newline at end of file diff --git a/config/locales/views.bg.yml b/config/locales/views.bg.yml index 598f2c7..8484f44 100644 --- a/config/locales/views.bg.yml +++ b/config/locales/views.bg.yml @@ -66,3 +66,6 @@ bg: logout: Изход of_motto: да споделим свободата + + meta_data: "Език: %{language}, поток: „%{track}“, продължителност: %{length} мин." + suggestion_and_speaker_count: "%{suggestions} предложения от %{speakers} лектори" \ No newline at end of file diff --git a/config/locales/views.en.yml b/config/locales/views.en.yml index 51a15af..2360cb9 100644 --- a/config/locales/views.en.yml +++ b/config/locales/views.en.yml @@ -65,3 +65,5 @@ en: logout: Logout of_motto: share the freedom + meta_data: "Language: %{language}, track: \"%{track}\", length: %{length} min." + suggestion_and_speaker_count: "%{suggestions} suggestions by %{speakers} speakers" \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index 13558cd..3057924 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -4,6 +4,18 @@ Rails.application.routes.draw do devise_for :users, controllers: {registrations: 'registrations', sessions: 'sessions'} + namespace :management do + get '/', to: 'events#index' + + resources :users do + member do + post 'toggle_admin' + end + end + + resources :events + end + root 'home#index' # The priority is based upon order of creation: first created -> highest priority. # See how all your routes lay out with "rake routes". diff --git a/lib/tasks/backup.rake b/lib/tasks/backup.rake new file mode 100644 index 0000000..2e67d87 --- /dev/null +++ b/lib/tasks/backup.rake @@ -0,0 +1,14 @@ +# Copyright Dimitar Dimitrov, 2011 + +desc "Generates an SQL dump of the production database in the destination path provided as an argument." +task :backup, [:destination] => :environment do |t, args| + conf = ActiveRecord::Base.connection.instance_variable_get :@config + cmd = "PGPASSWORD=#{conf[:password]} pg_dump -U #{conf[:username]} --inserts #{conf[:database]} -p #{conf[:port]} -h #{conf[:host]} > #{args.destination}" + silent = Rake.application.options.silent + puts "Backing up '#{conf[:database]}' into: #{args.destination}" unless silent + if system(cmd) + puts 'Backup completed.' unless silent + else + puts "Backup failed!\nCommand exit status: #{$?}\nCommand was: #{cmd}" + end +end