diff --git a/.gitignore b/.gitignore index e21d1c2..a5f8f70 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,4 @@ /db/test.sqlite3 /coverage/ /spring-1000/ +*~ \ No newline at end of file diff --git a/.rspec b/.rspec new file mode 100644 index 0000000..c99d2e7 --- /dev/null +++ b/.rspec @@ -0,0 +1 @@ +--require spec_helper diff --git a/.travis.yml b/.travis.yml index a9c9912..8e01ff0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,20 @@ +env: + global: + - CC_TEST_REPORTER_ID=7aa7f481fab6b43c98fd0c009f4bea7803b8578b528751ee4aa7d6db69ba5799 + - GIT_COMMITTED_AT=$(if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then git log -1 --pretty=format:%ct; else git log -1 --skip 1 --pretty=format:%ct; fi) language: ruby rvm: - - 2.2.2 # may need to update this - + - 2.4.1 before_script: - - psql -c "CREATE USER sfewb WITH PASSWORD 'cs169';" -U postgres - - bundle exec rake db:migrate RAILS_ENV=test -notifications: - email: false - + - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter + - chmod +x ./cc-test-reporter +script: + - rake db:migrate + - bundle exec rspec +# Preferably you will run test-reporter on branch update events. But +# if you setup travis to build PR updates only, you don't need to run +# the line below + - if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT; fi +# In the case where travis is setup to build PR updates only, +# uncomment the line below +# - ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT \ No newline at end of file diff --git a/Gemfile b/Gemfile index 5dd2f6f..ead4919 100644 --- a/Gemfile +++ b/Gemfile @@ -1,50 +1,57 @@ source 'https://rubygems.org' -#ruby '2.2.2' +ruby '2.4.1' # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' -gem 'rails', '4.2.5' +gem 'rails', '4.2.9' gem 'sprockets-rails', :require => 'sprockets/railtie' # Boostrap for styling -gem 'bootstrap', '~> 4.0.0.alpha4' +gem 'bootstrap' # Use SCSS for stylesheets -gem 'sass-rails', '~> 5.0' +gem 'sass-rails' # Use Uglifier as compressor for JavaScript assets -gem 'uglifier', '>= 1.3.0' +gem 'uglifier' # Use CoffeeScript for .coffee assets and views -gem 'coffee-rails', '~> 4.1.0' +gem 'coffee-rails' gem 'jquery-rails' gem 'jquery-ui-rails' gem 'bootstrap-datepicker-rails' -gem "paperclip", "~>4.2" +gem "paperclip" gem 'rails4-autocomplete' -gem 'language_list', '~> 1.1' +gem 'language_list' gem 'turbolinks' gem 'ransack' -gem 'jbuilder', '~> 2.0' -gem 'sdoc', '~> 0.4.0', group: :doc +gem 'jbuilder' +gem 'sdoc' # , '~> 0.4.0', group: :doc gem 'jquery-turbolinks' -gem 'bcrypt', '~> 3.1.7' -gem 'cancancan', '~> 1.10' +gem 'bcrypt' +gem 'cancancan' gem 'simple_form' gem 'devise' -gem 'rails-assets-tether', '>= 1.1.0' +gem 'rails-assets-tether' gem 'kaminari' -gem 'rails_admin', '~> 1.0' +gem 'rails_admin' +gem 'json' +gem 'rake' # , '10.4.2' +gem 'faker' +gem 'factory_girl_rails' group :development, :test do gem 'sqlite3' gem 'byebug' gem 'rspec-rails' gem 'test-unit' + gem 'guard-rspec' end group :development do # Access an IRB console on exception pages or by using <%= console %> in views - gem 'web-console', '~> 2.0' + gem 'web-console' # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring gem 'spring' + gem 'spring-commands-rspec' + gem 'spring-commands-cucumber' end # Setup Cucumber, RSpec, autotest support diff --git a/Gemfile.lock b/Gemfile.lock index 5232588..426f9f3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,68 +1,66 @@ GEM remote: https://rubygems.org/ specs: - ZenTest (4.11.0) + ZenTest (4.11.1) abstract_type (0.0.7) - actionmailer (4.2.5) - actionpack (= 4.2.5) - actionview (= 4.2.5) - activejob (= 4.2.5) + actionmailer (4.2.9) + actionpack (= 4.2.9) + actionview (= 4.2.9) + activejob (= 4.2.9) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 1.0, >= 1.0.5) - actionpack (4.2.5) - actionview (= 4.2.5) - activesupport (= 4.2.5) + actionpack (4.2.9) + actionview (= 4.2.9) + activesupport (= 4.2.9) rack (~> 1.6) rack-test (~> 0.6.2) rails-dom-testing (~> 1.0, >= 1.0.5) rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionview (4.2.5) - activesupport (= 4.2.5) + actionview (4.2.9) + activesupport (= 4.2.9) builder (~> 3.1) erubis (~> 2.7.0) rails-dom-testing (~> 1.0, >= 1.0.5) - rails-html-sanitizer (~> 1.0, >= 1.0.2) - activejob (4.2.5) - activesupport (= 4.2.5) + rails-html-sanitizer (~> 1.0, >= 1.0.3) + activejob (4.2.9) + activesupport (= 4.2.9) globalid (>= 0.3.0) - activemodel (4.2.5) - activesupport (= 4.2.5) + activemodel (4.2.9) + activesupport (= 4.2.9) builder (~> 3.1) - activerecord (4.2.5) - activemodel (= 4.2.5) - activesupport (= 4.2.5) + activerecord (4.2.9) + activemodel (= 4.2.9) + activesupport (= 4.2.9) arel (~> 6.0) - activesupport (4.2.5) + activesupport (4.2.9) i18n (~> 0.7) - json (~> 1.7, >= 1.7.7) minitest (~> 5.1) thread_safe (~> 0.3, >= 0.3.4) tzinfo (~> 1.1) adamantium (0.2.0) ice_nine (~> 0.11.0) memoizable (~> 0.4.0) - addressable (2.4.0) - arel (6.0.3) + addressable (2.5.1) + public_suffix (~> 2.0, >= 2.0.2) + arel (6.0.4) arrayfields (4.9.2) - ast (2.2.0) - autoprefixer-rails (6.5.1) + ast (2.3.0) + autoprefixer-rails (7.1.2.2) execjs autotest-rails (4.2.1) ZenTest (~> 4.5) bcrypt (3.1.11) - binding_of_caller (0.7.2) - debug_inspector (>= 0.0.1) - bootstrap (4.0.0.alpha4) + bootstrap (4.0.0.alpha6) autoprefixer-rails (>= 6.0.3) sass (>= 3.4.19) bootstrap-datepicker-rails (1.6.4.1) railties (>= 3.0) - builder (3.2.2) - byebug (8.2.2) - cancancan (1.15.0) + builder (3.2.3) + byebug (9.0.6) + cancancan (2.0.0) cane (2.6.2) parallel - capybara (2.6.2) + capybara (2.14.4) addressable mime-types (>= 1.16) nokogiri (>= 1.3.3) @@ -78,85 +76,109 @@ GEM rest-client (>= 1.6.0) ruby_parser (~> 3.0) sexp_processor (~> 4.1) - climate_control (0.0.3) - activesupport (>= 3.0) + climate_control (0.2.0) cocaine (0.5.8) climate_control (>= 0.0.3, < 1.0) - code_analyzer (0.4.5) + code_analyzer (0.4.7) sexp_processor code_metrics (0.1.3) coderay (1.1.1) - coffee-rails (4.1.1) + coffee-rails (4.2.2) coffee-script (>= 2.2.0) - railties (>= 4.0.0, < 5.1.x) + railties (>= 4.0.0) coffee-script (2.4.1) coffee-script-source execjs - coffee-script-source (1.10.0) - colored (1.2) + coffee-script-source (1.12.2) concord (0.1.5) adamantium (~> 0.2.0) equalizer (~> 0.0.9) - concurrent-ruby (1.0.0) - cucumber (2.3.2) + concurrent-ruby (1.0.5) + cucumber (2.4.0) builder (>= 2.1.2) - cucumber-core (~> 1.4.0) + cucumber-core (~> 1.5.0) cucumber-wire (~> 0.0.1) diff-lcs (>= 1.1.3) - gherkin (~> 3.2.0) + gherkin (~> 4.0) multi_json (>= 1.7.5, < 2.0) multi_test (>= 0.1.2) - cucumber-core (1.4.0) - gherkin (~> 3.2.0) - cucumber-rails (1.4.3) + cucumber-core (1.5.0) + gherkin (~> 4.0) + cucumber-rails (1.5.0) capybara (>= 1.1.2, < 3) - cucumber (>= 1.3.8, < 3) - mime-types (>= 1.16, < 4) + cucumber (>= 1.3.8, < 4) + mime-types (>= 1.17, < 4) nokogiri (~> 1.5) - railties (>= 3, < 5) + railties (>= 4, < 5.2) cucumber-rails-training-wheels (1.0.0) cucumber-rails (>= 1.1.1) cucumber-wire (0.0.1) - database_cleaner (1.5.1) - debug_inspector (0.0.2) - devise (4.2.0) + database_cleaner (1.6.1) + debug_inspector (0.0.3) + devise (4.3.0) bcrypt (~> 3.0) orm_adapter (~> 0.1) - railties (>= 4.1.0, < 5.1) + railties (>= 4.1.0, < 5.2) responders warden (~> 1.2.3) - diff-lcs (1.2.5) + diff-lcs (1.3) docile (1.1.5) - domain_name (0.5.20160128) + domain_name (0.5.20170404) unf (>= 0.0.5, < 1.0.0) equalizer (0.0.11) erubis (2.7.0) - execjs (2.6.0) - fattr (2.2.2) - flay (2.7.0) + execjs (2.7.0) + factory_girl (4.8.0) + activesupport (>= 3.0.0) + factory_girl_rails (4.8.0) + factory_girl (~> 4.8.0) + railties (>= 3.0.0) + faker (1.8.3) + i18n (~> 0.5) + fattr (2.3.0) + ffi (1.9.18) + flay (2.9.0) erubis (~> 2.7.0) + path_expander (~> 1.0) ruby_parser (~> 3.0) sexp_processor (~> 4.0) - flog (4.3.2) + flog (4.6.1) + path_expander (~> 1.0) ruby_parser (~> 3.1, > 3.1.0) - sexp_processor (~> 4.4) - font-awesome-rails (4.6.3.1) - railties (>= 3.2, < 5.1) - gherkin (3.2.0) - globalid (0.3.6) - activesupport (>= 4.1.0) - haml (4.0.7) + sexp_processor (~> 4.8) + font-awesome-rails (4.7.0.2) + railties (>= 3.2, < 5.2) + formatador (0.2.5) + gherkin (4.1.3) + globalid (0.4.0) + activesupport (>= 4.2.0) + guard (2.14.1) + formatador (>= 0.2.4) + listen (>= 2.7, < 4.0) + lumberjack (~> 1.0) + nenv (~> 0.1) + notiffany (~> 0.0) + pry (>= 0.9.12) + shellany (~> 0.0) + thor (>= 0.18.1) + guard-compat (1.2.1) + guard-rspec (4.7.3) + guard (~> 2.1) + guard-compat (~> 1.1) + rspec (>= 2.99.0, < 4.0) + haml (5.0.1) + temple (>= 0.8.0) tilt hirb (0.7.3) - http-cookie (1.0.2) + http-cookie (1.0.3) domain_name (~> 0.5) - i18n (0.7.0) + i18n (0.8.6) ice_nine (0.11.2) - jbuilder (2.4.1) - activesupport (>= 3.0.0, < 5.1) - multi_json (~> 1.2) - jquery-rails (4.1.0) - rails-dom-testing (~> 1.0) + jbuilder (2.7.0) + activesupport (>= 4.2.0) + multi_json (>= 1.2) + jquery-rails (4.3.1) + rails-dom-testing (>= 1, < 3) railties (>= 4.2.0) thor (>= 0.14, < 2.0) jquery-turbolinks (2.1.0) @@ -164,26 +186,41 @@ GEM turbolinks jquery-ui-rails (5.0.5) railties (>= 3.2.16) - json (1.8.3) - json_pure (1.8.3) - kaminari (0.17.0) - actionpack (>= 3.0.0) - activesupport (>= 3.0.0) - language_list (1.1.0) + json (1.8.6) + json_pure (2.1.0) + kaminari (1.0.1) + activesupport (>= 4.1.0) + kaminari-actionview (= 1.0.1) + kaminari-activerecord (= 1.0.1) + kaminari-core (= 1.0.1) + kaminari-actionview (1.0.1) + actionview + kaminari-core (= 1.0.1) + kaminari-activerecord (1.0.1) + activerecord + kaminari-core (= 1.0.1) + kaminari-core (1.0.1) + language_list (1.2.1) launchy (2.4.3) addressable (~> 2.3) + listen (3.1.5) + rb-fsevent (~> 0.9, >= 0.9.4) + rb-inotify (~> 0.9, >= 0.9.7) + ruby_dep (~> 1.2) loofah (2.0.3) nokogiri (>= 1.5.9) - mail (2.6.3) - mime-types (>= 1.16, < 3) - main (6.2.0) - arrayfields (>= 4.7.4) - chronic (>= 0.6.2) - fattr (>= 2.2.0) - map (>= 6.1.0) + lumberjack (1.0.12) + mail (2.6.6) + mime-types (>= 1.16, < 4) + main (6.2.2) + arrayfields (~> 4.7, >= 4.7.4) + chronic (~> 0.6, >= 0.6.2) + fattr (~> 2.2, >= 2.2.0) + map (~> 6.1, >= 6.1.0) map (6.6.0) memoizable (0.4.2) thread_safe (~> 0.3, >= 0.3.1) + method_source (0.8.2) metric_fu (4.12.0) cane (~> 2.5, >= 2.5.2) churn (~> 0.0.35) @@ -199,54 +236,66 @@ GEM reek (>= 1.3.4, < 3.0) roodi (~> 3.1) metric_fu-Saikuro (1.1.3) - mime-types (2.99.1) - mimemagic (0.3.0) - mini_portile2 (2.0.0) - minitest (5.8.4) - multi_json (1.11.2) + mime-types (3.1) + mime-types-data (~> 3.2015) + mime-types-data (3.2016.0521) + mimemagic (0.3.2) + mini_portile2 (2.2.0) + minitest (5.10.2) + multi_json (1.12.1) multi_test (0.1.2) + nenv (0.3.0) nested_form (0.3.2) netrc (0.11.0) - nokogiri (1.6.7.2) - mini_portile2 (~> 2.0.0.rc2) + nokogiri (1.8.0) + mini_portile2 (~> 2.2.0) + notiffany (0.1.1) + nenv (~> 0.1) + shellany (~> 0.0) orm_adapter (0.5.0) - paperclip (4.3.7) - activemodel (>= 3.2.0) - activesupport (>= 3.2.0) + paperclip (5.1.0) + activemodel (>= 4.2.0) + activesupport (>= 4.2.0) cocaine (~> 0.5.5) mime-types - mimemagic (= 0.3.0) - parallel (1.6.1) - parser (2.3.0.6) + mimemagic (~> 0.3.0) + parallel (1.11.2) + parser (2.4.0.0) ast (~> 2.2) - pg (0.18.4) + path_expander (1.0.2) + pg (0.21.0) polyamorous (1.3.1) activerecord (>= 3.0) - power_assert (0.2.6) - procto (0.0.2) - rack (1.6.4) + power_assert (1.0.2) + procto (0.0.3) + pry (0.10.4) + coderay (~> 1.1.0) + method_source (~> 0.8.1) + slop (~> 3.4) + public_suffix (2.0.5) + rack (1.6.8) rack-pjax (1.0.0) nokogiri (~> 1.5) rack (>= 1.1) rack-test (0.6.3) rack (>= 1.0) - rails (4.2.5) - actionmailer (= 4.2.5) - actionpack (= 4.2.5) - actionview (= 4.2.5) - activejob (= 4.2.5) - activemodel (= 4.2.5) - activerecord (= 4.2.5) - activesupport (= 4.2.5) + rails (4.2.9) + actionmailer (= 4.2.9) + actionpack (= 4.2.9) + actionview (= 4.2.9) + activejob (= 4.2.9) + activemodel (= 4.2.9) + activerecord (= 4.2.9) + activesupport (= 4.2.9) bundler (>= 1.3.0, < 2.0) - railties (= 4.2.5) + railties (= 4.2.9) sprockets-rails rails-assets-tether (1.1.1) rails-deprecated_sanitizer (1.0.3) activesupport (>= 4.2.0.alpha) - rails-dom-testing (1.0.7) + rails-dom-testing (1.0.8) activesupport (>= 4.2.0.beta, < 5.0) - nokogiri (~> 1.6.0) + nokogiri (~> 1.6) rails-deprecated_sanitizer (>= 1.0.1) rails-html-sanitizer (1.0.3) loofah (~> 2.0) @@ -255,133 +304,154 @@ GEM rails_12factor (0.0.3) rails_serve_static_assets rails_stdout_logging - rails_admin (1.0.0) + rails_admin (1.2.0) builder (~> 3.1) coffee-rails (~> 4.0) font-awesome-rails (>= 3.0, < 5) - haml (~> 4.0) + haml (>= 4.0, < 6) jquery-rails (>= 3.0, < 5) jquery-ui-rails (~> 5.0) - kaminari (~> 0.14) + kaminari (>= 0.14, < 2.0) nested_form (~> 0.3) rack-pjax (>= 0.7) rails (>= 4.0, < 6) remotipart (~> 1.3) sass-rails (>= 4.0, < 6) - rails_best_practices (1.15.7) + rails_best_practices (1.18.1) activesupport code_analyzer (>= 0.4.3) - colored erubis i18n json require_all ruby-progressbar rails_serve_static_assets (0.0.5) - rails_stdout_logging (0.0.4) - railties (4.2.5) - actionpack (= 4.2.5) - activesupport (= 4.2.5) + rails_stdout_logging (0.0.5) + railties (4.2.9) + actionpack (= 4.2.9) + activesupport (= 4.2.9) rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) - rainbow (2.1.0) - rake (10.5.0) - ransack (1.8.2) + rainbow (2.2.2) + rake + rake (12.0.0) + ransack (1.8.3) actionpack (>= 3.0) activerecord (>= 3.0) activesupport (>= 3.0) i18n polyamorous (~> 1.3) - rdoc (4.2.2) - json (~> 1.4) + rb-fsevent (0.10.2) + rb-inotify (0.9.10) + ffi (>= 0.5.0, < 2) + rdoc (4.3.0) redcard (1.1.0) reek (2.2.1) parser (~> 2.2) rainbow (~> 2.0) unparser (~> 0.2.2) remotipart (1.3.1) - require_all (1.3.3) - responders (2.3.0) - railties (>= 4.2.0, < 5.1) - rest-client (1.8.0) + require_all (1.4.0) + responders (2.4.0) + actionpack (>= 4.2.0, < 5.3) + railties (>= 4.2.0, < 5.3) + rest-client (2.0.2) http-cookie (>= 1.0.2, < 2.0) - mime-types (>= 1.16, < 3.0) - netrc (~> 0.7) + mime-types (>= 1.16, < 4.0) + netrc (~> 0.8) roodi (3.3.1) ruby_parser (~> 3.2, >= 3.2.2) - rspec-core (2.14.8) - rspec-expectations (2.14.5) - diff-lcs (>= 1.1.3, < 2.0) - rspec-mocks (2.14.6) - rspec-rails (2.14.0) + rspec (3.6.0) + rspec-core (~> 3.6.0) + rspec-expectations (~> 3.6.0) + rspec-mocks (~> 3.6.0) + rspec-core (3.6.0) + rspec-support (~> 3.6.0) + rspec-expectations (3.6.0) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.6.0) + rspec-mocks (3.6.0) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.6.0) + rspec-rails (3.6.0) actionpack (>= 3.0) activesupport (>= 3.0) railties (>= 3.0) - rspec-core (~> 2.14.0) - rspec-expectations (~> 2.14.0) - rspec-mocks (~> 2.14.0) - ruby-progressbar (1.7.5) - ruby_parser (3.8.1) + rspec-core (~> 3.6.0) + rspec-expectations (~> 3.6.0) + rspec-mocks (~> 3.6.0) + rspec-support (~> 3.6.0) + rspec-support (3.6.0) + ruby-progressbar (1.8.1) + ruby_dep (1.5.0) + ruby_parser (3.9.0) sexp_processor (~> 4.1) - sass (3.4.21) - sass-rails (5.0.4) - railties (>= 4.0.0, < 5.0) + sass (3.4.25) + sass-rails (5.0.6) + railties (>= 4.0.0, < 6) sass (~> 3.1) sprockets (>= 2.8, < 4.0) sprockets-rails (>= 2.0, < 4.0) tilt (>= 1.1, < 3) - sdoc (0.4.1) + sdoc (0.4.2) json (~> 1.7, >= 1.7.7) rdoc (~> 4.0) - sexp_processor (4.7.0) - simple_form (3.3.1) - actionpack (> 4, < 5.1) - activemodel (> 4, < 5.1) - simplecov (0.11.2) + sexp_processor (4.9.0) + shellany (0.0.1) + simple_form (3.5.0) + actionpack (> 4, < 5.2) + activemodel (> 4, < 5.2) + simplecov (0.14.1) docile (~> 1.1.0) - json (~> 1.8) + json (>= 1.8, < 3) simplecov-html (~> 0.10.0) - simplecov-html (0.10.0) - spring (1.6.3) - sprockets (3.5.2) + simplecov-html (0.10.1) + slop (3.6.0) + spring (2.0.2) + activesupport (>= 4.2) + spring-commands-cucumber (1.0.1) + spring (>= 0.9.1) + spring-commands-rspec (1.0.4) + spring (>= 0.9.1) + sprockets (3.7.1) concurrent-ruby (~> 1.0) rack (> 1, < 3) - sprockets-rails (3.0.1) + sprockets-rails (3.2.0) actionpack (>= 4.0) activesupport (>= 4.0) sprockets (>= 3.0.0) - sqlite3 (1.3.11) - test-unit (3.1.5) + sqlite3 (1.3.13) + temple (0.8.0) + test-unit (3.2.5) power_assert - thor (0.19.1) - thread_safe (0.3.5) - tilt (2.0.2) - turbolinks (2.5.3) - coffee-rails - tzinfo (1.2.2) + thor (0.19.4) + thread_safe (0.3.6) + tilt (2.0.7) + turbolinks (5.0.1) + turbolinks-source (~> 5) + turbolinks-source (5.0.3) + tzinfo (1.2.3) thread_safe (~> 0.1) - uglifier (2.7.2) - execjs (>= 0.3.0) - json (>= 1.8.0) + uglifier (3.2.0) + execjs (>= 0.3.0, < 3) unf (0.1.4) unf_ext - unf_ext (0.0.7.2) - unparser (0.2.5) + unf_ext (0.0.7.4) + unparser (0.2.6) abstract_type (~> 0.0.7) adamantium (~> 0.2.0) concord (~> 0.1.5) - diff-lcs (~> 1.2.5) + diff-lcs (~> 1.3) equalizer (~> 0.0.9) - parser (~> 2.3.0) + parser (>= 2.3.1.2, < 2.5) procto (~> 0.0.2) - warden (1.2.6) + warden (1.2.7) rack (>= 1.0) - web-console (2.3.0) - activemodel (>= 4.0) - binding_of_caller (>= 0.7.2) - railties (>= 4.0) - sprockets-rails (>= 2.0, < 4.0) - xpath (2.0.0) + web-console (3.3.0) + activemodel (>= 4.2) + debug_inspector + railties (>= 4.2) + xpath (2.1.0) nokogiri (~> 1.3) PLATFORMS @@ -389,44 +459,54 @@ PLATFORMS DEPENDENCIES autotest-rails - bcrypt (~> 3.1.7) - bootstrap (~> 4.0.0.alpha4) + bcrypt + bootstrap bootstrap-datepicker-rails byebug - cancancan (~> 1.10) - coffee-rails (~> 4.1.0) + cancancan + coffee-rails cucumber-rails cucumber-rails-training-wheels database_cleaner devise + factory_girl_rails + faker + guard-rspec haml - jbuilder (~> 2.0) + jbuilder jquery-rails jquery-turbolinks jquery-ui-rails + json kaminari - language_list (~> 1.1) + language_list metric_fu - paperclip (~> 4.2) + paperclip pg - rails (= 4.2.5) - rails-assets-tether (>= 1.1.0) + rails (= 4.2.9) + rails-assets-tether rails4-autocomplete rails_12factor - rails_admin (~> 1.0) + rails_admin + rake ransack rspec-rails - sass-rails (~> 5.0) - sdoc (~> 0.4.0) + sass-rails + sdoc simple_form simplecov spring + spring-commands-cucumber + spring-commands-rspec sprockets-rails sqlite3 test-unit turbolinks - uglifier (>= 1.3.0) - web-console (~> 2.0) + uglifier + web-console + +RUBY VERSION + ruby 2.4.1p111 BUNDLED WITH - 1.13.6 + 1.15.2 diff --git a/Guardfile b/Guardfile new file mode 100644 index 0000000..98af924 --- /dev/null +++ b/Guardfile @@ -0,0 +1,76 @@ +# A sample Guardfile +# More info at https://github.com/guard/guard#readme + +## Uncomment and set this to only include directories you want to watch +# directories %w(app lib config test spec features) \ +# .select{|d| Dir.exists?(d) ? d : UI.warning("Directory #{d} does not exist")} + +## Note: if you are using the `directories` clause above and you are not +## watching the project directory ('.'), then you will want to move +## the Guardfile to a watched dir and symlink it back, e.g. +# +# $ mkdir config +# $ mv Guardfile config/ +# $ ln -s config/Guardfile . +# +# and, you'll have to watch "config/Guardfile" instead of "Guardfile" + +# Note: The cmd option is now required due to the increasing number of ways +# rspec may be run, below are examples of the most common uses. +# * bundler: 'bundle exec rspec' +# * bundler binstubs: 'bin/rspec' +# * spring: 'bin/rspec' (This will use spring if running and you have +# installed the spring binstubs per the docs) +# * zeus: 'zeus rspec' (requires the server to be started separately) +# * 'just' rspec: 'rspec' + +guard :rspec, cmd: "bundle exec spring rspec" do + require "guard/rspec/dsl" + dsl = Guard::RSpec::Dsl.new(self) + + # Feel free to open issues for suggestions and improvements + + # RSpec files + rspec = dsl.rspec + watch(rspec.spec_helper) { rspec.spec_dir } + watch(rspec.spec_support) { rspec.spec_dir } + watch(rspec.spec_files) + + # Ruby files + ruby = dsl.ruby + dsl.watch_spec_files_for(ruby.lib_files) + + # Rails files + rails = dsl.rails(view_extensions: %w(erb haml slim)) + dsl.watch_spec_files_for(rails.app_files) + dsl.watch_spec_files_for(rails.views) + + watch(rails.controllers) do |m| + [ + rspec.spec.call("routing/#{m[1]}_routing"), + rspec.spec.call("controllers/#{m[1]}_controller"), + rspec.spec.call("acceptance/#{m[1]}") + ] + end + + # Rails config changes + watch(rails.spec_helper) { rspec.spec_dir } + watch(rails.routes) { "#{rspec.spec_dir}/routing" } + watch(rails.app_controller) { "#{rspec.spec_dir}/controllers" } + + # Capybara features specs + watch(rails.view_dirs) { |m| rspec.spec.call("features/#{m[1]}") } + watch(rails.layouts) { |m| rspec.spec.call("features/#{m[1]}") } + + # Turnip features and steps + watch(%r{^spec/acceptance/(.+)\.feature$}) + watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) do |m| + Dir[File.join("**/#{m[1]}.feature")][0] || "spec/acceptance" + end + + # User & Project watching + watch(%r{^app/models/.+\.rb}) { "#{rspec.spec_dir}/association_spec.rb" } + + + +end diff --git a/MIT License b/LICENSE similarity index 100% rename from MIT License rename to LICENSE diff --git a/Procfile b/Procfile new file mode 100644 index 0000000..8352e82 --- /dev/null +++ b/Procfile @@ -0,0 +1,2 @@ +web: rake db:migrate +web: bundle exec rackup config.ru -p $PORT diff --git a/README.md b/README.md index e2ecb37..365c197 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,17 @@ -[![Code Climate](https://codeclimate.com/github/mark-craig/engineerswithoutborders/badges/gpa.svg)](https://codeclimate.com/github/mark-craig/engineerswithoutborders) -[![Build Status](https://travis-ci.org/mark-craig/engineerswithoutborders.svg?branch=master)](https://travis-ci.org/mark-craig/engineerswithoutborders) +[![Code Climate](https://codeclimate.com/github/tbrachmann/engineerswithoutborders/badges/gpa.svg)](https://codeclimate.com/github/tbrachmann/engineerswithoutborders) +[![Test Coverage](https://codeclimate.com/github/tbrachmann/engineerswithoutborders/badges/coverage.svg)](https://codeclimate.com/github/tbrachmann/engineerswithoutborders/coverage) +[![Build Status](https://travis-ci.org/tbrachmann/engineerswithoutborders.svg?branch=master)](https://travis-ci.org/tbrachmann/engineerswithoutborders) # Engineer Without Borders' Volunteer System -CS 169 Fall 2016. -This project is based on the work of the previous group from Spring 2016. -https://ancient-river-67510.herokuapp.com/ +CS 169 Summer 2017. +This project is based on the work of the previous groups from Spring 2016 and Fall 2016. -[Pivotal Tracker](https://www.pivotaltracker.com/projects/1887169/memberships?page=1) +[Heroku App](https://morning-earth-50247.herokuapp.com/) -[Client Intro](https://youtu.be/FlaDXKL6-yk) +[Pivotal Tracker](https://www.pivotaltracker.com/n/projects/2071107) -[ScreenCast](https://youtu.be/71nNvWm0Itk) +[Client Intro](https://www.youtube.com/watch?v=vTYoWUjP5xo&feature=youtu.be) Project Summary: diff --git a/app/assets/images/main1.png b/app/assets/images/main1.png new file mode 100644 index 0000000..85a3016 Binary files /dev/null and b/app/assets/images/main1.png differ diff --git a/app/assets/images/main2.png b/app/assets/images/main2.png new file mode 100644 index 0000000..73c7ae3 Binary files /dev/null and b/app/assets/images/main2.png differ diff --git a/app/assets/images/main3.png b/app/assets/images/main3.png new file mode 100644 index 0000000..7996ea8 Binary files /dev/null and b/app/assets/images/main3.png differ diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index b4ba1f9..dc8bc3c 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -25,4 +25,6 @@ // $( function() { // $( "#project_start_date" ).datepicker(); -// } ); \ No newline at end of file +// } ); + +//= require filter_users.js \ No newline at end of file diff --git a/app/assets/javascripts/filter_users.js b/app/assets/javascripts/filter_users.js new file mode 100644 index 0000000..50b8b4f --- /dev/null +++ b/app/assets/javascripts/filter_users.js @@ -0,0 +1,75 @@ +var checked_skills = []; +var users_to_skills; + +var checked_certs=[]; +var users_to_certs; + +var all_checked_boxes=[]; + +$(document).ready(function(){ + $.ajax({type: "GET", + url: "/users", + error: function(e) { + console.log("failed!"); + return null + }, + success: function(data) { + users_to_skills = data['skills']; + users_to_certs = data['certs']; + } + }); +}); + +function change(id_class) { + var id = id_class.split('_')[0]; + var klass = id_class.split('_')[1]; + var checkbox = $('#' + id_class); + switch(klass) { + case 'skill': + processBoxes(checkbox, checked_skills, id); + break; + case 'cert': + processBoxes(checkbox, checked_certs, id); + break; + default: + } + processBoxes(checkbox, all_checked_boxes, id); + filterUsers(); +} + + +function filterUsers() { + var user_rows = $("div[klass='user_row']"); + for (i=0; i < user_rows.length; i++) { + shouldShow(parseInt(user_rows[i].id)); + } +} + +//returns true if arr1 includes any element in arr2 +function includesAll(arr1, arr2) { + arr1.forEach(function (b, index, arr1) { + arr1[index] = b.replace(/[^A-Z0-9]/ig, ''); + }); + return arr2.every(function (a) { + return arr1.indexOf(a) >= 0; + }); +} + +function shouldShow(user_id) { + if (all_checked_boxes.length === 0 || (includesAll(users_to_skills[user_id], checked_skills) && includesAll(users_to_certs[user_id], checked_certs))) { + $('#' + user_id).show(); + $('#' + user_id).next("hr").show() + } else { + $('#' + user_id).hide(); + $('#' + user_id).next("hr").hide() + } +} + +function processBoxes(new_check, already_checked, id) { + if (new_check.is(':checked')) { + already_checked.push(id); + } else if (!new_check.is(':checked')) { + already_checked.splice(already_checked.indexOf(id), 1); + } + +} diff --git a/app/assets/stylesheets/.application.scss.swp b/app/assets/stylesheets/.application.scss.swp new file mode 100644 index 0000000..175b8f8 Binary files /dev/null and b/app/assets/stylesheets/.application.scss.swp differ diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 125d593..c5ead46 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -1,7 +1,9 @@ -@import "bootstrap"; -body { - padding-top: 70px; } + +html, body { + height: 100%; + min-height: 100% + } /* * This is a manifest file that'll be compiled into application.css, which will include all the files * listed below. @@ -21,10 +23,13 @@ body { */ h1, h2, h3, h4, h5, h6 { - font-family: 'Corben', Georgia, Times, serif; + font-family: "proxima-nova"; + font-weight: bold; } -p, div { - font-family: 'Nobile', Helvetica, Arial, sans-serif; +p, div, strong { + font-family: "proxima-nova", Helvetica, Arial, sans-serif; + font-size: 18px; + font-weight: bold; } #projects .calendar { @@ -72,4 +77,242 @@ p, div { #projects ul { font-size: 11px; padding-left: 20px; +} + +.temp { + background-image: url('/assets/ewb.jpg'); + background-repeat: no-repeat; + background-size: contain; + background-position: center center; + width: 100%; + height: 90%; + } +.fill { + height: 100%; + min-height: 100%; + } +.main { + background: #FFFFFF; + position: relative; + z-index: 3; +} +.main-raised { + margin: -60px 30px 0px; + border-radius: 6px; + /* box-shadow: 0 16px 24px 2px rgba(0, 0, 0, 0.14), 0 6px 30px 5px rgba(0, 0, 0, 0.12), 0 8px 10px -5px rgba(0, 0, 0, 0.2); */ +} +.section { + background-position: center center; + background-size: cover; + padding: 70px 0; +} +.card { + border-radius: 6px; + box-shadow: 0 16px 24px 2px #333, 0 6px 30px 5px rgba(0, 0, 0, 0.12), 0 8px 10px -5px rgba(0, 0, 0, 0.2); + display: inline-block; + position: relative; + width: 100%; + margin-bottom: 30px; + color: rgba(0,0,0, 0.87); + background: #fff; + padding: 7%; +} +.card-title { + font-weight: 700; + font-family: nanum-barun-gothic-regular; +} +.card-image { + margin: 0; + border-radius: 3px; + height: 60%; + position: relative; + overflow: hidden; + box-shadow: 0 16px 38px -12px rgba(0, 0, 0, 0.56), 0 4px 25px 0px rgba(0, 0, 0, 0.12), 0 8px 10px -5px rgba(0, 0, 0, 0.2); +} +.btn-color { + background-color: #3D3C40; + color: #FFFFFF; +} +.bg-color { + background-color: #E5E5E5; +} +.nav-shadow{ + box-shadow: 0 10px 20px -12px rgba(0, 0, 0, 0.42), 0 3px 20px 0px rgba(0, 0, 0, 0.12), 0 8px 10px -5px rgba(0, 0, 0, 0.2); +} +.btn-round{ + border-radius: 300px; + background-color: transparent; + -webkit-font-smoothing: subpixel-antialiased; + border: 2px solid #000; + color: #000; + text-transform: uppercase; + text-decoration: none; + letter-spacing: 1px; + font-weight: 400; + font-style: normal; + margin-left: 1em; + padding: 1em 1.5em !important; + transition: background-color .1s 0s ease-in-out, color .1s 0s ease-in-out +} +.btn-round:hover { + background-color: #000000; + color: white; + +} + +.btn-round:active { + background-color: #121721; + box-shadow: 0 5px #666; + transform: translateY(4px); +} + +.row .col-md-7 { + left: 50px; +} + +// .search-checkbox { +// position: relative; +// left: 25px; +// top: 50px; +// } + +#user-checkbox { + position: relative; + left: 35px; + top: 40px; + // margin-bottom: 50px; +} + +.search-checkbox { + #search-submit { + position:absolute; + width: 20%; + height: 20%; + top: 13%; + right: 5%; + font-size: 20px; + font-weight: bold; + } + + + box-shadow: 0 1px #666; + transform: translateY(1px); +} + +.nav-item { + font-family: 'Open Sans', Helvetica, sans-serif; + text-transform: uppercase; + font-size: 13px; +} +.filter { + background-color: rgba(0, 0, 0, 0.5); +} +.multi_bg_example { + width: 100%; + height: 400px; + background-image: url(main1.png), url(main2.png), linear-gradient(to right, rgba(30, 75, 115, 1), rgba(255, 255, 255, 0)); + background-repeat: no-repeat, no-repeat, no-repeat; + background-position: bottom right, left, right; +} +.sqs-block-btn { + transition: .1s opacity linear; + -webkit-backface-visibility: hidden; + font-family: "proxima-nova", "Helvetica Neue", Helvetica, Arial, sans-serif; + text-transform: uppercase; + letter-spacing: 1px; + font-weight: 600; + font-style: normal; + font-size: 13px; + color: #fff; + border-color: #272727; + display: inline-block; + width: auto; + height: auto; + border-width: 0; + text-align: center; + text-decoration: none; + outline: none; + -webkit-appearance: none; + line-height: normal; + size: small; +} +.btn-mint { + background-color: #36b3a8; + padding: 21px 34px; +} +.btn-mint:hover { + background-color: #36b3a8; + background-repeat:no-repeat; + border: none; + cursor:pointer; + overflow: hidden; + outline:none; + color: white; + text-decoration: none; + filter: grayscale(30%); +} +.btn-black { + background-color: #000000; + padding: 12px 14px; +} +.btn-black:hover { + background-color: #000000; + background-repeat:no-repeat; + border: none; + cursor:pointer; + overflow: hidden; + outline:none; + color: white; + text-decoration: none; + filter: grayscale(90%); +} +.btn-black:active { + background-color: #000000; + box-shadow: 0 1px #666; + transform: translateY(1px); +} + +.background-img { + position: relative; + background-repeat: no-repeat; +} +.background-img::after { + content: ""; + background-image: url("https://umaine.edu/ewb/wp-content/uploads/sites/211/2016/05/ewb-usa-logo-color.jpg"); + opacity: 0.1; + top: 0; + left: 0; + bottom: 0; + right: 0; + position: absolute; + z-index: -1; + background-repeat: no-repeat; +} + +.form-control { + border: 0; + background-image: linear-gradient(#9c27b0, #9c27b0), linear-gradient(#D2D2D2, #D2D2D2); + background-size: 0 2px, 100% 1px; + background-repeat: no-repeat; + background-position: center bottom, center calc(100% - 1px); + background-color: transparent; + transition: background 0s ease-out; + float: none; + box-shadow: none; + border-radius: 0; + font-weight: 400; +} +.form-control { + color: #555; +} +.form-control:focus { + border: 0; + background-image: linear-gradient(#9c27b3, black), linear-gradient(black, black); + background-size: 0 2px, 100% 2px; + box-shadow: none; +} + +.user-qualities { + font-weight: normal; + font-size: 16px; } \ No newline at end of file diff --git a/app/assets/stylesheets/application_BACKUP_3303.scss b/app/assets/stylesheets/application_BACKUP_3303.scss new file mode 100644 index 0000000..95216f9 --- /dev/null +++ b/app/assets/stylesheets/application_BACKUP_3303.scss @@ -0,0 +1,307 @@ + + +html, body { + height: 100%; + min-height: 100% + } +/* + * This is a manifest file that'll be compiled into application.css, which will include all the files + * listed below. + * + * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, + * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path. + * + * You're free to add application-wide styles to this file and they'll appear at the top of the + * compiled file, but it's generally better to create a new file per style scope. + * + *= require jquery.ui.datepicker + *= require jquery-ui + *= require_self + *= require_tree . + *= require jquery-ui + *= require bootstrap-datepicker + */ + + h1, h2, h3, h4, h5, h6 { + font-family: "proxima-nova"; + font-weight: bold; +} +p, div, strong { + font-family: "proxima-nova", Helvetica, Arial, sans-serif; + font-size: 18px; + font-weight: bold; +} + + #projects .calendar { + border-collapse: collapse; + width: 100%; + + td, th { + font-family: "Lucida Grande", arial, helvetica, sans-serif; + font-size: 10px; + padding: 6px; + border: 1px solid #999; + } + + th { + + color: #666; + text-align: center; + width: 14.2857142857143%; + } + + td { + background: #FFF; + color: #777; + height: 80px; + vertical-align: top; + font-size: 16px; + } + + .notmonth, .notmonth a { color: #CCC; } + .today { background-color: #D7F2FF; } +} + +#projects #month { + margin: 0; + padding-bottom: 10px; + text-align: center; + font-size: 22px; + a { + text-decoration: none; + padding: 0 10px; + color: #999; + } +} + +#projects ul { + font-size: 11px; + padding-left: 20px; +} + +.temp { + background-image: url('/assets/ewb.jpg'); + background-repeat: no-repeat; + background-size: contain; + background-position: center center; + width: 100%; + height: 90%; + } +.fill { + height: 100%; + min-height: 100%; + } +.main { + background: #FFFFFF; + position: relative; + z-index: 3; +} +.main-raised { + margin: -60px 30px 0px; + border-radius: 6px; + /* box-shadow: 0 16px 24px 2px rgba(0, 0, 0, 0.14), 0 6px 30px 5px rgba(0, 0, 0, 0.12), 0 8px 10px -5px rgba(0, 0, 0, 0.2); */ +} +.section { + background-position: center center; + background-size: cover; + padding: 70px 0; +} +.card { + border-radius: 6px; + box-shadow: 0 16px 24px 2px #333, 0 6px 30px 5px rgba(0, 0, 0, 0.12), 0 8px 10px -5px rgba(0, 0, 0, 0.2); + display: inline-block; + position: relative; + width: 100%; + margin-bottom: 30px; + color: rgba(0,0,0, 0.87); + background: #fff; + padding: 7%; +} +.card-title { + font-weight: 700; + font-family: nanum-barun-gothic-regular; +} +.card-image { + margin: 0; + border-radius: 3px; + height: 60%; + position: relative; + overflow: hidden; + box-shadow: 0 16px 38px -12px rgba(0, 0, 0, 0.56), 0 4px 25px 0px rgba(0, 0, 0, 0.12), 0 8px 10px -5px rgba(0, 0, 0, 0.2); +} +.btn-color { + background-color: #3D3C40; + color: #FFFFFF; +} +.bg-color { + background-color: #E5E5E5; +} +.nav-shadow{ + box-shadow: 0 10px 20px -12px rgba(0, 0, 0, 0.42), 0 3px 20px 0px rgba(0, 0, 0, 0.12), 0 8px 10px -5px rgba(0, 0, 0, 0.2); +} +.btn-round{ + border-radius: 300px; + background-color: transparent; + -webkit-font-smoothing: subpixel-antialiased; + border: 2px solid #000; + color: #000; + text-transform: uppercase; + text-decoration: none; + letter-spacing: 1px; + font-weight: 400; + font-style: normal; + margin-left: 1em; + padding: 1em 1.5em !important; + transition: background-color .1s 0s ease-in-out, color .1s 0s ease-in-out +} +.btn-round:hover { + background-color: #000000; + color: white; + +} + +.btn-round:active { + background-color: #121721; +<<<<<<< HEAD + box-shadow: 0 5px #666; + transform: translateY(4px); +} + +.row .col-md-7 { + left: 50px; +} + +// .search-checkbox { +// position: relative; +// left: 25px; +// top: 50px; +// } + +.search-checkbox { + #search-submit { + position:absolute; + width: 20%; + height: 20%; + top: 13%; + right: 5%; + font-size: 20px; + font-weight: bold; + } + +======= + box-shadow: 0 1px #666; + transform: translateY(1px); +} +.nav-item { + font-family: 'Open Sans', Helvetica, sans-serif; + text-transform: uppercase; + font-size: 13px; +} +.filter { + background-color: rgba(0, 0, 0, 0.5); +} +.multi_bg_example { + width: 100%; + height: 400px; + background-image: url(main1.png), url(main2.png), linear-gradient(to right, rgba(30, 75, 115, 1), rgba(255, 255, 255, 0)); + background-repeat: no-repeat, no-repeat, no-repeat; + background-position: bottom right, left, right; +} +.sqs-block-btn { + transition: .1s opacity linear; + -webkit-backface-visibility: hidden; + font-family: "proxima-nova", "Helvetica Neue", Helvetica, Arial, sans-serif; + text-transform: uppercase; + letter-spacing: 1px; + font-weight: 600; + font-style: normal; + font-size: 13px; + color: #fff; + border-color: #272727; + display: inline-block; + width: auto; + height: auto; + border-width: 0; + text-align: center; + text-decoration: none; + outline: none; + -webkit-appearance: none; + line-height: normal; + size: small; +} +.btn-mint { + background-color: #36b3a8; + padding: 21px 34px; +} +.btn-mint:hover { + background-color: #36b3a8; + background-repeat:no-repeat; + border: none; + cursor:pointer; + overflow: hidden; + outline:none; + color: white; + text-decoration: none; + filter: grayscale(30%); +} +.btn-black { + background-color: #000000; + padding: 12px 14px; +} +.btn-black:hover { + background-color: #000000; + background-repeat:no-repeat; + border: none; + cursor:pointer; + overflow: hidden; + outline:none; + color: white; + text-decoration: none; + filter: grayscale(90%); +} +.btn-black:active { + background-color: #000000; + box-shadow: 0 1px #666; + transform: translateY(1px); +} + +.background-img { + position: relative; + background-repeat: no-repeat; +} +.background-img::after { + content: ""; + background-image: url("https://umaine.edu/ewb/wp-content/uploads/sites/211/2016/05/ewb-usa-logo-color.jpg"); + opacity: 0.1; + top: 0; + left: 0; + bottom: 0; + right: 0; + position: absolute; + z-index: -1; + background-repeat: no-repeat; +} + +.form-control { + border: 0; + background-image: linear-gradient(#9c27b0, #9c27b0), linear-gradient(#D2D2D2, #D2D2D2); + background-size: 0 2px, 100% 1px; + background-repeat: no-repeat; + background-position: center bottom, center calc(100% - 1px); + background-color: transparent; + transition: background 0s ease-out; + float: none; + box-shadow: none; + border-radius: 0; + font-weight: 400; +} +.form-control { + color: #555; +} +.form-control:focus { + border: 0; + background-image: linear-gradient(#9c27b3, black), linear-gradient(black, black); + background-size: 0 2px, 100% 2px; + box-shadow: none; +>>>>>>> e4e9f27d67527a9e38927c28a8b70703d73e75e2 +} \ No newline at end of file diff --git a/app/assets/stylesheets/application_BASE_3303.scss b/app/assets/stylesheets/application_BASE_3303.scss new file mode 100644 index 0000000..48b997b --- /dev/null +++ b/app/assets/stylesheets/application_BASE_3303.scss @@ -0,0 +1,163 @@ + + +html, body { + height: 100%; + min-height: 100% + } +/* + * This is a manifest file that'll be compiled into application.css, which will include all the files + * listed below. + * + * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, + * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path. + * + * You're free to add application-wide styles to this file and they'll appear at the top of the + * compiled file, but it's generally better to create a new file per style scope. + * + *= require jquery.ui.datepicker + *= require jquery-ui + *= require_self + *= require_tree . + *= require jquery-ui + *= require bootstrap-datepicker + */ + + h1, h2, h3, h4, h5, h6 { + font-family: 'Corben', Georgia, Times, serif; +} +p, div { + font-family: 'Nobile', Helvetica, Arial, sans-serif; +} + + #projects .calendar { + border-collapse: collapse; + width: 100%; + + td, th { + font-family: "Lucida Grande", arial, helvetica, sans-serif; + font-size: 10px; + padding: 6px; + border: 1px solid #999; + } + + th { + + color: #666; + text-align: center; + width: 14.2857142857143%; + } + + td { + background: #FFF; + color: #777; + height: 80px; + vertical-align: top; + font-size: 16px; + } + + .notmonth, .notmonth a { color: #CCC; } + .today { background-color: #D7F2FF; } +} + +#projects #month { + margin: 0; + padding-bottom: 10px; + text-align: center; + font-size: 22px; + a { + text-decoration: none; + padding: 0 10px; + color: #999; + } +} + +#projects ul { + font-size: 11px; + padding-left: 20px; +} + +.temp { + background-image: url('/assets/ewb.jpg'); + background-repeat: no-repeat; + background-size: contain; + background-position: center center; + width: 100%; + height: 90%; + } +.fill { + height: 100%; + min-height: 100%; + } +.main { + background: #FFFFFF; + position: relative; + z-index: 3; +} +.main-raised { + margin: -60px 30px 0px; + border-radius: 6px; + /* box-shadow: 0 16px 24px 2px rgba(0, 0, 0, 0.14), 0 6px 30px 5px rgba(0, 0, 0, 0.12), 0 8px 10px -5px rgba(0, 0, 0, 0.2); */ +} +.section { + background-position: center center; + background-size: cover; + padding: 70px 0; +} +.card { + border-radius: 6px; + box-shadow: 0 16px 24px 2px #333, 0 6px 30px 5px rgba(0, 0, 0, 0.12), 0 8px 10px -5px rgba(0, 0, 0, 0.2); + display: inline-block; + position: relative; + width: 100%; + margin-bottom: 30px; + color: rgba(0,0,0, 0.87); + background: #fff; +} +.card-title { + font-weight: 700; + font-family: nanum-barun-gothic-regular; +} +.card-image { + margin: 0; + border-radius: 3px; + height: 60%; + position: relative; + overflow: hidden; + box-shadow: 0 16px 38px -12px rgba(0, 0, 0, 0.56), 0 4px 25px 0px rgba(0, 0, 0, 0.12), 0 8px 10px -5px rgba(0, 0, 0, 0.2); +} +.btn-color { + background-color: #3D3C40; + color: #FFFFFF; +} +.bg-color { + background-color: #E5E5E5; +} +.nav-shadow{ + box-shadow: 0 10px 20px -12px rgba(0, 0, 0, 0.42), 0 3px 20px 0px rgba(0, 0, 0, 0.12), 0 8px 10px -5px rgba(0, 0, 0, 0.2); +} +.btn-round{ + border-radius: 300px; + background-color: transparent; + -webkit-font-smoothing: subpixel-antialiased; + border: 2px solid #000; + color: #000; + text-transform: uppercase; + text-decoration: none; + letter-spacing: 1px; + font-weight: 400; + font-style: normal; + margin-left: 1em; + padding: 1em 1.5em !important; + transition: background-color .1s 0s ease-in-out, color .1s 0s ease-in-out +} +.btn-round:hover { + background-color: #313844; + color: white; + +} + +.btn-round:active { + background-color: #121721; + box-shadow: 0 5px #666; + transform: translateY(4px); +} \ No newline at end of file diff --git a/app/assets/stylesheets/application_LOCAL_3303.scss b/app/assets/stylesheets/application_LOCAL_3303.scss new file mode 100644 index 0000000..6d3d6f2 --- /dev/null +++ b/app/assets/stylesheets/application_LOCAL_3303.scss @@ -0,0 +1,186 @@ + + +html, body { + height: 100%; + min-height: 100% + } +/* + * This is a manifest file that'll be compiled into application.css, which will include all the files + * listed below. + * + * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, + * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path. + * + * You're free to add application-wide styles to this file and they'll appear at the top of the + * compiled file, but it's generally better to create a new file per style scope. + * + *= require jquery.ui.datepicker + *= require jquery-ui + *= require_self + *= require_tree . + *= require jquery-ui + *= require bootstrap-datepicker + */ + + h1, h2, h3, h4, h5, h6 { + font-family: 'Corben', Georgia, Times, serif; +} +p, div { + font-family: 'Nobile', Helvetica, Arial, sans-serif; +} + + #projects .calendar { + border-collapse: collapse; + width: 100%; + + td, th { + font-family: "Lucida Grande", arial, helvetica, sans-serif; + font-size: 10px; + padding: 6px; + border: 1px solid #999; + } + + th { + + color: #666; + text-align: center; + width: 14.2857142857143%; + } + + td { + background: #FFF; + color: #777; + height: 80px; + vertical-align: top; + font-size: 16px; + } + + .notmonth, .notmonth a { color: #CCC; } + .today { background-color: #D7F2FF; } +} + +#projects #month { + margin: 0; + padding-bottom: 10px; + text-align: center; + font-size: 22px; + a { + text-decoration: none; + padding: 0 10px; + color: #999; + } +} + +#projects ul { + font-size: 11px; + padding-left: 20px; +} + +.temp { + background-image: url('/assets/ewb.jpg'); + background-repeat: no-repeat; + background-size: contain; + background-position: center center; + width: 100%; + height: 90%; + } +.fill { + height: 100%; + min-height: 100%; + } +.main { + background: #FFFFFF; + position: relative; + z-index: 3; +} +.main-raised { + margin: -60px 30px 0px; + border-radius: 6px; + /* box-shadow: 0 16px 24px 2px rgba(0, 0, 0, 0.14), 0 6px 30px 5px rgba(0, 0, 0, 0.12), 0 8px 10px -5px rgba(0, 0, 0, 0.2); */ +} +.section { + background-position: center center; + background-size: cover; + padding: 70px 0; +} +.card { + border-radius: 6px; + box-shadow: 0 16px 24px 2px #333, 0 6px 30px 5px rgba(0, 0, 0, 0.12), 0 8px 10px -5px rgba(0, 0, 0, 0.2); + display: inline-block; + position: relative; + width: 100%; + margin-bottom: 30px; + color: rgba(0,0,0, 0.87); + background: #fff; +} +.card-title { + font-weight: 700; + font-family: nanum-barun-gothic-regular; +} +.card-image { + margin: 0; + border-radius: 3px; + height: 60%; + position: relative; + overflow: hidden; + box-shadow: 0 16px 38px -12px rgba(0, 0, 0, 0.56), 0 4px 25px 0px rgba(0, 0, 0, 0.12), 0 8px 10px -5px rgba(0, 0, 0, 0.2); +} +.btn-color { + background-color: #3D3C40; + color: #FFFFFF; +} +.bg-color { + background-color: #E5E5E5; +} +.nav-shadow{ + box-shadow: 0 10px 20px -12px rgba(0, 0, 0, 0.42), 0 3px 20px 0px rgba(0, 0, 0, 0.12), 0 8px 10px -5px rgba(0, 0, 0, 0.2); +} +.btn-round{ + border-radius: 300px; + background-color: transparent; + -webkit-font-smoothing: subpixel-antialiased; + border: 2px solid #000; + color: #000; + text-transform: uppercase; + text-decoration: none; + letter-spacing: 1px; + font-weight: 400; + font-style: normal; + margin-left: 1em; + padding: 1em 1.5em !important; + transition: background-color .1s 0s ease-in-out, color .1s 0s ease-in-out +} +.btn-round:hover { + background-color: #313844; + color: white; + +} + +.btn-round:active { + background-color: #121721; + box-shadow: 0 5px #666; + transform: translateY(4px); +} + +.row .col-md-7 { + left: 50px; +} + +// .search-checkbox { +// position: relative; +// left: 25px; +// top: 50px; +// } + +.search-checkbox { + #search-submit { + position:absolute; + width: 20%; + height: 10%; + top: 13%; + right: 5%; + font-size: 20px; + font-weight: bold; + } + +} \ No newline at end of file diff --git a/app/assets/stylesheets/application_REMOTE_3303.scss b/app/assets/stylesheets/application_REMOTE_3303.scss new file mode 100644 index 0000000..f156c45 --- /dev/null +++ b/app/assets/stylesheets/application_REMOTE_3303.scss @@ -0,0 +1,279 @@ + + +html, body { + height: 100%; + min-height: 100% + } +/* + * This is a manifest file that'll be compiled into application.css, which will include all the files + * listed below. + * + * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, + * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path. + * + * You're free to add application-wide styles to this file and they'll appear at the top of the + * compiled file, but it's generally better to create a new file per style scope. + * + *= require jquery.ui.datepicker + *= require jquery-ui + *= require_self + *= require_tree . + *= require jquery-ui + *= require bootstrap-datepicker + */ + + h1, h2, h3, h4, h5, h6 { + font-family: "proxima-nova"; + font-weight: bold; +} +p, div, strong { + font-family: "proxima-nova", Helvetica, Arial, sans-serif; + font-size: 18px; + font-weight: bold; +} + + #projects .calendar { + border-collapse: collapse; + width: 100%; + + td, th { + font-family: "Lucida Grande", arial, helvetica, sans-serif; + font-size: 10px; + padding: 6px; + border: 1px solid #999; + } + + th { + + color: #666; + text-align: center; + width: 14.2857142857143%; + } + + td { + background: #FFF; + color: #777; + height: 80px; + vertical-align: top; + font-size: 16px; + } + + .notmonth, .notmonth a { color: #CCC; } + .today { background-color: #D7F2FF; } +} + +#projects #month { + margin: 0; + padding-bottom: 10px; + text-align: center; + font-size: 22px; + a { + text-decoration: none; + padding: 0 10px; + color: #999; + } +} + +#projects ul { + font-size: 11px; + padding-left: 20px; +} + +.temp { + background-image: url('/assets/ewb.jpg'); + background-repeat: no-repeat; + background-size: contain; + background-position: center center; + width: 100%; + height: 90%; + } +.fill { + height: 100%; + min-height: 100%; + } +.main { + background: #FFFFFF; + position: relative; + z-index: 3; +} +.main-raised { + margin: -60px 30px 0px; + border-radius: 6px; + /* box-shadow: 0 16px 24px 2px rgba(0, 0, 0, 0.14), 0 6px 30px 5px rgba(0, 0, 0, 0.12), 0 8px 10px -5px rgba(0, 0, 0, 0.2); */ +} +.section { + background-position: center center; + background-size: cover; + padding: 70px 0; +} +.card { + border-radius: 6px; + box-shadow: 0 16px 24px 2px #333, 0 6px 30px 5px rgba(0, 0, 0, 0.12), 0 8px 10px -5px rgba(0, 0, 0, 0.2); + display: inline-block; + position: relative; + width: 100%; + margin-bottom: 30px; + color: rgba(0,0,0, 0.87); + background: #fff; + padding: 7%; +} +.card-title { + font-weight: 700; + font-family: nanum-barun-gothic-regular; +} +.card-image { + margin: 0; + border-radius: 3px; + height: 60%; + position: relative; + overflow: hidden; + box-shadow: 0 16px 38px -12px rgba(0, 0, 0, 0.56), 0 4px 25px 0px rgba(0, 0, 0, 0.12), 0 8px 10px -5px rgba(0, 0, 0, 0.2); +} +.btn-color { + background-color: #3D3C40; + color: #FFFFFF; +} +.bg-color { + background-color: #E5E5E5; +} +.nav-shadow{ + box-shadow: 0 10px 20px -12px rgba(0, 0, 0, 0.42), 0 3px 20px 0px rgba(0, 0, 0, 0.12), 0 8px 10px -5px rgba(0, 0, 0, 0.2); +} +.btn-round{ + border-radius: 300px; + background-color: transparent; + -webkit-font-smoothing: subpixel-antialiased; + border: 2px solid #000; + color: #000; + text-transform: uppercase; + text-decoration: none; + letter-spacing: 1px; + font-weight: 400; + font-style: normal; + margin-left: 1em; + padding: 1em 1.5em !important; + transition: background-color .1s 0s ease-in-out, color .1s 0s ease-in-out +} +.btn-round:hover { + background-color: #000000; + color: white; + +} + +.btn-round:active { + background-color: #121721; + box-shadow: 0 1px #666; + transform: translateY(1px); +} +.nav-item { + font-family: 'Open Sans', Helvetica, sans-serif; + text-transform: uppercase; + font-size: 13px; +} +.filter { + background-color: rgba(0, 0, 0, 0.5); +} +.multi_bg_example { + width: 100%; + height: 400px; + background-image: url(main1.png), url(main2.png), linear-gradient(to right, rgba(30, 75, 115, 1), rgba(255, 255, 255, 0)); + background-repeat: no-repeat, no-repeat, no-repeat; + background-position: bottom right, left, right; +} +.sqs-block-btn { + transition: .1s opacity linear; + -webkit-backface-visibility: hidden; + font-family: "proxima-nova", "Helvetica Neue", Helvetica, Arial, sans-serif; + text-transform: uppercase; + letter-spacing: 1px; + font-weight: 600; + font-style: normal; + font-size: 13px; + color: #fff; + border-color: #272727; + display: inline-block; + width: auto; + height: auto; + border-width: 0; + text-align: center; + text-decoration: none; + outline: none; + -webkit-appearance: none; + line-height: normal; + size: small; +} +.btn-mint { + background-color: #36b3a8; + padding: 21px 34px; +} +.btn-mint:hover { + background-color: #36b3a8; + background-repeat:no-repeat; + border: none; + cursor:pointer; + overflow: hidden; + outline:none; + color: white; + text-decoration: none; + filter: grayscale(30%); +} +.btn-black { + background-color: #000000; + padding: 12px 14px; +} +.btn-black:hover { + background-color: #000000; + background-repeat:no-repeat; + border: none; + cursor:pointer; + overflow: hidden; + outline:none; + color: white; + text-decoration: none; + filter: grayscale(90%); +} +.btn-black:active { + background-color: #000000; + box-shadow: 0 1px #666; + transform: translateY(1px); +} + +.background-img { + position: relative; + background-repeat: no-repeat; +} +.background-img::after { + content: ""; + background-image: url("https://umaine.edu/ewb/wp-content/uploads/sites/211/2016/05/ewb-usa-logo-color.jpg"); + opacity: 0.1; + top: 0; + left: 0; + bottom: 0; + right: 0; + position: absolute; + z-index: -1; + background-repeat: no-repeat; +} + +.form-control { + border: 0; + background-image: linear-gradient(#9c27b0, #9c27b0), linear-gradient(#D2D2D2, #D2D2D2); + background-size: 0 2px, 100% 1px; + background-repeat: no-repeat; + background-position: center bottom, center calc(100% - 1px); + background-color: transparent; + transition: background 0s ease-out; + float: none; + box-shadow: none; + border-radius: 0; + font-weight: 400; +} +.form-control { + color: #555; +} +.form-control:focus { + border: 0; + background-image: linear-gradient(#9c27b3, black), linear-gradient(black, black); + background-size: 0 2px, 100% 2px; + box-shadow: none; +} \ No newline at end of file diff --git a/app/controllers/events_controller.rb b/app/controllers/events_controller.rb deleted file mode 100644 index 3eca9f0..0000000 --- a/app/controllers/events_controller.rb +++ /dev/null @@ -1,50 +0,0 @@ -class EventsController < ApplicationController - def index - @all_events = Event.all - @events = @all_events.page(params[:page]).per(7) - end - - def show - @event = Event.find(params[:id]) - end - - def new - @event = Event.new - end - - def edit - @event = Event.find(params[:id]) - end - - def create - @event = Event.new(event_params) - @event.project_id = session[:current_project_id] - if @event.save - redirect_to @event, notice: "Successfully created event." - else - render :new - end - end - - def update - @event = Event.find(params[:id]) - if @event.update(event_params) - redirect_to @event, notice: "Successfully updated event." - else - render :edit - end - end - - private - - def event_params - params.require(:event).permit(:name, :description, :start_time, :end_time, :location, :repeats, :project_id, daysRepeated: []) - end - - def destroy - @event = Event.find(params[:id]) - @event.destroy - redirect_to event_path, notice: "Successfully destroyed event." - end -end - \ No newline at end of file diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 853dfce..3e5c20d 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -9,14 +9,17 @@ def index end def show - @project = Project.find(params[:id]) - @all_events = Event.all + @project = Project.find(params[:id]) +=begin + if @project && @project.skills + @skills = @project.skills().map{|x| x.name}.join(", ") + end +=end session[:current_project_id] = @project.id end def new @project = Project.new - @all_events = Event.all end def edit @@ -26,6 +29,7 @@ def edit def create @project = Project.new(project_params) if @project.save + @project.managers << current_user redirect_to @project, notice: "Successfully created project." else render :new @@ -44,7 +48,7 @@ def update private def project_params - params.require(:project).permit(:name, :description, :start_date, :volunteer_capacity, :volunteers, :location, :image, :hours_per_week) + params.require(:project).permit(:name, :description, :start_date, :volunteer_capacity, :location, :image, :hours_per_week) end def destroy @@ -52,4 +56,4 @@ def destroy @project.destroy redirect_to project_path, notice: "Successfully destroyed project" end -end \ No newline at end of file +end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index b898794..f31abb9 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -18,12 +18,28 @@ def create end def index + if request.xhr? + skill_name = params[:skill_name] + puts "skill_name" + skill_obj = Skill.find_by name: skill_name + @user = skill_obj.users.first + render :json => @user + return + end @user = User.all @search = User.search(params[:q]) @users = @search.result.page(params[:page]).per(10) @search.build_condition authorize! :read, @user end + + def manages + if(!current_user.manager?) + redirect_to projects_path + end + @all_projects = current_user.manages + @projects = @all_projects.page(params[:page]).per(3) + end def age_sorting @users = User.all @@ -71,6 +87,8 @@ def update end user = User.find(params[:id]) # update fields + + user.first_name = user_params[:first_name] user.last_name = user_params[:last_name] user.age = user_params[:age] @@ -78,7 +96,7 @@ def update user.school = user_params[:school] user.expertise = user_params[:expertise] user.description = user_params[:description] - user.certifications = user_params[:certifications] + #user.certifications = user_params[:certifications] user.phone = user_params[:phone] user.zip = user_params[:zip] # languages @@ -89,15 +107,11 @@ def update # availability user.travel = user_params[:travel] user.time_commitment = user_params[:time_commitment] - user.sunday_availability = user_params[:sunday_availability] - user.monday_availability = user_params[:monday_availability] - user.tuesday_availability = user_params[:tuesday_availability] - user.wednesday_availability = user_params[:wednesday_availability] - user.thursday_availability = user_params[:thursday_availability] - user.friday_availability = user_params[:friday_availability] - user.saturday_availability = user_params[:saturday_availability] + user.availability_comments = user_params[:availability_comments] + user.skills = Skill.get_skills(user_params[:skill_ids]) + user.save # update complete flag @@ -129,3 +143,154 @@ def user_params params.require(:user) end end + + +class UsersController < ApplicationController + before_action only: [:show, :edit, :update, :age_sorting] + + autocomplete :user, :school + + rescue_from CanCan::AccessDenied do |exception| + redirect_to main_app.root_url, :alert => exception.message + end + + def create + @user = User.new(params[:user]) + if @user.save + UserMailer.signup_confirmation(@user).deliver + redirect_to @user, notice: "Signed up successfully" + else + render :new + end + end + + def index + if request.xhr? + #skill_name = params[:skill_name] + @skills = Hash.new + @certs = Hash.new + users = User.all + users.each do |user| + @skills[user[:id]] = [] + @certs[user[:id]] = [] + user.certifications.each do |cert| + @certs[user[:id]].push cert[:name] + end + user.skills.each do |skill| + @skills[user[:id]].push skill[:name] + end + end + data = {:skills => @skills, :certs => @certs} + render :json => data + return + end + @user = User.all + @search = User.search(params[:q]) + @users = @search.result.page(params[:page]).per(10) + @search.build_condition + authorize! :read, @user + end + + def age_sorting + @users = User.all + @users = @users.order(age: :desc) + render :users => 'index' + end + + def first_name_sorting + @users = User.all + @users = @users.order(first_name :desc) + render :users => 'index' + end + + def last_name_sorting + @users = User.all + @users = @users.order(last_name :desc) + render :users => 'index' + end + + + def show + @user = User.find(params[:id]) + authorize! :read, @user + end + + # GET /users/1/edit + def edit + @user = User.find(params[:id]) + @education_choices = ["GED", "College Student", "Bachelor's Degree", "Master's Degree", "Doctorate Degree"] + @proficiency_choices = ["1 - Elementary Proficiency", "2 - Limited Working Proficiency", "3 - Minimum Professional Proficiency", "4 - Full Professional Proficiency", "5 - Native or Bilingual Proficiency"] + @availability_choices = ["Not Available", "Morning", "Afternoon", "Evening", "Any Time"] + @time_commitment_choices = ["1-3 hours every month", "1-3 hours every week", "More than 3 hours per week"] + @travel_availability = ["Yes", "No"] + @field_choices = ["Civil Engineering","Environmental Engineering","Mechanical Engineering","Electrical Engineering","Materials Science","Chemical Engineering","Hydraulics / Hydrology","Computer Science","Education","International Development"] + @certificate_choices = ["Agricultural and Biological Engineering","Architectural","Chemical","Civil: Construction","Civil: Geotechnical","Civil: Structural","Civil: Transportation","Civil: Water Resources and Environmental","Control Systems","Electrical and Computer: Computer Engineering","Electrical and Computer: Electrical and Electronics","Electrical and Computer: Power","Environmental","Fire Protection","Industrial and Systems","Mechanical: HVAC and Refrigeration","Mechanical: Machine Design and Materials","Mechanical: Thermal and Fluids Systems","Metallurgical and Materials","Mining and Mineral Processing","Naval Architecture and Marine","Nuclear","Petroleum","Software","Structural"] + @current_availability = @user.availability.as_json + authorize! :manage, @user + end + + # PATCH/PUT /users/1 + # PATCH/PUT /users/1.json + def update + if not params[:id] + redirect_to root_path + end + user = User.find(params[:id]) + # update fields + + user.update_availability(user_params[:availability]) + + + user.first_name = user_params[:first_name] + user.last_name = user_params[:last_name] + user.age = user_params[:age] + user.education = user_params[:education] + user.school = user_params[:school] + user.expertise = user_params[:expertise] + user.description = user_params[:description] + + #user.certifications = user_params[:certifications] + user.phone = user_params[:phone] + user.zip = user_params[:zip] + # languages + user.lang1 = user_params[:lang1] + user.lang1_fluency = user_params[:lang1_fluency] + user.lang2 = user_params[:lang2] + user.lang2_fluency = user_params[:lang2_fluency] + # availability + user.travel = user_params[:travel] + user.time_commitment = user_params[:time_commitment] + user.availability_comments = user_params[:availability_comments] + user.skills = Skill.get_skills(user_params[:skill_ids]) + + user.save + + # update complete flag + if not user.complete + all_fields_filled = true + user_params.each do |k, v| + if v.blank? + all_fields_filled = false + end + end + if all_fields_filled + user.complete = true + user.save + else + flash[:warning] = "Some profile information is still missing. Please fill out the missing fields so that we can determine the best projects for you!" + end + + if not flash[:warning] + flash[:notice] = "Profile was successfully updated." + end + end + + redirect_to user_path(params[:id]) + end + + private + def user_params + # this simply makes it easier to access params[:user_params[:param]] + params.require(:user).permit! + end +end diff --git a/app/models/ability.rb b/app/models/ability.rb index f78d5be..8ce7c23 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -31,7 +31,7 @@ def initialize(user) user ||= User.new # guest user (not logged in) # manager abilities - if user.role == "manager" + if user.manager can :manage, Project can :read, :all end diff --git a/app/models/availability.rb b/app/models/availability.rb new file mode 100644 index 0000000..0a672c5 --- /dev/null +++ b/app/models/availability.rb @@ -0,0 +1,9 @@ +class Availability < ActiveRecord::Base + belongs_to :user + + + def user_params + # this simply makes it easier to access params[:user_params[:param]] + params.require(:user) + end +end \ No newline at end of file diff --git a/app/models/certification.rb b/app/models/certification.rb new file mode 100644 index 0000000..eb36e1f --- /dev/null +++ b/app/models/certification.rb @@ -0,0 +1,12 @@ +class Certification < ActiveRecord::Base + has_and_belongs_to_many :users + has_and_belongs_to_many :projects + + def self.ransackable_attributes(auth_object = nil) + ['name'] + end + + validates :name, presence: true, allow_blank: false + +end + diff --git a/app/models/construction_experience.rb b/app/models/construction_experience.rb new file mode 100644 index 0000000..a922fbe --- /dev/null +++ b/app/models/construction_experience.rb @@ -0,0 +1,11 @@ +class ConstructionExperience < ActiveRecord::Base + has_and_belongs_to_many :users + has_and_belongs_to_many :projects + + def self.ransackable_attributes(auth_object = nil) + ['name'] + end + + validates :name, presence: true, allow_blank: false + +end diff --git a/app/models/design_experience.rb b/app/models/design_experience.rb new file mode 100644 index 0000000..83f357c --- /dev/null +++ b/app/models/design_experience.rb @@ -0,0 +1,11 @@ +class DesignExperience < ActiveRecord::Base + has_and_belongs_to_many :users + has_and_belongs_to_many :projects + + def self.ransackable_attributes(auth_object = nil) + ['name'] + end + + validates :name, presence: true, allow_blank: false + +end diff --git a/app/models/event.rb b/app/models/event.rb deleted file mode 100644 index 367df41..0000000 --- a/app/models/event.rb +++ /dev/null @@ -1,3 +0,0 @@ -class Event < ActiveRecord::Base - belongs_to :project -end diff --git a/app/models/manager_relationship.rb b/app/models/manager_relationship.rb new file mode 100644 index 0000000..ffdeffc --- /dev/null +++ b/app/models/manager_relationship.rb @@ -0,0 +1,4 @@ +class ManagerRelationship < ActiveRecord::Base + belongs_to :user, inverse_of: :manager_relationships + belongs_to :project, inverse_of: :manager_relationships +end diff --git a/app/models/project.rb b/app/models/project.rb index a674721..18f7b0a 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -1,5 +1,41 @@ class Project < ActiveRecord::Base - has_many :events - has_attached_file :image, styles: { large: "600x600>", medium: "300x300>", thumb: "150x150#" } - validates_attachment_content_type :image, content_type: /\Aimage\/.*\Z/ + has_many :manager_relationships + has_many :managers, -> { distinct }, through: :manager_relationships, source: :user do + def << (*managers) + # If user is already a volunteer on the project, promote him to a manager + managers.each do |manager| + if self.proxy_association.owner.volunteers.include?(manager) + self.proxy_association.owner.volunteers.delete(manager) + end + super + end + end + end + + has_many :volunteer_relationships #, inverse_of: :project + has_many :volunteers, -> { distinct }, through: :volunteer_relationships, source: :user do + # If user is already a manager, do nothing + def << (*volunteers) + volunteers.each do |volunteer| + if proxy_association.owner.managers.include?(volunteer) + next + end + super + end + end + end + + has_and_belongs_to_many :skills + has_and_belongs_to_many :certifications + has_and_belongs_to_many :design_experiences + has_and_belongs_to_many :construction_experiences + + + has_attached_file :image, styles: { large: "600x600>", + medium: "300x300>", + thumb: "150x150#" } + validates_attachment_content_type :image, content_type: /\Aimage\/.*\Z/ + + private :manager_relationships, :manager_relationships= + private :volunteer_relationships, :volunteer_relationships= end diff --git a/app/models/role.rb b/app/models/role.rb new file mode 100644 index 0000000..e34975f --- /dev/null +++ b/app/models/role.rb @@ -0,0 +1,10 @@ +class Role < ActiveRecord::Base + has_many :users + + def self.ransackable_attributes(auth_object = nil) + ['name'] + end + + validates :name, presence: true, allow_blank: false + +end diff --git a/app/models/skill.rb b/app/models/skill.rb new file mode 100644 index 0000000..23b04dd --- /dev/null +++ b/app/models/skill.rb @@ -0,0 +1,25 @@ +class Skill < ActiveRecord::Base + has_and_belongs_to_many :users + has_and_belongs_to_many :projects + + def self.get_skills(skill_ids) + total = [] + if skill_ids + skill_ids.each do |x| + if Skill.exists? x + total << Skill.find(x) + end + end + return total + else + return [] + end + end + + def self.ransackable_attributes(auth_object = nil) + ['name'] + end + + validates :name, presence: true, allow_blank: false + +end diff --git a/app/models/user.rb b/app/models/user.rb index e3e2695..ed716c1 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,8 +1,93 @@ class User < ActiveRecord::Base + has_and_belongs_to_many :skills + has_and_belongs_to_many :certifications + belongs_to :role # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable and :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable ROLES = %w[admin manager volunteer].freeze + #has_and_belongs_to_many :projects -end \ No newline at end of file + has_many :manager_relationships + has_many :manages, through: :manager_relationships, source: :project do + def << (*projects) + projects.flatten! + projects.each do |project| + project.managers << self.proxy_association.owner + end + end + end + + @@preset_time_slots = [ + :monday_morning, :monday_afternoon, :monday_evening, :tuesday_morning, + :tuesday_afternoon, :tuesday_evening, :wednesday_morning, :wednesday_afternoon, + :wednesday_evening, :thursday_morning, :thursday_afternoon, :thursday_evening, + :friday_morning, :friday_afternoon, :friday_evening, :saturday_morning, + :saturday_afternoon, :saturday_evening, :sunday_morning, :sunday_afternoon, :sunday_evening + ] + + has_many :volunteer_relationships #, inverse_of: :user + has_many :projects, through: :volunteer_relationships, source: :project do + def << (*projects) + projects.flatten! + projects.each do |project| + project.volunteers << self.proxy_association.owner + end + end + end + + def demote_manager_all + my_projects = self.manages.to_a + self.manages.delete_all + self.projects << my_projects + self.manager = false + end + + def name + if self.first_name.nil? && self.last_name.nil? + return "" + elsif !self.first_name.nil? && self.last_name.nil? + return self.first_name + elsif self.first_name.nil? && !self.last_name.nil? + return self.last_name + else + return self.first_name + " " + self.last_name + end + end + + + has_and_belongs_to_many :design_experiences + has_and_belongs_to_many :construction_experiences + + has_one :availability + + private :manager_relationships, :manager_relationships= + private :volunteer_relationships, :volunteer_relationships= + + # Over riding this method specifies which fields we want to be able to search on + def self.ransackable_attributes(auth_object = nil) + ["first_name", + "last_name", + "education", + "expertise", + "description", + "school"].sort + end + + def update_availability(availability_params) + symbol_int_availability = Hash[availability_params.map{|x, y| [x.to_sym , y == "1"]}] + if self.availability + self.availability.update(symbol_int_availability) + else + self.availability = Availability.create(symbol_int_availability) + end + self.availability.save! + end + + def preset_time_slots + @@preset_time_slots + end + + +end diff --git a/app/models/volunteer_relationship.rb b/app/models/volunteer_relationship.rb new file mode 100644 index 0000000..9bfc362 --- /dev/null +++ b/app/models/volunteer_relationship.rb @@ -0,0 +1,4 @@ +class VolunteerRelationship < ActiveRecord::Base + belongs_to :user + belongs_to :project +end diff --git a/app/views/devise/confirmations/new.html.erb b/app/views/devise/confirmations/new.html.erb index 949b172..2b2f664 100644 --- a/app/views/devise/confirmations/new.html.erb +++ b/app/views/devise/confirmations/new.html.erb @@ -1,16 +1,20 @@ -

