From c2309dd2ef7810ea5e4a212b71180ef1112c7cd1 Mon Sep 17 00:00:00 2001 From: Luke Barratt Date: Wed, 2 Apr 2014 00:07:21 +0100 Subject: [PATCH] Added timezone based google calendar widget Updated unicorn and capistrano deployment configuration for the staging environment HTML formatting Fixes errors when posting new issues Added Google Calendar client code CSS tweaks to layout Added new .env vars Layout tweaks Updated contributors --- .env.example | 3 + Gemfile | 2 + Gemfile.lock | 6 + README.md | 7 +- app/assets/stylesheets/sass/articles.sass | 6 +- app/assets/stylesheets/sass/general.sass | 2 +- app/assets/stylesheets/sass/index.sass | 25 +- app/assets/stylesheets/sass/special.sass | 2 +- app/helpers/application_helper.rb | 14 + app/models/issue.rb | 2 + app/services/google_calendar.rb | 120 +++ app/views/layouts/application.html.erb | 6 +- app/views/users/edit.html.erb | 4 +- app/views/widgets/_calendar.html.erb | 16 + app/views/widgets/_matches.html.erb | 22 +- config/deploy.rb | 2 - config/deploy/production.rb | 3 +- config/deploy/staging.rb | 9 +- config/environments/development.rb | 2 +- config/environments/production.rb | 2 +- config/environments/staging.rb | 6 +- config/locales/en.yml | 3 + config/unicorn.rb | 4 +- spec/factories/profile.rb | 5 + spec/factories/user.rb | 4 + .../calendar/google_calendar_widget_spec.rb | 53 ++ spec/fixtures/google_calendar.json | 763 ++++++++++++++++++ spec/services/api/v1/users_collection_spec.rb | 2 + spec/support/features/session_helpers.rb | 11 +- 29 files changed, 1065 insertions(+), 41 deletions(-) create mode 100644 app/services/google_calendar.rb create mode 100644 app/views/widgets/_calendar.html.erb create mode 100644 spec/factories/profile.rb create mode 100644 spec/features/calendar/google_calendar_widget_spec.rb create mode 100644 spec/fixtures/google_calendar.json diff --git a/.env.example b/.env.example index d390356..2d588bb 100644 --- a/.env.example +++ b/.env.example @@ -2,6 +2,8 @@ RACK_ENV= RAILS_ENV= APP_SECRET= +DEPLOY_PATH= + UNICORN_USER=deploy UNICORN_GROUP=deploy UNICORN_WORKERS=4 @@ -18,4 +20,5 @@ NEW_RELIC_LICENSE_KEY= EXCEPTIONAL_API_KEY= +GOOGLE_API_KEY= GOOGLE_CALENDAR_ID= diff --git a/Gemfile b/Gemfile index 427b01f..f7d254c 100644 --- a/Gemfile +++ b/Gemfile @@ -9,6 +9,7 @@ gem 'dalli', '~> 2.7.0' gem 'exceptional', '~> 2.0.33' gem 'oj', '~> 2.5.5' +gem 'faraday', '~> 0.9.0' gem 'gruff', '~> 0.3.6' gem 'nokogiri', '~> 1.6.1' gem 'bbcoder', '~> 1.0.1' @@ -50,6 +51,7 @@ group :test do gem 'poltergeist', '~> 1.5.0' gem 'selenium-webdriver', '~> 2.41.0' gem 'factory_girl_rails', '~> 4.4.1' + gem 'timecop', '~> 0.7.1' end group :development, :test do diff --git a/Gemfile.lock b/Gemfile.lock index 898d21d..0474942 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -100,6 +100,8 @@ GEM factory_girl_rails (4.4.1) factory_girl (~> 4.4.0) railties (>= 3.0.0) + faraday (0.9.0) + multipart-post (>= 1.2, < 3) ffi (1.9.3) ffi (1.9.3-x86-mingw32) gruff (0.3.6) @@ -119,6 +121,7 @@ GEM mime-types (1.25.1) mini_portile (0.5.3) multi_json (1.8.4) + multipart-post (2.0.0) mysql2 (0.3.15) net-scp (1.1.2) net-ssh (>= 2.6.5) @@ -223,6 +226,7 @@ GEM ref thor (0.18.1) tilt (1.4.1) + timecop (0.7.1) tins (1.0.1) tinymce-rails (3.5.9) railties (>= 3.1.1) @@ -268,6 +272,7 @@ DEPENDENCIES dynamic_form (~> 1.1.4) exceptional (~> 2.0.33) factory_girl_rails (~> 4.4.1) + faraday (~> 0.9.0) gruff (~> 0.3.6) jquery-rails (~> 2.0.2) kgio (~> 2.9.2) @@ -286,6 +291,7 @@ DEPENDENCIES selenium-webdriver (~> 2.41.0) simplecov (~> 0.7.1) therubyracer (~> 0.12.1) + timecop (~> 0.7.1) tinymce-rails (~> 3.5.9) uglifier (~> 2.5.0) unicorn (~> 4.8.2) diff --git a/README.md b/README.md index 414f630..2b7e08c 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,7 @@ Features: ## Contributors -- [Ari Timonen](https://github.com/jirikivaari) - Original author -- [Florent Latombe](https://github.com/flatombe) - Improvements -- [Luke Barratt](https://github.com/lbarratt) - Improvements +- [Ari Timonen](https://github.com/jirikivaari) (Original Author) +- [Florent Latombe](https://github.com/flatombe) +- [Luke Barratt](https://github.com/lbarratt) +- [Callum Barratt](https://github.com/cbarratt) \ No newline at end of file diff --git a/app/assets/stylesheets/sass/articles.sass b/app/assets/stylesheets/sass/articles.sass index e654610..cf93039 100644 --- a/app/assets/stylesheets/sass/articles.sass +++ b/app/assets/stylesheets/sass/articles.sass @@ -6,8 +6,9 @@ div &.article @include rounded-corners @include shadow - width: 650px + width: 100% padding: 0px + margin-right: 0 margin-bottom: 20px border: 1px solid #d7d7d7 background-color: $bg_box @@ -16,8 +17,9 @@ div &.article > h1 @include shaded-top + box-sizing: border-box margin: 0 - width: 630px + width: 100% font-size: 140% h1 a color: #ffffff diff --git a/app/assets/stylesheets/sass/general.sass b/app/assets/stylesheets/sass/general.sass index a63ecd4..423af2c 100644 --- a/app/assets/stylesheets/sass/general.sass +++ b/app/assets/stylesheets/sass/general.sass @@ -164,7 +164,7 @@ input float: right .big - width: 65% + width: 70% .big2 width: 62% diff --git a/app/assets/stylesheets/sass/index.sass b/app/assets/stylesheets/sass/index.sass index 1759f55..4d83815 100644 --- a/app/assets/stylesheets/sass/index.sass +++ b/app/assets/stylesheets/sass/index.sass @@ -137,12 +137,13 @@ div color: #d6d5d5 &#indexMainarea - padding: 10px 100px 10px 150px + padding: 10px 100px 10px 100px &#indexContent - width: 650px + width: 700px + margin-top: 15px margin-left: 15px - margin-right: 15px + margin-right: 20px float: left padding: 0 @@ -152,7 +153,7 @@ div &.indexBox @include rounded-corners @include shadow - width: 220px + width: 250px padding-bottom: 10px margin-bottom: 15px background-color: $bg_box @@ -164,6 +165,14 @@ div height: 25px font-size: 14px font-weight: bold + &.separator + @include shaded-top + border-radius: 0px + margin: 0 + padding-top: 5px + height: 20px + font-size: 12px + font-weight: normal &.body width: 100% text-align: left @@ -183,6 +192,14 @@ div width: 110px text-align: center + &#index-calendar + padding-bottom: 0 + .widget-content-wrapper + padding-bottom: 10px + max-height: 400px + overflow-x: hidden + overflow-y: scroll + &#indexPosts padding: 5px diff --git a/app/assets/stylesheets/sass/special.sass b/app/assets/stylesheets/sass/special.sass index a64425a..9ad393a 100644 --- a/app/assets/stylesheets/sass/special.sass +++ b/app/assets/stylesheets/sass/special.sass @@ -23,7 +23,7 @@ td padding-left: 15px padding-top: 20px vertical-align: top - width: 450px + width: 550px div &.userFields diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 3e5d726..c701f1d 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -130,4 +130,18 @@ module ApplicationHelper end link_to_function(name, ("add_fields(this, '#{association}', '#{escape_javascript(fields)}')")) end + + def timezone_offset + if @cuser + @cuser.time_zone + else + Time.zone.name + end + end + + def upcoming_matches + GoogleCalendar.new(ENV['GOOGLE_CALENDAR_ID'], timezone_offset).upcoming.sort_by do |event| + event.start + end + end end diff --git a/app/models/issue.rb b/app/models/issue.rb index 04116cf..4fd6c07 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -18,6 +18,8 @@ require File.join(Rails.root, 'vendor', 'plugins', 'acts-as-readable', 'init.rb') class Issue < ActiveRecord::Base + include Extra + STATUS_OPEN = 0 STATUS_SOLVED = 1 STATUS_REJECTED = 2 diff --git a/app/services/google_calendar.rb b/app/services/google_calendar.rb new file mode 100644 index 0000000..f259389 --- /dev/null +++ b/app/services/google_calendar.rb @@ -0,0 +1,120 @@ +class GoogleCalendar + attr_accessor :timezone + + def initialize(id, timezone_offset = Time.zone.name) + @id = id + @timezone_offset = timezone_offset + end + + def summary + list.summary + end + + def timezone + list.timezone + end + + def events + list.events + end + + def upcoming + events.select do |event| + event.start >= Time.zone.now + end + end + + def list + @list ||= GoogleCalendar::Request.events_list(@id, @timezone_offset) + end +end + +class GoogleCalendar + class Request + BASE_URL = "https://www.googleapis.com/calendar/v3/calendars" + EVENTS_ENDPOINT = "events" + + def self.events_list(id, timezone_offset) + request = self.new(id, EVENTS_ENDPOINT) + GoogleCalendar::EventList.new(request.parsed_response, timezone_offset) + end + + def initialize(id, endpoint) + @id = id + @endpoint = endpoint + @response = get_data + end + + def parsed_response + JSON.parse(@response.body) + end + + private + + def get_data + Rails.cache.fetch(cache_key, expires_in: 5.minutes) do + Faraday.get(request_url) + end + end + + def cache_key + "/google_calendar/#{@id}/#{@endpoint}" + end + + def request_url + "#{BASE_URL}/#{@id}/#{@endpoint}/?key=#{ENV['GOOGLE_API_KEY']}" + end + end + + class EventList + attr_reader :summary, :events, :timezone + + def initialize(list, timezone_offset) + @list = list + @timezone_offset = timezone_offset + + parse_list + parse_events + end + + private + + def parse_list + @summary = @list["summary"] + @timezone = @list["timeZone"] + end + + def parse_events + @events = @list["items"].map do |item| + GoogleCalendar::Event.new(item, @timezone_offset) + end + end + end + + class Event + def initialize(entry, timezone_offset) + @entry = entry + @timezone_offset = timezone_offset + end + + def start + Time.use_zone(@timezone_offset) { Time.zone.parse(@entry["start"]["dateTime"]) } + end + + def end + Time.use_zone(@timezone_offset) { Time.zone.parse(@entry["end"]["dateTime"]) } + end + + def formatted_summary + summary.gsub(/(http\:\/\/)(.*[^)])/i, '\2').html_safe + end + + def [](key) + @entry[key] + end + + def method_missing(method) + self[method.to_s] + end + end +end \ No newline at end of file diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index a37dbd0..f153bbf 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -34,6 +34,10 @@
+
+ <%= render :partial => "widgets/calendar" %> +
+
Shoutbox & Match search
@@ -43,11 +47,9 @@
- <%# if @current_controller == "contests" %>
<%= render :partial => "widgets/highlights" %>
- <%# end %>
<%= render :partial => "widgets/posts" %> diff --git a/app/views/users/edit.html.erb b/app/views/users/edit.html.erb index 9686098..118a43b 100644 --- a/app/views/users/edit.html.erb +++ b/app/views/users/edit.html.erb @@ -6,7 +6,7 @@

