Skip to content

Commit

Permalink
Merge branch 'feature-store-timezone' into develop
Browse files Browse the repository at this point in the history
Conflicts:
	db/schema.rb

Also added links to visualise projects and sites.
  • Loading branch information
cofiem committed Mar 7, 2015
2 parents 0258258 + 75c77f8 commit f19d90e
Show file tree
Hide file tree
Showing 23 changed files with 226 additions and 20 deletions.
4 changes: 0 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,6 @@ external_modules.log
# ignore test coverage files
/coverage/

# ignore vendor binary files
/vendor/bin/*
/vendor

# ignore generated api documentation
/doc
/.yardoc/
5 changes: 5 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ gem 'gmaps4rails', '< 2'
# git grep --full-name --name-only '.fa-play' $(git rev-list --all) > font-awesome-find.txt

# Don't update this, as site still uses bootstrap v2. Need to update this when bootstrap is updated.
# https://github.com/seyhunak/twitter-bootstrap-rails/tree/38476dbd7f9a99179388bffb101826d844029949
gem 'twitter-bootstrap-rails', git: 'https://github.com/seyhunak/twitter-bootstrap-rails.git', branch: :master, ref: '38476dbd7f'

gem 'bootstrap-timepicker-rails', '~> 0.1.3'
Expand All @@ -69,6 +70,10 @@ gem 'will_paginate', '~> 3.0.7'
gem 'dotiw', git: 'https://github.com/radar/dotiw.git', branch: :master, ref: '89d936adc6'
gem 'recaptcha', '~> 0.3.6', require: 'recaptcha/rails'

# for proper timezone support
gem 'tzinfo', '~> 1.2.2'
gem 'tzinfo-data', '~> 1.2015.1'

# USERS & PERMISSIONS
# -------------------------------------
# https://github.com/plataformatec/devise/blob/master/CHANGELOG.md
Expand Down
4 changes: 4 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,8 @@ GEM
tins (1.3.5)
tzinfo (1.2.2)
thread_safe (~> 0.1)
tzinfo-data (1.2015.1)
tzinfo (>= 1.0.0)
uglifier (2.7.1)
execjs (>= 0.3.0)
json (>= 1.8.0)
Expand Down Expand Up @@ -537,6 +539,8 @@ DEPENDENCIES
therubyracer (~> 0.12.1)
thin (~> 1.6.3)
twitter-bootstrap-rails!
tzinfo (~> 1.2.2)
tzinfo-data (~> 1.2015.1)
uglifier (>= 1.3.0)
uuidtools (~> 2.1.5)
webmock (~> 1.20.4)
Expand Down
2 changes: 2 additions & 0 deletions app/assets/javascripts/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
//= require bootstrap-datepicker
//= require gmaps4rails/gmaps4rails.base
//= require gmaps4rails/gmaps4rails.googlemaps
//= require moment-with-locales.min
//= require moment-timezone-with-data.min
//= require bootstrap
//= require shared
//= require public
Expand Down
4 changes: 2 additions & 2 deletions app/assets/stylesheets/projects.scss
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ $baseFontSize: 14px;

.project_thumbnail {
position: relative;
i {
i.project_permission_icon {
color: $grayDark;
position: absolute;
right: 10px;
bottom: 10px;
top: 10px;
font-size: $baseFontSize * 1.75;
}
}
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ def get_redirect

def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:user_name, :email, :password, :password_confirmation) }
devise_parameter_sanitizer.for(:account_update) { |u| u.permit(:user_name, :email, :password, :password_confirmation, :current_password, :image) }
devise_parameter_sanitizer.for(:account_update) { |u| u.permit(:user_name, :email, :password, :password_confirmation, :current_password, :image, :tzinfo_tz) }
end

private
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/sites_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ def get_user_sites
end

def site_params
params.require(:site).permit(:name, :latitude, :longitude, :description, :image, :notes)
params.require(:site).permit(:name, :latitude, :longitude, :description, :image, :notes, :tzinfo_tz)
end

def site_show_params
Expand Down
11 changes: 11 additions & 0 deletions app/models/site.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ class Site < ActiveRecord::Base

validates_attachment_content_type :image, content_type: /^image\/(jpg|jpeg|pjpeg|png|x-png|gif)$/, message: 'file type %{value} is not allowed (only jpeg/png/gif images)'

before_save :set_rails_tz, if: Proc.new { |site| site.tzinfo_tz_changed? }

# commonly used queries
#scope :specified_sites, lambda { |site_ids| where('id in (:ids)', { :ids => site_ids } ) }
#scope :sites_in_project, lambda { |project_ids| where(Project.specified_projects, { :ids => project_ids } ) }
Expand Down Expand Up @@ -133,4 +135,13 @@ def self.filter_settings
}
}
end

def set_rails_tz
tzInfo_id = TimeZoneHelper.to_identifier(self.tzinfo_tz)
rails_tz_string = TimeZoneHelper.tzinfo_to_ruby(tzInfo_id)
unless rails_tz_string.blank?
self.rails_tz = rails_tz_string
end
end

end
10 changes: 10 additions & 0 deletions app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ def login

after_create :special_after_create_actions

before_save :set_rails_tz, if: Proc.new { |user| user.tzinfo_tz_changed? }

def projects
# TODO tidy up user project accessing - too many ways to do the same thing
(self.created_projects.includes(:sites, :creator) + self.accessible_projects.includes(:sites, :creator)).uniq.sort { |a, b| a.name.downcase <=> b.name.downcase }
Expand Down Expand Up @@ -407,4 +409,12 @@ def generate_authentication_token
end
end

def set_rails_tz
tzInfo_id = TimeZoneHelper.to_identifier(self.tzinfo_tz)
rails_tz_string = TimeZoneHelper.tzinfo_to_ruby(tzInfo_id)
unless rails_tz_string.blank?
self.rails_tz = rails_tz_string
end
end

end
1 change: 1 addition & 0 deletions app/views/devise/registrations/edit.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
.form-inputs
= f.input :user_name, required: true, autofocus: true
= f.input :email, required: true
= render partial: '/shared/time_zone_select_custom', locals: { f: f, attribute_name: :tzinfo_tz, model_name: resource_name }
- if devise_mapping.confirmable? && resource.pending_reconfirmation?
%p
Currently waiting confirmation for: #{resource.unconfirmed_email}
Expand Down
2 changes: 1 addition & 1 deletion app/views/layouts/application.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
= javascript_include_tag 'application'

%body
= render partial: '/navbar'
= render partial: '/shared/navbar'

.container

Expand Down
13 changes: 9 additions & 4 deletions app/views/projects/_project_thumb_large.html.haml
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
%li.span6
= link_to project , class: 'thumbnail right-caption span12 project_thumbnail' do
.thumbnail.right-caption.span12.project_thumbnail
.span4= image_tag project.image.url(:span2)
.caption.span7
%h4= project.name
%h4= link_to project.name, project
%p= truncate(project.description, length: 50, separator: ' ')
- if current_user.can_write?(project)
%i.fa.fa-unlock(title="You have read & write access" data-toggle='tooltip' data-placement='top')
%i.project_permission_icon.fa.fa-unlock(title="You have read & write access" data-toggle='tooltip' data-placement='top')
- elsif current_user.can_read?(project)
%i.fa.fa-lock(title="You have read only access" data-toggle='tooltip' data-placement='top')
%i.project_permission_icon.fa.fa-lock(title="You have read only access" data-toggle='tooltip' data-placement='top')
%ul.nav.nav-pills.nav-stacked.pull-right{style: 'margin-bottom:0'}
%li
%a{href: "/visualize?projectId=#{project.id}"}
%i.fa.fa-eye
Visualise
File renamed without changes.
68 changes: 68 additions & 0 deletions app/views/shared/_time_zone_select_custom.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
- control_id = "#{model_name}_#{attribute_name}"
- span_id = "#{control_id}_appended_info"
- help_id = "#{control_id}_appended_help"
.control-group.string.optional{class: control_id }
= f.label attribute_name, 'Time Zone', class: 'string optional control-label', for: control_id
.controls
.input-append
= f.input_field attribute_name, type: 'text', autocomplete: 'off', class: 'span12'
%span.add-on{id: span_id, title: 'Time zone abbreviation and current UTC offset'}
(no match)
%p.help-block{id: help_id }

:javascript
var mapping = #{TimeZoneHelper.mapping_zone_to_offset.to_json}
var mapping_keys = Object.keys(mapping);
var mapping_values = Object.keys(mapping).map(function (key) { return mapping[key]; });

$('##{control_id}').typeahead({
'source': Object.keys(mapping),
'minLength': 2,
'items': 10
});

$('##{control_id}').on('change keydown keypress', function(){
checkTimeZone();
});

function checkTimeZone(){
var enteredValue = $('##{control_id}').val();
var mappingValue = mapping[enteredValue];

var appendedInfo = $('##{span_id}');
var helpInfo = $('##{help_id}');
if(mappingValue){
appendedInfo.text(mappingValue);

var momentTimezoneName = enteredValue;

// to make this match with moment js
// replace dashes with slashes
var momentTimezoneName = momentTimezoneName.replace(' - ', '/');
var momentTimezoneName = momentTimezoneName.replace("'", '');

// move place name after comma
var commaIndex = momentTimezoneName.indexOf(', ');
if (commaIndex >= 0){
var toMove = momentTimezoneName.substring(commaIndex + 2);
momentTimezoneName = momentTimezoneName.replace('/', '/' + toMove + '/');
momentTimezoneName = momentTimezoneName.substring(0,momentTimezoneName.indexOf(', '));
}

// replace spaces with underscores
var momentTimezoneName = momentTimezoneName.replace(' ', '_');

var origTime = moment().tz(momentTimezoneName);
var formatted = origTime.format("dddd, MMMM Do YYYY, h:mm:ss a z Z")
helpInfo.text('Currently: ' + formatted);
} else {
appendedInfo.text('(no match)');
helpInfo.text('(no match)');
}
}

// check time zone when page loads
$(document).ready(function() {
checkTimeZone();
});

8 changes: 5 additions & 3 deletions app/views/sites/_form.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@
= f.input :description, input_html: {rows: '6', class: 'span12' }
= f.input :latitude, input_html: { class: 'span12', max: 90, min: -90 }
= f.input :longitude, input_html: { class: 'span12', max: 180, min: -180 }
.control_group
.control_group.file.optional{class: :site_image}
= f.label :image
.controls
- unless @site.image_file_name.blank?
= image_tag @site.image.url(:span1)
= f.file_field :image
= image_tag @site.image.url, class: 'file optional span4'
= f.file_field :image, class: 'span8'
.clearfix
= render partial: '/shared/time_zone_select_custom', locals: { f: f, attribute_name: :tzinfo_tz, model_name: :site }
.span6= gmaps(markers: {data: @markers, options: { draggable: true } },
map_options: gmaps_default_options )
.row-fluid
Expand Down
9 changes: 7 additions & 2 deletions app/views/sites/_site_thumb_large.html.haml
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
%li.span12
= link_to [@project, site] , class: 'thumbnail right-caption span12' do
.thumbnail.right-caption.span12
= image_tag site.image.url(:span1)
.caption
%h3= site.name
%h3= link_to site.name, [@project, site]
%ul.nav.nav-pills.nav-stacked.pull-right{style: 'margin-bottom:0'}
%li
%a{href: "/visualize?siteId=#{site.id}"}
%i.fa.fa-eye
Visualise


2 changes: 1 addition & 1 deletion app/views/user_accounts/_form.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
- [:confirmed_at,:reset_password_sent_at, :remember_created_at, :sign_in_count, :last_seen_at,
:current_sign_in_at, :last_sign_in_at, :current_sign_in_ip, :last_sign_in_ip,
:confirmation_sent_at, :failed_attempts,:locked_at, :created_at, :updated_at,
:roles_mask, :image_updated_at].each do |item|
:roles_mask, :image_updated_at, :tzinfo_tz, :rails_tz].each do |item|
= render partial: "user_accounts/static_info", locals: {user_attribute_name: item, user: @user}
.control_group
= f.label :image
Expand Down
5 changes: 5 additions & 0 deletions config/application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,11 @@ class Application < Rails::Application
#config.time_zone - 'UTC'
config.time_zone = 'Brisbane'

# config.active_record.default_timezone determines whether to use Time.local (if set to :local)
# or Time.utc (if set to :utc) when pulling dates and times from the database.
# The default is :utc.
#config.active_record.default_timezone = :utc

# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}')]
config.i18n.default_locale = 'en-AU'
Expand Down
2 changes: 1 addition & 1 deletion config/initializers/assets.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
Rails.application.config.assets.version = '1.0'

# Add additional assets to the asset load path
# Rails.application.config.assets.paths << Emoji.images_path
Rails.application.config.assets.paths << Rails.root.join('vendor', 'assets').to_path

# Precompile additional assets.
# application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
Expand Down
11 changes: 11 additions & 0 deletions db/migrate/20150306224910_add_timezone_columns.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
class AddTimezoneColumns < ActiveRecord::Migration
def change
add_column :users, :tzinfo_tz, :string, null: true, limit: 255
add_column :users, :rails_tz, :string, null: true, limit: 255

add_column :sites, :tzinfo_tz, :string, null: true, limit: 255
add_column :sites, :rails_tz, :string, null: true, limit: 255

add_column :audio_recordings, :recorded_utc_offset, :string, null: true, limit: 20
end
end
64 changes: 64 additions & 0 deletions lib/modules/time_zone_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
require 'tzinfo'
require 'active_support'

class TimeZoneHelper
class << self
def mapping_zone_to_offset
Hash[
TZInfo::Timezone.all.map do |tz|
this_tz = TZInfo::Timezone.get(tz.identifier)
period = this_tz.current_period
abbr = period.abbreviation
offset = period.utc_total_offset # in seconds
offset_hours = offset / (60 * 60)
offset_minutes = (offset % 60).to_s.rjust(2, '0')

if offset_hours < 0
offset_hours = (offset_hours * -1).to_s.rjust(2, '0')
offset_hours = '-' + offset_hours
else
offset_hours = '+'+ offset_hours.to_s.rjust(2, '0')
end

[
tz.to_s,
"#{abbr} (#{offset_hours}:#{offset_minutes})"
]
end
]
end

def to_identifier(friendly_name)
found = TZInfo::Timezone.all.select { |tz| friendly_name == tz.friendly_identifier}
if found.size == 1
found[0].identifier
else
nil
end
end

def to_friendly(identifier)
found = TZInfo::Timezone.all.select { |tz| identifier == tz.identifier}
if found.size == 1
found[0].friendly_identifier
else
nil
end
end

# Get the TZInfo Timezone equivalent to the Ruby TimeZone.
# @param [string] ruby_tz_name
# @return [TZInfo::Timezone] TZInfo Timezone
def ruby_to_tzinfo(ruby_tz_name)
TZInfo::Timezone.get(ActiveSupport::TimeZone::MAPPING[ruby_tz_name])
end

# Get the Ruby TimeZone equivalent to the TZInfo Timezone.
# @param [string] tzinfo_tz_name
# @return [string] Ruby Timezone
def tzinfo_to_ruby(tzinfo_tz_name)
ActiveSupport::TimeZone::MAPPING.invert[tzinfo_tz_name]
end

end
end
7 changes: 7 additions & 0 deletions vendor/assets/javascripts/moment-timezone-with-data.min.js

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions vendor/assets/javascripts/moment-with-locales.min.js

Large diffs are not rendered by default.

0 comments on commit f19d90e

Please sign in to comment.