Resend confirmation instructions

- -<%= simple_form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post }) do |f| %> - <%= f.error_notification %> - <%= f.full_error :confirmation_token %> - -
- <%= f.input :email, required: true, autofocus: true %> +
+
+

Resend confirmation instructions

+ + <%= simple_form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post }) do |f| %> + <%= f.error_notification %> + <%= f.full_error :confirmation_token %> + +
+ <%= f.input :email, required: true, autofocus: true %> +
+ +
+ <%= f.button :submit, "Resend confirmation instructions" %> +
+ <% end %> + + <%= render "devise/shared/links" %>
- -
- <%= f.button :submit, "Resend confirmation instructions" %> -
-<% end %> - -<%= render "devise/shared/links" %> +
\ No newline at end of file diff --git a/app/views/devise/mailer/confirmation_instructions.html.erb b/app/views/devise/mailer/confirmation_instructions.html.erb index dc55f64..5a089da 100644 --- a/app/views/devise/mailer/confirmation_instructions.html.erb +++ b/app/views/devise/mailer/confirmation_instructions.html.erb @@ -1,5 +1,9 @@ -

Welcome <%= @email %>!

- -

You can confirm your account email through the link below:

- -

<%= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token) %>

+
+
+

Welcome <%= @email %>!

+ +