- <%= f.submit "Save" %> + <%= f.submit %>

<% end %> diff --git a/app/views/widgets/_calendar.html.erb b/app/views/widgets/_calendar.html.erb new file mode 100644 index 0000000..9589de8 --- /dev/null +++ b/app/views/widgets/_calendar.html.erb @@ -0,0 +1,16 @@ +
Match Schedule
+ +
+ <% upcoming_matches.group_by{ |e| e.start.month }.each do |month, events| %> + <% events.group_by { |e| e.start.day }.each do |day, day_events| %> +
<%= day_events.first.start.strftime("%A, %e %B") %>
+ <% day_events.each do |event| %> +
+

<%= event.formatted_summary %>

+

<%= event.start.strftime("%H:%M %Z") %>

+
+ <% end %> + <% end %> + <% end %> +
+ \ No newline at end of file diff --git a/app/views/widgets/_matches.html.erb b/app/views/widgets/_matches.html.erb index 77ce7b2..82a6376 100644 --- a/app/views/widgets/_matches.html.erb +++ b/app/views/widgets/_matches.html.erb @@ -19,14 +19,14 @@ <% link_to match do %> <%= match.contester1 %>
<% if match.score1 > match.score2; c1 = 'green'; c2 = 'red' end %> - <% if match.score1 < match.score2; c1 = 'red'; c2 = 'green' end %> - <% if match.score1 == match.score2; c1 = 'yellow'; c2 = 'yellow' end %> -   <%= h match.score1 %> - - - <%= h match.score2 %> -
- <%= match.contester2 %> - <% end %> -

- <% end %> - + <% if match.score1 < match.score2; c1 = 'red'; c2 = 'green' end %> + <% if match.score1 == match.score2; c1 = 'yellow'; c2 = 'yellow' end %> +   <%= h match.score1 %> + - + <%= h match.score2 %> +
+ <%= match.contester2 %> + <% end %> +