You can confirm your account email through the link below:

+ +

<%= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token) %>

+
+
diff --git a/app/views/devise/mailer/password_change.html.erb b/app/views/devise/mailer/password_change.html.erb index b41daf4..e7c55a5 100644 --- a/app/views/devise/mailer/password_change.html.erb +++ b/app/views/devise/mailer/password_change.html.erb @@ -1,3 +1,7 @@ -

Hello <%= @resource.email %>!

- -

We're contacting you to notify you that your password has been changed.

+
+
+

Hello <%= @resource.email %>!

+ +

We're contacting you to notify you that your password has been changed.

+
+
\ No newline at end of file diff --git a/app/views/devise/mailer/reset_password_instructions.html.erb b/app/views/devise/mailer/reset_password_instructions.html.erb index f667dc1..ace5b79 100644 --- a/app/views/devise/mailer/reset_password_instructions.html.erb +++ b/app/views/devise/mailer/reset_password_instructions.html.erb @@ -1,8 +1,12 @@ -

Hello <%= @resource.email %>!

- -

Someone has requested a link to change your password. You can do this through the link below.

- -

<%= link_to 'Change my password', edit_password_url(@resource, reset_password_token: @token) %>

- -

If you didn't request this, please ignore this email.

-

Your password won't change until you access the link above and create a new one.

+
+
+

Hello <%= @resource.email %>!

+ +

Someone has requested a link to change your password. You can do this through the link below.

+ +

<%= link_to 'Change my password', edit_password_url(@resource, reset_password_token: @token) %>

+ +

If you didn't request this, please ignore this email.

+

Your password won't change until you access the link above and create a new one.

+
+
\ No newline at end of file diff --git a/app/views/devise/mailer/unlock_instructions.html.erb b/app/views/devise/mailer/unlock_instructions.html.erb index 41e148b..69dbd43 100644 --- a/app/views/devise/mailer/unlock_instructions.html.erb +++ b/app/views/devise/mailer/unlock_instructions.html.erb @@ -1,7 +1,11 @@ -

Hello <%= @resource.email %>!

- -

Your account has been locked due to an excessive number of unsuccessful sign in attempts.

- -

Click the link below to unlock your account:

- -

<%= link_to 'Unlock my account', unlock_url(@resource, unlock_token: @token) %>

+
+
+

Hello <%= @resource.email %>!

+ +

Your account has been locked due to an excessive number of unsuccessful sign in attempts.

+ +

Click the link below to unlock your account:

+ +

<%= link_to 'Unlock my account', unlock_url(@resource, unlock_token: @token) %>

+
+
\ No newline at end of file diff --git a/app/views/devise/passwords/edit.html.erb b/app/views/devise/passwords/edit.html.erb index a938930..07a459c 100644 --- a/app/views/devise/passwords/edit.html.erb +++ b/app/views/devise/passwords/edit.html.erb @@ -1,19 +1,23 @@ -