+ <% end %> + diff --git a/config/deploy.rb b/config/deploy.rb index 398a58a..7bc1a43 100644 --- a/config/deploy.rb +++ b/config/deploy.rb @@ -1,8 +1,6 @@ lock '3.1.0' set :application, 'ensl' -set :deploy_user, 'deploy' -set :deploy_to, '/var/www/virtual/ensl.org/deploy' set :deploy_via, :remote_cache set :pty, true diff --git a/config/deploy/production.rb b/config/deploy/production.rb index 7e4b4e0..a78403c 100644 --- a/config/deploy/production.rb +++ b/config/deploy/production.rb @@ -1,9 +1,10 @@ set :branch, 'master' +set :deploy_to, '/var/www/virtual/ensl.org/deploy' + set :rails_env, 'production' set :unicorn_rack_env, fetch(:rails_env) role :app, %w{vu2009@ensl.org} role :web, %w{vu2009@ensl.org} -role :db, %w{vu2009@ensl.org} server 'ensl.org', user: 'vu2009', roles: %w{web app} diff --git a/config/deploy/staging.rb b/config/deploy/staging.rb index 80edfcd..58c65d4 100644 --- a/config/deploy/staging.rb +++ b/config/deploy/staging.rb @@ -1,9 +1,10 @@ set :branch, 'develop' +set :deploy_to, '/var/www/virtual/ensl.org/staging/rails' + set :rails_env, 'staging' set :unicorn_rack_env, fetch(:rails_env) -role :app, %w{deploy@staging.ensl.org} -role :web, %w{deploy@staging.ensl.org} -role :db, %w{deploy@staging.ensl.org} +role :app, %w{vu2009@staging.ensl.org} +role :web, %w{vu2009@staging.ensl.org} -server 'staging.ensl.org', user: 'deploy', roles: %w{web app} +server 'staging.ensl.org', user: 'vu2009', roles: %w{web app} diff --git a/config/environments/development.rb b/config/environments/development.rb index b0c0176..6fc7019 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -10,7 +10,7 @@ Ensl::Application.configure do config.whiny_nils = true # Show full error reports and disable caching - config.consider_all_requests_local = true + config.consider_all_requests_local = true config.action_controller.perform_caching = false # Don't care if the mailer can't send diff --git a/config/environments/production.rb b/config/environments/production.rb index 5d7ece9..980ff81 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -5,7 +5,7 @@ Ensl::Application.configure do config.cache_classes = true # Full error reports are disabled and caching is turned on - config.consider_all_requests_local = false + config.consider_all_requests_local = false config.action_controller.perform_caching = true # Disable Rails's static asset server (Apache or nginx will already do this) diff --git a/config/environments/staging.rb b/config/environments/staging.rb index 01e18ea..1bf7d89 100644 --- a/config/environments/staging.rb +++ b/config/environments/staging.rb @@ -24,8 +24,8 @@ Ensl::Application.configure do # config.assets.manifest = YOUR_PATH # Specifies the header that your server uses for sending files - # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache - config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx + config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache + # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. # config.force_ssl = true @@ -61,4 +61,4 @@ Ensl::Application.configure do # Send deprecation notices to registered listeners config.active_support.deprecation = :notify -end \ No newline at end of file +end diff --git a/config/locales/en.yml b/config/locales/en.yml index 0407863..25e2129 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -81,6 +81,8 @@ en: votes_success: "Voted successfully." error: "error" prohibited: "prohibited" + profile: + locals: "Locals" sessions: form: forgot_password: "Forgot password?" @@ -92,6 +94,7 @@ en: user: login: "Login" create: "Register" + update: "Update Profile" post: create: "Create Article" activerecord: diff --git a/config/unicorn.rb b/config/unicorn.rb index 75ccd3f..75793d3 100644 --- a/config/unicorn.rb +++ b/config/unicorn.rb @@ -1,7 +1,7 @@ require "dotenv" Dotenv.load -base_path = "/var/www/virtual/ensl.org/deploy" +base_path = (ENV['DEPLOY_PATH'] || Dir.pwd) current_path = "#{base_path}/current" shared_path = "#{base_path}/shared" @@ -11,7 +11,7 @@ timeout 30 preload_app true user ENV['UNICORN_USER'], ENV['UNICORN_GROUP'] -listen Integer(ENV['UNICORN_PORT'] || 4000), :tcp_nopush => true +listen Integer(ENV['UNICORN_PORT']), :tcp_nopush => true listen ENV['UNICORN_SOCKET'], :backlog => 64 stderr_path "#{shared_path}/log/unicorn.stderr.log" diff --git a/spec/factories/profile.rb b/spec/factories/profile.rb new file mode 100644 index 0000000..af03b4a --- /dev/null +++ b/spec/factories/profile.rb @@ -0,0 +1,5 @@ +FactoryGirl.define do + factory :profile do + web "ensl.org" + end +end diff --git a/spec/factories/user.rb b/spec/factories/user.rb index 2f87bc2..fc5f7aa 100644 --- a/spec/factories/user.rb +++ b/spec/factories/user.rb @@ -9,6 +9,10 @@ FactoryGirl.define do country "EU" raw_password "PasswordABC123" + after(:create) do |user| + create(:profile, user: user) + end + factory :user_with_team do after(:create) do |user| create(:team, founder: user) diff --git a/spec/features/calendar/google_calendar_widget_spec.rb b/spec/features/calendar/google_calendar_widget_spec.rb new file mode 100644 index 0000000..6cdb3b7 --- /dev/null +++ b/spec/features/calendar/google_calendar_widget_spec.rb @@ -0,0 +1,53 @@ +require 'spec_helper' + +feature 'Google Calendar widget' do + let(:time) { Time.zone.local(2014, 4, 1, 12, 0, 0) } + let(:events_list_json) { JSON.parse(File.read(Rails.root.join('spec/fixtures/google_calendar.json'))) } + let!(:user) { create(:user) } + + before do + Timecop.travel(time) + + GoogleCalendar::Request.stub(:events_list) do + GoogleCalendar::EventList.new(events_list_json, Time.zone.name) + end + + visit root_path + end + + scenario 'the most recent upcoming event should appear correctly' do + expect(first_event).to have_content("Div 2B: el'pheer vs. RadicaL") + end + + feature 'Timezones offsets' do + scenario 'when a user is logged out, CEST is default' do + expect(first_event).to have_content("20:30 CEST") + end + + scenario 'when a user is logged in, their local timezone is used' do + sign_in_as(user) + change_timezone_for(user, timezone_us_east) + visit root_path + + expect(first_event).to have_content(timezone_adjusted) + end + end + + private + + def first_event + page.find(:xpath, "//div[@id = 'index-calendar']/div/div[@class = 'content'][1]") + end + + def timezone_adjusted + if Time.now.dst? + "14:30 EDT" + else + "15:30 EST" + end + end + + def timezone_us_east + "Eastern Time (US & Canada)" + end +end \ No newline at end of file diff --git a/spec/fixtures/google_calendar.json b/spec/fixtures/google_calendar.json new file mode 100644 index 0000000..1db765f --- /dev/null +++ b/spec/fixtures/google_calendar.json @@ -0,0 +1,763 @@ +{ + "kind": "calendar#events", + "etag": "\"2DaeHpkENZGECFHdcr5l8tYxjD4/uXUVU6PbSJC9e6cCh7-EC4OsKu0\"", + "summary": "NSL Season 4 Confirmed Match Schedule", + "description": "", + "updated": "2014-04-01T20:18:31.372Z", + "timeZone": "America/New_York", + "accessRole": "reader", + "items": [ + { + "kind": "calendar#event", + "etag": "\"2DaeHpkENZGECFHdcr5l8tYxjD4/MTM5NTM1ODMwOTgxMjAwMA\"", + "id": "gsq5f4k3mhg4keuqu1hqom1h18", + "status": "confirmed", + "htmlLink": "https://www.google.com/calendar/event?eid=Z3NxNWY0azNtaGc0a2V1cXUxaHFvbTFoMTggdnQuZWR1X281dHVnc3NqZTRoNnBqbnZ2aHNuNmw3bG9jQGc", + "created": "2014-03-19T21:40:28.000Z", + "updated": "2014-03-20T23:31:49.812Z", + "summary": "Div 3A: Silvermoon vs. Frequency (http://twitch.tv/feathermonster)", + "description": "http://www.ensl.org/matches/5488\n\nWeek 1 matchup. \n\nReferee: NeXuS\nCaster: Feathermonster\nStream: http://twitch.tv/feathermonster", + "creator": { + "email": "joeyh89@vt.edu", + "displayName": "Joey Hutchins" + }, + "organizer": { + "email": "vt.edu_o5tugssje4h6pjnvvhsn6l7loc@group.calendar.google.com", + "displayName": "NSL Season 4 Matches", + "self": true + }, + "start": { + "dateTime": "2014-03-20T22:00:00-04:00" + }, + "end": { + "dateTime": "2014-03-21T00:00:00-04:00" + }, + "iCalUID": "gsq5f4k3mhg4keuqu1hqom1h18@google.com", + "sequence": 1 + }, + { + "kind": "calendar#event", + "etag": "\"2DaeHpkENZGECFHdcr5l8tYxjD4/MTM5NTM1ODM4NTQyMDAwMA\"", + "id": "7g1k46eq471fsrsub1hqiqa4do", + "status": "confirmed", + "htmlLink": "https://www.google.com/calendar/event?eid=N2cxazQ2ZXE0NzFmc3JzdWIxaHFpcWE0ZG8gdnQuZWR1X281dHVnc3NqZTRoNnBqbnZ2aHNuNmw3bG9jQGc", + "created": "2014-03-19T21:37:32.000Z", + "updated": "2014-03-20T23:33:05.420Z", + "summary": "Div 2B: WongaNS vs. 2hrsLater (http://hitbox.tv/danjio)", + "description": "http://www.ensl.org/matches/5509\n\nWeek 1 matchup. \n\nReferee: Sohma\nCaster: Danjio\nStream: http://hitbox.tv/danjio", + "creator": { + "email": "joeyh89@vt.edu", + "displayName": "Joey Hutchins" + }, + "organizer": { + "email": "vt.edu_o5tugssje4h6pjnvvhsn6l7loc@group.calendar.google.com", + "displayName": "NSL Season 4 Matches", + "self": true + }, + "start": { + "dateTime": "2014-03-26T15:45:00-04:00" + }, + "end": { + "dateTime": "2014-03-26T17:45:00-04:00" + }, + "transparency": "transparent", + "iCalUID": "7g1k46eq471fsrsub1hqiqa4do@google.com", + "sequence": 4 + }, + { + "kind": "calendar#event", + "etag": "\"2DaeHpkENZGECFHdcr5l8tYxjD4/MTM5NTQyMTI1MzAzMDAwMA\"", + "id": "4bkilrunk0b0n2bl49v2n2tfok", + "status": "confirmed", + "htmlLink": "https://www.google.com/calendar/event?eid=NGJraWxydW5rMGIwbjJibDQ5djJuMnRmb2sgdnQuZWR1X281dHVnc3NqZTRoNnBqbnZ2aHNuNmw3bG9jQGc", + "created": "2014-03-19T17:39:23.000Z", + "updated": "2014-03-21T17:00:53.030Z", + "summary": "Div 1: Gnarcolepsy vs. Singularity (http://www.twitch.tv/gold_n)", + "description": "http://www.ensl.org/matches/5545\n\nWeek 1 matchup. \n\nReferee: Jehuty\nCaster: Golden & joshhhy\nStream: http://www.twitch.tv/gold_n", + "creator": { + "email": "joeyh89@vt.edu", + "displayName": "Joey Hutchins" + }, + "organizer": { + "email": "vt.edu_o5tugssje4h6pjnvvhsn6l7loc@group.calendar.google.com", + "displayName": "NSL Season 4 Matches", + "self": true + }, + "start": { + "dateTime": "2014-03-23T20:00:00-04:00", + "timeZone": "America/Los_Angeles" + }, + "end": { + "dateTime": "2014-03-23T22:00:00-04:00", + "timeZone": "America/Los_Angeles" + }, + "transparency": "transparent", + "iCalUID": "4bkilrunk0b0n2bl49v2n2tfok@google.com", + "sequence": 1 + }, + { + "kind": "calendar#event", + "etag": "\"2DaeHpkENZGECFHdcr5l8tYxjD4/MTM5NTQyOTg3NjIwMTAwMA\"", + "id": "i8vir19jo5vgsf57qb1gjuldak", + "status": "confirmed", + "htmlLink": "https://www.google.com/calendar/event?eid=aTh2aXIxOWpvNXZnc2Y1N3FiMWdqdWxkYWsgdnQuZWR1X281dHVnc3NqZTRoNnBqbnZ2aHNuNmw3bG9jQGc", + "created": "2014-03-21T19:23:38.000Z", + "updated": "2014-03-21T19:24:36.201Z", + "summary": "Div 4B: PinkFluffyGorges vs. FrenchCompany (http://www.twitch.tv/nittai_nev)", + "description": "http://www.ensl.org/matches/5582\n\nWeek 1 matchup. \n\nReferee: Yaluzan\nCaster: Nittai\nStream: http://www.twitch.tv/nittai_nev", + "creator": { + "email": "joeyh89@vt.edu", + "displayName": "Joey Hutchins" + }, + "organizer": { + "email": "vt.edu_o5tugssje4h6pjnvvhsn6l7loc@group.calendar.google.com", + "displayName": "NSL Season 4 Confirmed Match Schedule", + "self": true + }, + "start": { + "dateTime": "2014-03-22T16:00:00-04:00" + }, + "end": { + "dateTime": "2014-03-22T18:00:00-04:00" + }, + "iCalUID": "i8vir19jo5vgsf57qb1gjuldak@google.com", + "sequence": 0 + }, + { + "kind": "calendar#event", + "etag": "\"2DaeHpkENZGECFHdcr5l8tYxjD4/MTM5NTQzODc1MTM2MTAwMA\"", + "id": "2m5v78g88hqq02evfhg5vn9ka8", + "status": "confirmed", + "htmlLink": "https://www.google.com/calendar/event?eid=Mm01djc4Zzg4aHFxMDJldmZoZzV2bjlrYTggdnQuZWR1X281dHVnc3NqZTRoNnBqbnZ2aHNuNmw3bG9jQGc", + "created": "2014-03-21T21:51:27.000Z", + "updated": "2014-03-21T21:52:31.361Z", + "summary": "Div 2A: Perfect Peckers vs. Intent (http://www.twitch.tv/vindalo0)", + "description": "http://www.ensl.org/matches/5532\n\nWeek 1 matchup. \n\nReferee: Unique\nCaster: Vindaloo\nStream: http://www.twitch.tv/vindalo0", + "creator": { + "email": "pelargir.lsa@gmail.com", + "displayName": "Pelargir Chazalet" + }, + "organizer": { + "email": "vt.edu_o5tugssje4h6pjnvvhsn6l7loc@group.calendar.google.com", + "displayName": "NSL Season 4 Confirmed Match Schedule", + "self": true + }, + "start": { + "dateTime": "2014-03-22T07:00:00-04:00" + }, + "end": { + "dateTime": "2014-03-22T09:00:00-04:00" + }, + "iCalUID": "2m5v78g88hqq02evfhg5vn9ka8@google.com", + "sequence": 0 + }, + { + "kind": "calendar#event", + "etag": "\"2DaeHpkENZGECFHdcr5l8tYxjD4/MTM5NTUzNDU1MTgxMTAwMA\"", + "id": "i7fh8brdlj7im5c7thivp6hc9g", + "status": "confirmed", + "htmlLink": "https://www.google.com/calendar/event?eid=aTdmaDhicmRsajdpbTVjN3RoaXZwNmhjOWcgdnQuZWR1X281dHVnc3NqZTRoNnBqbnZ2aHNuNmw3bG9jQGc", + "created": "2014-03-20T19:21:50.000Z", + "updated": "2014-03-23T00:29:11.811Z", + "summary": "Div 3A: Gorge Busters vs. >>ACV<< ( http://www.hitbox.tv/danjio)", + "description": "http://www.ensl.org/matches/5489\n\nWeek 1 matchup. \n\nReferee: \nCaster: Danjio\nStream: http://hitbox.tv/danjio", + "creator": { + "email": "joeyh89@vt.edu", + "displayName": "Joey Hutchins" + }, + "organizer": { + "email": "vt.edu_o5tugssje4h6pjnvvhsn6l7loc@group.calendar.google.com", + "displayName": "NSL Season 4 Matches", + "self": true + }, + "start": { + "dateTime": "2014-03-23T14:30:00-04:00" + }, + "end": { + "dateTime": "2014-03-23T16:30:00-04:00" + }, + "iCalUID": "i7fh8brdlj7im5c7thivp6hc9g@google.com", + "sequence": 3 + }, + { + "kind": "calendar#event", + "etag": "\"2DaeHpkENZGECFHdcr5l8tYxjD4/MTM5NTU4NDU3Mjc1MjAwMA\"", + "id": "jt9upnr744ooit6rhijqs248gc", + "status": "confirmed", + "htmlLink": "https://www.google.com/calendar/event?eid=anQ5dXBucjc0NG9vaXQ2cmhpanFzMjQ4Z2MgdnQuZWR1X281dHVnc3NqZTRoNnBqbnZ2aHNuNmw3bG9jQGc", + "created": "2014-03-23T14:22:52.000Z", + "updated": "2014-03-23T14:22:52.752Z", + "summary": "Div 4A: UKTeamplay vs. LuckyFkers (http://www.twitch.tv/ISEGaming)", + "description": "http://www.ensl.org/matches/5596\n\nWeek 1 matchup.\n\nReferee: Argosh \nCaster: ItsSuperEffective \nStream: http://www.twitch.tv/ISEGaming", + "creator": { + "email": "pelargir.lsa@gmail.com", + "displayName": "Pelargir Chazalet" + }, + "organizer": { + "email": "vt.edu_o5tugssje4h6pjnvvhsn6l7loc@group.calendar.google.com", + "displayName": "NSL Season 4 Confirmed Match Schedule", + "self": true + }, + "start": { + "dateTime": "2014-03-23T15:00:00-04:00" + }, + "end": { + "dateTime": "2014-03-23T17:00:00-04:00" + }, + "visibility": "public", + "iCalUID": "jt9upnr744ooit6rhijqs248gc@google.com", + "sequence": 0 + }, + { + "kind": "calendar#event", + "etag": "\"2DaeHpkENZGECFHdcr5l8tYxjD4/MTM5NTYwMDkwNzc4OTAwMA\"", + "id": "mvt93vu72idnqo2p16oklqe5i8", + "status": "confirmed", + "htmlLink": "https://www.google.com/calendar/event?eid=bXZ0OTN2dTcyaWRucW8ycDE2b2tscWU1aTggdnQuZWR1X281dHVnc3NqZTRoNnBqbnZ2aHNuNmw3bG9jQGc", + "created": "2014-03-23T00:33:02.000Z", + "updated": "2014-03-23T18:55:07.789Z", + "summary": "Div 3B: 3hrsLater vs. PowerUP! (http://www.twitch.tv/RIdeOnSkulks)", + "description": "http://www.ensl.org/matches/5475\n\nWeek 1 matchup.\n\nReferee: Pelargir\nCaster: RioS \nStream: http://www.twitch.tv/RIdeOnSkulks", + "creator": { + "email": "pelargir.lsa@gmail.com", + "displayName": "Pelargir Chazalet" + }, + "organizer": { + "email": "vt.edu_o5tugssje4h6pjnvvhsn6l7loc@group.calendar.google.com", + "displayName": "NSL Season 4 Confirmed Match Schedule", + "self": true + }, + "start": { + "dateTime": "2014-03-23T15:00:00-04:00" + }, + "end": { + "dateTime": "2014-03-23T17:00:00-04:00" + }, + "visibility": "public", + "iCalUID": "mvt93vu72idnqo2p16oklqe5i8@google.com", + "sequence": 0 + }, + { + "kind": "calendar#event", + "etag": "\"2DaeHpkENZGECFHdcr5l8tYxjD4/MTM5NTc0MzY4ODE0NDAwMA\"", + "id": "ps74a0vskblsi52i24dkicvklg", + "status": "confirmed", + "htmlLink": "https://www.google.com/calendar/event?eid=cHM3NGEwdnNrYmxzaTUyaTI0ZGtpY3ZrbGcgdnQuZWR1X281dHVnc3NqZTRoNnBqbnZ2aHNuNmw3bG9jQGc", + "created": "2014-03-25T10:34:48.000Z", + "updated": "2014-03-25T10:34:48.144Z", + "summary": "Div 1: Joan of Arc™ vs. Virtual Dejection (http://www.hitbox.tv/danjio)", + "description": "http://www.ensl.org/matches/5547\n\nWeek 1 Matchup.\n\nReferee: Pelargir\nCaster: Danjio\nStream: http://www.hitbox.tv/danjio", + "creator": { + "email": "pelargir.lsa@gmail.com", + "displayName": "Pelargir Chazalet" + }, + "organizer": { + "email": "vt.edu_o5tugssje4h6pjnvvhsn6l7loc@group.calendar.google.com", + "displayName": "NSL Season 4 Confirmed Match Schedule", + "self": true + }, + "start": { + "dateTime": "2014-03-29T10:00:00-04:00" + }, + "end": { + "dateTime": "2014-03-29T12:00:00-04:00" + }, + "visibility": "public", + "iCalUID": "ps74a0vskblsi52i24dkicvklg@google.com", + "sequence": 0 + }, + { + "kind": "calendar#event", + "etag": "\"2DaeHpkENZGECFHdcr5l8tYxjD4/MTM5NTc2NTM5ODQwNzAwMA\"", + "id": "aafemih6n92b5v5o70k5imd348", + "status": "confirmed", + "htmlLink": "https://www.google.com/calendar/event?eid=YWFmZW1paDZuOTJiNXY1bzcwazVpbWQzNDggdnQuZWR1X281dHVnc3NqZTRoNnBqbnZ2aHNuNmw3bG9jQGc", + "created": "2014-03-25T10:31:01.000Z", + "updated": "2014-03-25T16:36:38.407Z", + "summary": "Div 4B: [karvalakki] vs. TAWsome (http://www.twitch.tv/ggKaneh)", + "description": "http://www.ensl.org/matches/5581\n\nWeek 1 Matchup.\n\nReferee: Pelargir\nCaster: Kaneh\nStream: http://www.twitch.tv/ggKaneh", + "creator": { + "email": "pelargir.lsa@gmail.com", + "displayName": "Pelargir Chazalet" + }, + "organizer": { + "email": "vt.edu_o5tugssje4h6pjnvvhsn6l7loc@group.calendar.google.com", + "displayName": "NSL Season 4 Confirmed Match Schedule", + "self": true + }, + "start": { + "dateTime": "2014-03-25T15:00:00-04:00" + }, + "end": { + "dateTime": "2014-03-25T17:00:00-04:00" + }, + "visibility": "public", + "iCalUID": "aafemih6n92b5v5o70k5imd348@google.com", + "sequence": 0 + }, + { + "kind": "calendar#event", + "etag": "\"2DaeHpkENZGECFHdcr5l8tYxjD4/MTM5NTkxODQ5MDc2ODAwMA\"", + "id": "mjipkmgdia834bp7f2ksmnf0rk", + "status": "confirmed", + "htmlLink": "https://www.google.com/calendar/event?eid=bWppcGttZ2RpYTgzNGJwN2Yya3NtbmYwcmsgdnQuZWR1X281dHVnc3NqZTRoNnBqbnZ2aHNuNmw3bG9jQGc", + "created": "2014-03-27T11:08:10.000Z", + "updated": "2014-03-27T11:08:10.768Z", + "summary": "Div 3B: TAW ♥ vs. HBZ (http://www.twitch.tv/feathermonster)", + "description": "http://www.ensl.org/matches/5474\n\nWeek 1 Matchup.\n\nReferee: Pelargir\nCaster: Feathermonster\nStream: http://www.twitch.tv/feathermonster", + "creator": { + "email": "pelargir.lsa@gmail.com", + "displayName": "Pelargir Chazalet" + }, + "organizer": { + "email": "vt.edu_o5tugssje4h6pjnvvhsn6l7loc@group.calendar.google.com", + "displayName": "NSL Season 4 Confirmed Match Schedule", + "self": true + }, + "start": { + "dateTime": "2014-03-27T15:30:00-04:00" + }, + "end": { + "dateTime": "2014-03-27T17:30:00-04:00" + }, + "visibility": "public", + "iCalUID": "mjipkmgdia834bp7f2ksmnf0rk@google.com", + "sequence": 0 + }, + { + "kind": "calendar#event", + "etag": "\"2DaeHpkENZGECFHdcr5l8tYxjD4/MTM5NTkxODUyNjAxMjAwMA\"", + "id": "49jnm0eh22lrjgg6738jr85d3k", + "status": "confirmed", + "htmlLink": "https://www.google.com/calendar/event?eid=NDlqbm0wZWgyMmxyamdnNjczOGpyODVkM2sgdnQuZWR1X281dHVnc3NqZTRoNnBqbnZ2aHNuNmw3bG9jQGc", + "created": "2014-03-25T10:36:45.000Z", + "updated": "2014-03-27T11:08:46.012Z", + "summary": "Div 2B: Table For Six vs. -/AUS/- (http://www.twitch.tv/schwaschwa)", + "description": "http://www.ensl.org/matches/5511\n\nWeek 1 Matchup.\n\nReferee: Tico\nCaster: Schwa\nStream: http://www.twitch.tv/schwaschwa", + "creator": { + "email": "pelargir.lsa@gmail.com", + "displayName": "Pelargir Chazalet" + }, + "organizer": { + "email": "vt.edu_o5tugssje4h6pjnvvhsn6l7loc@group.calendar.google.com", + "displayName": "NSL Season 4 Confirmed Match Schedule", + "self": true + }, + "start": { + "dateTime": "2014-03-29T22:00:00-04:00" + }, + "end": { + "dateTime": "2014-03-30T00:00:00-04:00" + }, + "visibility": "public", + "iCalUID": "49jnm0eh22lrjgg6738jr85d3k@google.com", + "sequence": 0 + }, + { + "kind": "calendar#event", + "etag": "\"2DaeHpkENZGECFHdcr5l8tYxjD4/MTM5NTkxODk5MzEwMjAwMA\"", + "id": "h7k7efkmoorimfolqkcn3833l0", + "status": "confirmed", + "htmlLink": "https://www.google.com/calendar/event?eid=aDdrN2Vma21vb3JpbWZvbHFrY24zODMzbDAgdnQuZWR1X281dHVnc3NqZTRoNnBqbnZ2aHNuNmw3bG9jQGc", + "created": "2014-03-24T15:12:39.000Z", + "updated": "2014-03-27T11:16:33.102Z", + "summary": "Div 4A: She-Wolves vs. Diamond Gamers (http://www.twitch.tv/ISEGaming)", + "description": "http://www.ensl.org/matches/5597\n\nWeek 1 matchup.\n\nReferee: Tico\nCaster: ItsSuperEffective\nStream: http://www.twitch.tv/ISEGaming", + "creator": { + "email": "pelargir.lsa@gmail.com", + "displayName": "Pelargir Chazalet" + }, + "organizer": { + "email": "vt.edu_o5tugssje4h6pjnvvhsn6l7loc@group.calendar.google.com", + "displayName": "NSL Season 4 Confirmed Match Schedule", + "self": true + }, + "start": { + "dateTime": "2014-03-31T21:00:00-04:00" + }, + "end": { + "dateTime": "2014-03-31T23:00:00-04:00" + }, + "visibility": "public", + "iCalUID": "h7k7efkmoorimfolqkcn3833l0@google.com", + "sequence": 3 + }, + { + "kind": "calendar#event", + "etag": "\"2DaeHpkENZGECFHdcr5l8tYxjD4/MTM5NjAxNTI1MDczNTAwMA\"", + "id": "gq026ueot20a8hfv8leu66r7g0", + "status": "confirmed", + "htmlLink": "https://www.google.com/calendar/event?eid=Z3EwMjZ1ZW90MjBhOGhmdjhsZXU2NnI3ZzAgdnQuZWR1X281dHVnc3NqZTRoNnBqbnZ2aHNuNmw3bG9jQGc", + "created": "2014-03-28T14:00:44.000Z", + "updated": "2014-03-28T14:00:50.735Z", + "summary": "Div 3A: TkMaster vs. Neuromancers (http://www.twitch.tv/sadenki)", + "description": "http://www.ensl.org/matches/5493\n\nWeek 2 Matchup.\n\nSTREAM IN FRENCH\n\nReferee:\nCaster: Sadenki\nStream: http://www.twitch.tv/sadenki", + "creator": { + "email": "pelargir.lsa@gmail.com", + "displayName": "Pelargir Chazalet" + }, + "organizer": { + "email": "vt.edu_o5tugssje4h6pjnvvhsn6l7loc@group.calendar.google.com", + "displayName": "NSL Season 4 Confirmed Match Schedule", + "self": true + }, + "start": { + "dateTime": "2014-03-30T14:30:00-04:00" + }, + "end": { + "dateTime": "2014-03-30T16:30:00-04:00" + }, + "visibility": "public", + "iCalUID": "gq026ueot20a8hfv8leu66r7g0@google.com", + "sequence": 0 + }, + { + "kind": "calendar#event", + "etag": "\"2DaeHpkENZGECFHdcr5l8tYxjD4/MTM5NjA0NDg1OTEyMDAwMA\"", + "id": "5kp8kjnmhf0dipvc322quf2f6g", + "status": "confirmed", + "htmlLink": "https://www.google.com/calendar/event?eid=NWtwOGtqbm1oZjBkaXB2YzMyMnF1ZjJmNmcgdnQuZWR1X281dHVnc3NqZTRoNnBqbnZ2aHNuNmw3bG9jQGc", + "created": "2014-03-27T22:26:55.000Z", + "updated": "2014-03-28T22:14:19.120Z", + "summary": "Div 3A: TkMaster vs. Vexta Ω (http://www.twitch.tv/sadenki)", + "description": "http://www.ensl.org/matches/5490\n\nWeek 1 Matchup.\n\nSTREAM IN FRENCH\n\nReferee: Sohma\nCaster: Sadenki & Mirmouz\nStream: http://www.twitch.tv/sadenki", + "creator": { + "email": "pelargir.lsa@gmail.com", + "displayName": "Pelargir Chazalet" + }, + "organizer": { + "email": "vt.edu_o5tugssje4h6pjnvvhsn6l7loc@group.calendar.google.com", + "displayName": "NSL Season 4 Confirmed Match Schedule", + "self": true + }, + "start": { + "dateTime": "2014-03-31T14:00:00-04:00" + }, + "end": { + "dateTime": "2014-03-31T16:00:00-04:00" + }, + "visibility": "public", + "iCalUID": "5kp8kjnmhf0dipvc322quf2f6g@google.com", + "sequence": 1 + }, + { + "kind": "calendar#event", + "etag": "\"2DaeHpkENZGECFHdcr5l8tYxjD4/MTM5NjA4OTY3NjMyMzAwMA\"", + "id": "8u7mrqlspe78mia6tu21pbst1k", + "status": "confirmed", + "htmlLink": "https://www.google.com/calendar/event?eid=OHU3bXJxbHNwZTc4bWlhNnR1MjFwYnN0MWsgdnQuZWR1X281dHVnc3NqZTRoNnBqbnZ2aHNuNmw3bG9jQGc", + "created": "2014-03-29T10:39:01.000Z", + "updated": "2014-03-29T10:41:16.323Z", + "summary": "Div 1: onFire vs. RaZe (http://www.twitch.tv/ren26)", + "description": "http://www.ensl.org/matches/5548\n\nWeek 1 Matchup.\n\nReferee:\nCaster: Ren26\nStream: http://www.twitch.tv/ren26", + "creator": { + "email": "pelargir.lsa@gmail.com", + "displayName": "Pelargir Chazalet" + }, + "organizer": { + "email": "vt.edu_o5tugssje4h6pjnvvhsn6l7loc@group.calendar.google.com", + "displayName": "NSL Season 4 Confirmed Match Schedule", + "self": true + }, + "start": { + "dateTime": "2014-03-29T19:00:00-04:00" + }, + "end": { + "dateTime": "2014-03-29T21:00:00-04:00" + }, + "visibility": "public", + "iCalUID": "8u7mrqlspe78mia6tu21pbst1k@google.com", + "sequence": 0 + }, + { + "kind": "calendar#event", + "etag": "\"2DaeHpkENZGECFHdcr5l8tYxjD4/MTM5NjExNTY2Mjc0NDAwMA\"", + "id": "c46jqcbqt1kb95roo0gedskhd0", + "status": "confirmed", + "htmlLink": "https://www.google.com/calendar/event?eid=YzQ2anFjYnF0MWtiOTVyb28wZ2Vkc2toZDAgdnQuZWR1X281dHVnc3NqZTRoNnBqbnZ2aHNuNmw3bG9jQGc", + "created": "2014-03-29T17:54:22.000Z", + "updated": "2014-03-29T17:54:22.744Z", + "summary": "Div 2A: Vexta vs. Aphex (http://www.twitch.tv/ren26)", + "description": "http://www.ensl.org/matches/5531\n\nWeek 1 Matchup.\n\nReferees: Tico & Zebroe\nCaster: Ren26\nStream: http://www.twitch.tv/ren26", + "creator": { + "email": "pelargir.lsa@gmail.com", + "displayName": "Pelargir Chazalet" + }, + "organizer": { + "email": "vt.edu_o5tugssje4h6pjnvvhsn6l7loc@group.calendar.google.com", + "displayName": "NSL Season 4 Confirmed Match Schedule", + "self": true + }, + "start": { + "dateTime": "2014-03-29T16:00:00-04:00" + }, + "end": { + "dateTime": "2014-03-29T18:00:00-04:00" + }, + "visibility": "public", + "iCalUID": "c46jqcbqt1kb95roo0gedskhd0@google.com", + "sequence": 0 + }, + { + "kind": "calendar#event", + "etag": "\"2DaeHpkENZGECFHdcr5l8tYxjD4/MTM5NjEyNTcxMzQ1MzAwMA\"", + "id": "eeduo3nnj33hci76hff49ii8ts", + "status": "confirmed", + "htmlLink": "https://www.google.com/calendar/event?eid=ZWVkdW8zbm5qMzNoY2k3NmhmZjQ5aWk4dHMgdnQuZWR1X281dHVnc3NqZTRoNnBqbnZ2aHNuNmw3bG9jQGc", + "created": "2014-03-29T20:41:53.000Z", + "updated": "2014-03-29T20:41:53.453Z", + "summary": "Premiere: Saunamen vs. iMAGINE (http://www.twitch.tv/ren26)", + "description": "http://www.ensl.org/matches/5429\n\nWeek 1 Matchup.\n\nReferee: Pelargir\nCaster: Ren26\nStream: http://www.twitch.tv/ren26", + "creator": { + "email": "pelargir.lsa@gmail.com", + "displayName": "Pelargir Chazalet" + }, + "organizer": { + "email": "vt.edu_o5tugssje4h6pjnvvhsn6l7loc@group.calendar.google.com", + "displayName": "NSL Season 4 Confirmed Match Schedule", + "self": true + }, + "start": { + "dateTime": "2014-03-30T14:00:00-04:00" + }, + "end": { + "dateTime": "2014-03-30T16:00:00-04:00" + }, + "visibility": "public", + "iCalUID": "eeduo3nnj33hci76hff49ii8ts@google.com", + "sequence": 0 + }, + { + "kind": "calendar#event", + "etag": "\"2DaeHpkENZGECFHdcr5l8tYxjD4/MTM5NjE4MDAzODU3ODAwMA\"", + "id": "7rdlnhgllqii9582cdtfhki3lc", + "status": "confirmed", + "htmlLink": "https://www.google.com/calendar/event?eid=N3JkbG5oZ2xscWlpOTU4MmNkdGZoa2kzbGMgdnQuZWR1X281dHVnc3NqZTRoNnBqbnZ2aHNuNmw3bG9jQGc", + "created": "2014-03-27T11:10:53.000Z", + "updated": "2014-03-30T11:47:18.578Z", + "summary": "Premiere: Legendary Snails vs. Titus Gaming (http://www.twitch.tv/naturalselection2)", + "description": "http://www.ensl.org/matches/5428\n\nWeek 1 Matchup.\n\nReferee: Yaluzan\nCaster: WasabiOne & Ren26\nStream: http://www.twitch.tv/naturalselection2", + "creator": { + "email": "pelargir.lsa@gmail.com", + "displayName": "Pelargir Chazalet" + }, + "organizer": { + "email": "vt.edu_o5tugssje4h6pjnvvhsn6l7loc@group.calendar.google.com", + "displayName": "NSL Season 4 Confirmed Match Schedule", + "self": true + }, + "start": { + "dateTime": "2014-03-30T12:00:00-04:00" + }, + "end": { + "dateTime": "2014-03-30T14:00:00-04:00" + }, + "visibility": "public", + "iCalUID": "7rdlnhgllqii9582cdtfhki3lc@google.com", + "sequence": 0 + }, + { + "kind": "calendar#event", + "etag": "\"2DaeHpkENZGECFHdcr5l8tYxjD4/MTM5NjE4MDE0NzAwMzAwMA\"", + "id": "aflokq41l64msqdq1q1pmuedqs", + "status": "confirmed", + "htmlLink": "https://www.google.com/calendar/event?eid=YWZsb2txNDFsNjRtc3FkcTFxMXBtdWVkcXMgdnQuZWR1X281dHVnc3NqZTRoNnBqbnZ2aHNuNmw3bG9jQGc", + "created": "2014-03-28T10:11:46.000Z", + "updated": "2014-03-30T11:49:07.003Z", + "summary": "Div 4B: TAWsome vs. FrenchCompany (http://www.twitch.tv/feathermonster )", + "description": "http://www.ensl.org/matches/5585\n\nWeek 2 Matchup.\n\nReferee:\nCaster: Feathermonster\nStream: http://www.twitch.tv/feathermonster", + "creator": { + "email": "pelargir.lsa@gmail.com", + "displayName": "Pelargir Chazalet" + }, + "organizer": { + "email": "vt.edu_o5tugssje4h6pjnvvhsn6l7loc@group.calendar.google.com", + "displayName": "NSL Season 4 Confirmed Match Schedule", + "self": true + }, + "start": { + "dateTime": "2014-03-30T15:00:00-04:00" + }, + "end": { + "dateTime": "2014-03-30T17:00:00-04:00" + }, + "visibility": "public", + "iCalUID": "aflokq41l64msqdq1q1pmuedqs@google.com", + "sequence": 4 + }, + { + "kind": "calendar#event", + "etag": "\"2DaeHpkENZGECFHdcr5l8tYxjD4/MTM5NjE4MDQ3NDIzMTAwMA\"", + "id": "274hn9kkkff6hme7k6de1aun9s", + "status": "confirmed", + "htmlLink": "https://www.google.com/calendar/event?eid=Mjc0aG45a2trZmY2aG1lN2s2ZGUxYXVuOXMgdnQuZWR1X281dHVnc3NqZTRoNnBqbnZ2aHNuNmw3bG9jQGc", + "created": "2014-03-24T15:28:41.000Z", + "updated": "2014-03-30T11:54:34.231Z", + "summary": "Div 2B: el'pheer vs. RadicaL (http://www.twitch.tv/feathermonster)", + "description": "http://www.ensl.org/matches/5510\n\nWeek 1 matchup.\n\nReferee:\nCaster: Feathermonster\nStream: http://www.twitch.tv/feathermonster", + "creator": { + "email": "pelargir.lsa@gmail.com", + "displayName": "Pelargir Chazalet" + }, + "organizer": { + "email": "vt.edu_o5tugssje4h6pjnvvhsn6l7loc@group.calendar.google.com", + "displayName": "NSL Season 4 Confirmed Match Schedule", + "self": true + }, + "start": { + "dateTime": "2014-04-03T14:30:00-04:00" + }, + "end": { + "dateTime": "2014-04-03T16:30:00-04:00" + }, + "visibility": "public", + "iCalUID": "274hn9kkkff6hme7k6de1aun9s@google.com", + "sequence": 2 + }, + { + "kind": "calendar#event", + "etag": "\"2DaeHpkENZGECFHdcr5l8tYxjD4/MTM5NjE5MjY3Nzg0MTAwMA\"", + "id": "ucrpfl5eeoldr1g29cq35s56o0", + "status": "confirmed", + "htmlLink": "https://www.google.com/calendar/event?eid=dWNycGZsNWVlb2xkcjFnMjljcTM1czU2bzAgdnQuZWR1X281dHVnc3NqZTRoNnBqbnZ2aHNuNmw3bG9jQGc", + "created": "2014-03-27T22:22:21.000Z", + "updated": "2014-03-30T15:17:57.841Z", + "summary": "Div 2A: Cheesecake vs. Gorge Casting Couch (http://www.twitch.tv/ggKaneh)", + "description": "http://www.ensl.org/matches/5530\n\nWeek 1 Matchup.\n\nReferee: Danjio\nCaster: Kaneh\nStream: http://www.twitch.tv/ggKaneh", + "creator": { + "email": "pelargir.lsa@gmail.com", + "displayName": "Pelargir Chazalet" + }, + "organizer": { + "email": "vt.edu_o5tugssje4h6pjnvvhsn6l7loc@group.calendar.google.com", + "displayName": "NSL Season 4 Confirmed Match Schedule", + "self": true + }, + "start": { + "dateTime": "2014-03-30T15:00:00-04:00" + }, + "end": { + "dateTime": "2014-03-30T17:00:00-04:00" + }, + "visibility": "public", + "iCalUID": "ucrpfl5eeoldr1g29cq35s56o0@google.com", + "sequence": 2 + }, + { + "kind": "calendar#event", + "etag": "\"2DaeHpkENZGECFHdcr5l8tYxjD4/MTM5NjI3Mzk4OTc0MzAwMA\"", + "id": "4dtgq7c1mk583gjglomk60tn80", + "status": "confirmed", + "htmlLink": "https://www.google.com/calendar/event?eid=NGR0Z3E3YzFtazU4M2dqZ2xvbWs2MHRuODAgdnQuZWR1X281dHVnc3NqZTRoNnBqbnZ2aHNuNmw3bG9jQGc", + "created": "2014-03-31T13:53:09.000Z", + "updated": "2014-03-31T13:53:09.743Z", + "summary": "Div 3B: OMNOM vs. Mister (twitch.tv/LoopyCaster)", + "description": "http://www.ensl.org/matches/5473\n\nWeek 1 Matchup.\n\nReferee: \nCasters! Schwa & Loopy\nStream: http://www.twitch.tv/LoopyCaster", + "creator": { + "email": "pelargir.lsa@gmail.com", + "displayName": "Pelargir Chazalet" + }, + "organizer": { + "email": "vt.edu_o5tugssje4h6pjnvvhsn6l7loc@group.calendar.google.com", + "displayName": "NSL Season 4 Confirmed Match Schedule", + "self": true + }, + "start": { + "dateTime": "2014-04-05T14:00:00-04:00" + }, + "end": { + "dateTime": "2014-04-05T16:00:00-04:00" + }, + "visibility": "public", + "iCalUID": "4dtgq7c1mk583gjglomk60tn80@google.com", + "sequence": 0 + }, + { + "kind": "calendar#event", + "etag": "\"2DaeHpkENZGECFHdcr5l8tYxjD4/MTM5NjI3NDA3NTQzMTAwMA\"", + "id": "do011hdp17c36c8rkoobi6lksk", + "status": "confirmed", + "htmlLink": "https://www.google.com/calendar/event?eid=ZG8wMTFoZHAxN2MzNmM4cmtvb2JpNmxrc2sgdnQuZWR1X281dHVnc3NqZTRoNnBqbnZ2aHNuNmw3bG9jQGc", + "created": "2014-03-24T15:26:11.000Z", + "updated": "2014-03-31T13:54:35.431Z", + "summary": "Div 1: Gnarcolepsy vs. Ant (http://www.twitch.tv/schwaschwa)", + "description": "http://www.ensl.org/matches/5549\n\nWeek 2 matchup.\n\nReferee: \nCaster: Schwa\nStream: http://www.twitch.tv/schwaschwa", + "creator": { + "email": "pelargir.lsa@gmail.com", + "displayName": "Pelargir Chazalet" + }, + "organizer": { + "email": "vt.edu_o5tugssje4h6pjnvvhsn6l7loc@group.calendar.google.com", + "displayName": "NSL Season 4 Confirmed Match Schedule", + "self": true + }, + "start": { + "dateTime": "2014-04-05T15:30:00-04:00" + }, + "end": { + "dateTime": "2014-04-05T17:30:00-04:00" + }, + "visibility": "public", + "iCalUID": "do011hdp17c36c8rkoobi6lksk@google.com", + "sequence": 3 + }, + { + "kind": "calendar#event", + "etag": "\"2DaeHpkENZGECFHdcr5l8tYxjD4/MTM5NjI3NDE2NTMxMzAwMA\"", + "id": "eo46nhg92f1t3domncc0qiejlo", + "status": "confirmed", + "htmlLink": "https://www.google.com/calendar/event?eid=ZW80Nm5oZzkyZjF0M2RvbW5jYzBxaWVqbG8gdnQuZWR1X281dHVnc3NqZTRoNnBqbnZ2aHNuNmw3bG9jQGc", + "created": "2014-03-31T13:56:05.000Z", + "updated": "2014-03-31T13:56:05.313Z", + "summary": "Div 4B: [karvalakki] vs. PinkFluffyGorges (twitch.tv/LoopyCaster)", + "description": "http://www.ensl.org/matches/5584\n\nWeek 2 Matchup.\n\nReferee: \nCaster: Loopy\nStream: http://www.ensl.org/matches/5584", + "creator": { + "email": "pelargir.lsa@gmail.com", + "displayName": "Pelargir Chazalet" + }, + "organizer": { + "email": "vt.edu_o5tugssje4h6pjnvvhsn6l7loc@group.calendar.google.com", + "displayName": "NSL Season 4 Confirmed Match Schedule", + "self": true + }, + "start": { + "dateTime": "2014-04-06T14:00:00-04:00" + }, + "end": { + "dateTime": "2014-04-06T16:00:00-04:00" + }, + "visibility": "public", + "iCalUID": "eo46nhg92f1t3domncc0qiejlo@google.com", + "sequence": 0 + }, + { + "kind": "calendar#event", + "etag": "\"2DaeHpkENZGECFHdcr5l8tYxjD4/MTM5NjI3NDMwNDE1MzAwMA\"", + "id": "1lb8cg9d6m2nl0bs0ude42nplc", + "status": "confirmed", + "htmlLink": "https://www.google.com/calendar/event?eid=MWxiOGNnOWQ2bTJubDBiczB1ZGU0Mm5wbGMgdnQuZWR1X281dHVnc3NqZTRoNnBqbnZ2aHNuNmw3bG9jQGc", + "created": "2014-03-31T13:58:24.000Z", + "updated": "2014-03-31T13:58:24.153Z", + "summary": "Div 3B: Mister vs. HBZ (twitch.tv/vindalo0)", + "description": "http://www.ensl.org/matches/5477\n\nWeek 2 Matchup.\n\nReferee:\nCaster: Vindaloo\nStream: http://www.twitch.tv/vindalo0", + "creator": { + "email": "pelargir.lsa@gmail.com", + "displayName": "Pelargir Chazalet" + }, + "organizer": { + "email": "vt.edu_o5tugssje4h6pjnvvhsn6l7loc@group.calendar.google.com", + "displayName": "NSL Season 4 Confirmed Match Schedule", + "self": true + }, + "start": { + "dateTime": "2014-04-04T16:00:00-04:00" + }, + "end": { + "dateTime": "2014-04-04T18:00:00-04:00" + }, + "visibility": "public", + "iCalUID": "1lb8cg9d6m2nl0bs0ude42nplc@google.com", + "sequence": 0 + } + ] +} \ No newline at end of file diff --git a/spec/services/api/v1/users_collection_spec.rb b/spec/services/api/v1/users_collection_spec.rb index a4844cc..9d29c02 100644 --- a/spec/services/api/v1/users_collection_spec.rb +++ b/spec/services/api/v1/users_collection_spec.rb @@ -1,3 +1,5 @@ +require 'spec_helper' + describe Api::V1::UsersCollection do let(:collection) { Api::V1::UsersCollection.new } diff --git a/spec/support/features/session_helpers.rb b/spec/support/features/session_helpers.rb index b22d459..7a888c5 100644 --- a/spec/support/features/session_helpers.rb +++ b/spec/support/features/session_helpers.rb @@ -6,7 +6,16 @@ module Features fill_in "login_username", with: user.username fill_in "login_password", with: user.raw_password - click_button 'Login' + click_button I18n.t('helpers.submit.user.login') + end + + def change_timezone_for(user, timezone) + visit edit_user_path(user.id) + + click_link I18n.t('profile.locals') + find("option[value='#{timezone}']").select_option + + click_button I18n.t('helpers.submit.user.update') end end end \ No newline at end of file