Change your password

- -<%= simple_form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f| %> - <%= f.error_notification %> - - <%= f.input :reset_password_token, as: :hidden %> - <%= f.full_error :reset_password_token %> - -
- <%= f.input :password, label: "New password", required: true, autofocus: true, hint: ("#{@minimum_password_length} characters minimum" if @minimum_password_length) %> - <%= f.input :password_confirmation, label: "Confirm your new password", required: true %> +
+
+

Change your password

+ + <%= simple_form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f| %> + <%= f.error_notification %> + + <%= f.input :reset_password_token, as: :hidden %> + <%= f.full_error :reset_password_token %> + +
+ <%= f.input :password, label: "New password", required: true, autofocus: true, hint: ("#{@minimum_password_length} characters minimum" if @minimum_password_length) %> + <%= f.input :password_confirmation, label: "Confirm your new password", required: true %> +
+ +
+ <%= f.button :submit, "Change my password" %> +
+ <% end %> + + <%= render "devise/shared/links" %>
- -
- <%= f.button :submit, "Change my password" %> -
-<% end %> - -<%= render "devise/shared/links" %> +
diff --git a/app/views/devise/passwords/new.html.erb b/app/views/devise/passwords/new.html.erb index d1503e7..e04a0ed 100644 --- a/app/views/devise/passwords/new.html.erb +++ b/app/views/devise/passwords/new.html.erb @@ -1,15 +1,19 @@ -

Forgot your password?

- -<%= simple_form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f| %> - <%= f.error_notification %> - -
- <%= f.input :email, required: true, autofocus: true %> +
+
+

Forgot your password?

+ + <%= simple_form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f| %> + <%= f.error_notification %> + +
+ <%= f.input :email, required: true, autofocus: true %> +
+ +
+ <%= f.button :submit, "Send me reset password instructions" %> +
+ <% end %> + + <%= render "devise/shared/links" %>
- -
- <%= f.button :submit, "Send me reset password instructions" %> -
-<% end %> - -<%= render "devise/shared/links" %> +
\ No newline at end of file diff --git a/app/views/devise/registrations/edit.html.erb b/app/views/devise/registrations/edit.html.erb index 5db350b..da020f7 100644 --- a/app/views/devise/registrations/edit.html.erb +++ b/app/views/devise/registrations/edit.html.erb @@ -1,27 +1,31 @@ -

Edit <%= resource_name.to_s.humanize %>

- -<%= simple_form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %> - <%= f.error_notification %> - -
- <%= f.input :email, required: true, autofocus: true %> - - <% if devise_mapping.confirmable? && resource.pending_reconfirmation? %> -

Currently waiting confirmation for: <%= resource.unconfirmed_email %>

+
+
+

Edit <%= resource_name.to_s.humanize %>

+ + <%= simple_form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %> + <%= f.error_notification %> + +
+ <%= f.input :email, required: true, autofocus: true %> + + <% if devise_mapping.confirmable? && resource.pending_reconfirmation? %> +

Currently waiting confirmation for: <%= resource.unconfirmed_email %>

+ <% end %> + + <%= f.input :password, autocomplete: "off", hint: "leave it blank if you don't want to change it", required: false %> + <%= f.input :password_confirmation, required: false %> + <%= f.input :current_password, hint: "we need your current password to confirm your changes", required: true %> +
+ +
+ <%= f.button :submit, "Update", class:"btn btn-sm sqs-block-btn btn-black" %> +
<% end %> - - <%= f.input :password, autocomplete: "off", hint: "leave it blank if you don't want to change it", required: false %> - <%= f.input :password_confirmation, required: false %> - <%= f.input :current_password, hint: "we need your current password to confirm your changes", required: true %> + +

Cancel my account

+ +

Unhappy? <%= link_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete %>

+ + <%= link_to "Back", :back %>
- -
- <%= f.button :submit, "Update" %> -
-<% end %> - -

Cancel my account

- -

Unhappy? <%= link_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete %>

- -<%= link_to "Back", :back %> +
diff --git a/app/views/devise/registrations/new.html.erb b/app/views/devise/registrations/new.html.erb index 34b4279..ae12cbb 100644 --- a/app/views/devise/registrations/new.html.erb +++ b/app/views/devise/registrations/new.html.erb @@ -1,17 +1,22 @@ -

Sign up

+
+
+

Sign up

+ <%= simple_form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %> + <%= f.error_notification %> -<%= simple_form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %> - <%= f.error_notification %> +
+ <%= f.input :email, required: true, autofocus: true %> + <%= f.input :password, required: true, hint: ("#{@minimum_password_length} characters minimum" if @minimum_password_length) %> + <%= f.input :password_confirmation, required: true %> +
-
- <%= f.input :email, required: true, autofocus: true %> - <%= f.input :password, required: true, hint: ("#{@minimum_password_length} characters minimum" if @minimum_password_length) %> - <%= f.input :password_confirmation, required: true %> -
+
+ <%= f.button :submit, "Sign up", class:"btn sqs-block-btn btn-black" %> +
+ <% end %> + <%= render "devise/shared/links" %> + +
+
-
- <%= f.button :submit, "Sign up" %> -
-<% end %> -<%= render "devise/shared/links" %> diff --git a/app/views/devise/sessions/new.html.erb b/app/views/devise/sessions/new.html.erb index 31f8a4d..45d0ec9 100644 --- a/app/views/devise/sessions/new.html.erb +++ b/app/views/devise/sessions/new.html.erb @@ -1,15 +1,18 @@ -

Log in

+
+
+

Log in

+ <%= simple_form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %> +
+ <%= f.input :email, required: false, autofocus: true, class: "form-control" %> + <%= f.input :password, required: false %> + <%= f.input :remember_me, as: :boolean if devise_mapping.rememberable? %> +
-<%= simple_form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %> -
- <%= f.input :email, required: false, autofocus: true %> - <%= f.input :password, required: false %> - <%= f.input :remember_me, as: :boolean if devise_mapping.rememberable? %> -
+
+ <%= f.button :submit, "Log in", class:"btn sqs-block-btn btn-black" %> +
+ <% end %> -
- <%= f.button :submit, "Log in" %> -
-<% end %> - -<%= render "devise/shared/links" %> + <%= render "devise/shared/links" %> +
+
diff --git a/app/views/devise/shared/_links.html.erb b/app/views/devise/shared/_links.html.erb index e6a3e41..b35531c 100644 --- a/app/views/devise/shared/_links.html.erb +++ b/app/views/devise/shared/_links.html.erb @@ -1,25 +1,29 @@ -<%- if controller_name != 'sessions' %> - <%= link_to "Log in", new_session_path(resource_name) %>
-<% end -%> - -<%- if devise_mapping.registerable? && controller_name != 'registrations' %> - <%= link_to "Sign up", new_registration_path(resource_name) %>
-<% end -%> - -<%- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' %> - <%= link_to "Forgot your password?", new_password_path(resource_name) %>
-<% end -%> - -<%- if devise_mapping.confirmable? && controller_name != 'confirmations' %> - <%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %>
-<% end -%> - -<%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %> - <%= link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name) %>
-<% end -%> - -<%- if devise_mapping.omniauthable? %> - <%- resource_class.omniauth_providers.each do |provider| %> - <%= link_to "Sign in with #{OmniAuth::Utils.camelize(provider)}", omniauth_authorize_path(resource_name, provider) %>
- <% end -%> -<% end -%> +
+
+ <%- if controller_name != 'sessions' %> + <%= link_to "Log in", new_session_path(resource_name) %>
+ <% end -%> + + <%- if devise_mapping.registerable? && controller_name != 'registrations' %> + <%= link_to "Sign up", new_registration_path(resource_name) %>
+ <% end -%> + + <%- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' %> + <%= link_to "Forgot your password?", new_password_path(resource_name) %>
+ <% end -%> + + <%- if devise_mapping.confirmable? && controller_name != 'confirmations' %> + <%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %>
+ <% end -%> + + <%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %> + <%= link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name) %>
+ <% end -%> + + <%- if devise_mapping.omniauthable? %> + <%- resource_class.omniauth_providers.each do |provider| %> + <%= link_to "Sign in with #{OmniAuth::Utils.camelize(provider)}", omniauth_authorize_path(resource_name, provider) %>
+ <% end -%> + <% end -%> +
+
\ No newline at end of file diff --git a/app/views/devise/unlocks/new.html.erb b/app/views/devise/unlocks/new.html.erb index 788f62e..761901c 100644 --- a/app/views/devise/unlocks/new.html.erb +++ b/app/views/devise/unlocks/new.html.erb @@ -1,16 +1,20 @@ -

Resend unlock instructions

- -<%= simple_form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { method: :post }) do |f| %> - <%= f.error_notification %> - <%= f.full_error :unlock_token %> - -
- <%= f.input :email, required: true, autofocus: true %> +
+
+

Resend unlock instructions

+ + <%= simple_form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { method: :post }) do |f| %> + <%= f.error_notification %> + <%= f.full_error :unlock_token %> + +
+ <%= f.input :email, required: true, autofocus: true %> +
+ +
+ <%= f.button :submit, "Resend unlock instructions" %> +
+ <% end %> + + <%= render "devise/shared/links" %>
- -
- <%= f.button :submit, "Resend unlock instructions" %> -
-<% end %> - -<%= render "devise/shared/links" %> +
diff --git a/app/views/events/_form.html.erb b/app/views/events/_form.html.erb deleted file mode 100644 index 82367c9..0000000 --- a/app/views/events/_form.html.erb +++ /dev/null @@ -1,16 +0,0 @@ -<%= simple_form_for(@event) do |f| %> - <%= f.input :name %> - <%= f.input :description %> - <%= f.label :starting_time %>: - <%= f.datetime_select :start_time, { :include_blank => false } %> -
- <%= f.label :ending_time %>: - <%= f.datetime_select :end_time, { :include_blank => false } %> -
- <%= f.input :location %> - <%= f.input :repeats, label: "Repeats:", collection: ["Yes", "No"] %> - - - <%= f.button :submit, class: "btn btn-md btn-success" %>

-<% end %> - diff --git a/app/views/events/edit.html.erb b/app/views/events/edit.html.erb deleted file mode 100644 index 2be2ec7..0000000 --- a/app/views/events/edit.html.erb +++ /dev/null @@ -1,3 +0,0 @@ -

Editing Event

- -<%= render 'form' %> diff --git a/app/views/events/index.html.erb b/app/views/events/index.html.erb deleted file mode 100644 index f607c83..0000000 --- a/app/views/events/index.html.erb +++ /dev/null @@ -1,15 +0,0 @@ -

Listing Events

- -
-