update with changes from Production branch
This commit is contained in:
@ -1,42 +1,50 @@
|
||||
class ApiKeysController < ApplicationController
|
||||
include KeyUtilities
|
||||
include KeyUtilities, ApiKeys
|
||||
|
||||
before_filter :require_user, :set_channels_menu
|
||||
before_filter :require_user, :set_channels_menu
|
||||
|
||||
def index
|
||||
@channel = current_user.channels.find(params[:channel_id])
|
||||
@write_key = @channel.api_keys.write_keys.first
|
||||
@read_keys = @channel.api_keys.read_keys
|
||||
end
|
||||
def index
|
||||
api_index params[:channel_id]
|
||||
end
|
||||
|
||||
def destroy
|
||||
current_user.api_keys.find_by_api_key(params[:id]).try(:destroy)
|
||||
redirect_to :back
|
||||
end
|
||||
def destroy
|
||||
current_user.api_keys.find_by_api_key(params[:id]).try(:destroy)
|
||||
redirect_to :back
|
||||
end
|
||||
|
||||
def create
|
||||
@channel = current_user.channels.find(params[:channel_id])
|
||||
@api_key = @channel.api_keys.write_keys.first
|
||||
def create
|
||||
@channel = current_user.channels.find(params[:channel_id])
|
||||
@api_key = @channel.api_keys.write_keys.first
|
||||
|
||||
# if no api key found or read api key
|
||||
if (@api_key.nil? or params[:write] == '0')
|
||||
@api_key = ApiKey.new
|
||||
@api_key.channel_id = @channel.id
|
||||
@api_key.user_id = current_user.id
|
||||
@api_key.write_flag = params[:write]
|
||||
end
|
||||
# if no api key found or read api key
|
||||
if (@api_key.nil? || params[:write] == '0')
|
||||
@api_key = ApiKey.new
|
||||
@api_key.channel_id = @channel.id
|
||||
@api_key.user_id = current_user.id
|
||||
@api_key.write_flag = params[:write]
|
||||
end
|
||||
|
||||
# set new api key and save
|
||||
@api_key.api_key = generate_api_key
|
||||
@api_key.save
|
||||
# set new api key and save
|
||||
@api_key.api_key = generate_api_key
|
||||
@api_key.save
|
||||
|
||||
# redirect
|
||||
redirect_to channel_api_keys_path(@channel)
|
||||
end
|
||||
# redirect
|
||||
# redirect_to channel_api_keys_path(@channel.id)
|
||||
redirect_to channel_path(@channel.id, :anchor => "apikeys")
|
||||
end
|
||||
|
||||
def update
|
||||
@api_key = current_user.api_keys.find_by_api_key(params[:id])
|
||||
@api_key.update_attributes(api_key_params)
|
||||
redirect_to :back
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# only allow these params
|
||||
def api_key_params
|
||||
params.require(:api_key).permit(:note)
|
||||
end
|
||||
|
||||
def update
|
||||
@api_key = current_user.api_keys.find_by_api_key(params[:id])
|
||||
@api_key.update_attributes(params[:api_key])
|
||||
redirect_to :back
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1,51 +1,134 @@
|
||||
class ApplicationController < ActionController::Base
|
||||
# include all helpers for controllers
|
||||
# include all helpers for controllers
|
||||
helper :all
|
||||
# include these helper methods for views
|
||||
helper_method :current_user_session, :current_user, :get_header_value
|
||||
# include these helper methods for views
|
||||
helper_method :current_user_session, :current_user, :logged_in?, :is_admin?, :get_header_value, :to_bytes
|
||||
protect_from_forgery
|
||||
before_filter :set_variables
|
||||
before_filter :allow_cross_domain_access, :set_variables
|
||||
|
||||
# set up some variables across the entire application
|
||||
# responds with blank
|
||||
def respond_with_blank
|
||||
respond_to do |format|
|
||||
format.html { render :text => '' }
|
||||
format.json { render :json => {}.to_json }
|
||||
# fix xml response line breaks
|
||||
format.xml { render :xml => {}.to_xml.gsub("\n", '').gsub("<hash>", "\n<hash>") }
|
||||
end
|
||||
end
|
||||
|
||||
# responds with an error
|
||||
def respond_with_error(error_code)
|
||||
error_response = ErrorResponse.new(error_code)
|
||||
respond_to do |format|
|
||||
format.html { render :text => error_response.error_code, :status => error_response.http_status }
|
||||
format.json { render :json => error_response.to_json, :status => error_response.http_status }
|
||||
format.xml { render :xml => error_response.to_xml, :status => error_response.http_status }
|
||||
end
|
||||
end
|
||||
|
||||
# set up some variables across the entire application
|
||||
def set_variables
|
||||
@api_domain ||= api_domain
|
||||
@ssl_api_domain ||= ssl_api_domain
|
||||
@locale ||= get_locale
|
||||
I18n.locale = ALLOWED_LOCALES.include?(@locale) ? @locale : I18n.default_locale
|
||||
I18n.locale = @locale
|
||||
# sets timezone for current user, all DateTime outputs will be automatically formatted
|
||||
Time.zone = current_user.time_zone if current_user
|
||||
end
|
||||
|
||||
|
||||
# get the locale, but don't fail if header value doesn't exist
|
||||
def get_locale
|
||||
locale = get_header_value('HTTP_ACCEPT_LANGUAGE')
|
||||
# only look for 'pt-br' as first 5 letters, can make more robust in future if other languages are needed
|
||||
locale = locale[0..4].downcase if locale
|
||||
|
||||
if locale and ALLOWED_LOCALES.include?(locale[0..1].downcase)
|
||||
locale = locale[0..1].downcase
|
||||
elsif locale and ALLOWED_LOCALES.include?(locale[0..4].downcase)
|
||||
locale = locale[0..4].downcase
|
||||
else
|
||||
locale = I18n.default_locale
|
||||
end
|
||||
|
||||
return locale
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_channels_menu
|
||||
@menu = 'channels'
|
||||
end
|
||||
# allow javascript requests from any domain
|
||||
def allow_cross_domain_access
|
||||
response.headers['Access-Control-Allow-Origin'] = '*'
|
||||
response.headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, OPTIONS, DELETE, PATCH'
|
||||
response.headers['Access-Control-Allow-Headers'] = 'origin, content-type, X-Requested-With'
|
||||
response.headers['Access-Control-Max-Age'] = '1800'
|
||||
end
|
||||
|
||||
def logged_in?
|
||||
true if current_user
|
||||
end
|
||||
|
||||
# check that user's email address matches admin
|
||||
def is_admin?
|
||||
current_user && ADMIN_EMAILS.include?(current_user.email)
|
||||
end
|
||||
|
||||
def set_admin_menu
|
||||
@menu = 'admin'
|
||||
end
|
||||
|
||||
# converts a string to a byte string for c output
|
||||
def to_bytes(input, separator='.', prefix='')
|
||||
return '' if input == nil
|
||||
output = []
|
||||
# split the input array using the separator, and add necessary prefixes to each item
|
||||
input.split(separator).each { |i| output.push(prefix + i) }
|
||||
# rejoin the array into a comma separated string
|
||||
return output.join(', ')
|
||||
end
|
||||
|
||||
def set_channels_menu
|
||||
@menu = 'channels'
|
||||
end
|
||||
|
||||
def set_apps_menu
|
||||
@menu = 'apps'
|
||||
end
|
||||
|
||||
def set_plugins_menu
|
||||
@menu = 'plugins'
|
||||
end
|
||||
|
||||
def set_devices_menu
|
||||
@menu = 'devices'
|
||||
end
|
||||
|
||||
def current_user_session
|
||||
return @current_user_session if defined?(@current_user_session)
|
||||
@current_user_session = UserSession.find
|
||||
end
|
||||
|
||||
|
||||
def current_user
|
||||
return @current_user if defined?(@current_user)
|
||||
@current_user = current_user_session && current_user_session.record
|
||||
end
|
||||
|
||||
# check that user is logged in
|
||||
def require_user
|
||||
if current_user.nil?
|
||||
redirect_to login_path
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def require_user
|
||||
logger.info "Require User"
|
||||
if current_user.nil?
|
||||
respond_to do |format|
|
||||
format.html {
|
||||
session[:link_back] = request.url
|
||||
logger.debug "Redirecting to login"
|
||||
redirect_to login_path
|
||||
return true
|
||||
}
|
||||
format.json do
|
||||
render :json => {'error' => 'Could not authenticate you.'}, :status => :unauthorized
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
def require_no_user
|
||||
if current_user
|
||||
store_location
|
||||
@ -54,142 +137,205 @@ class ApplicationController < ActionController::Base
|
||||
end
|
||||
end
|
||||
|
||||
def store_location
|
||||
if params[:controller] != "user_sessions"
|
||||
session[:return_to] = request.fullpath
|
||||
end
|
||||
def require_admin
|
||||
unless current_user && is_admin?
|
||||
render :nothing => true, :status => 403 and return
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def store_location
|
||||
if params[:controller] != "user_sessions"
|
||||
session[:return_to] = request.fullpath
|
||||
end
|
||||
end
|
||||
|
||||
def redirect_back_or_default(default)
|
||||
redirect_to(session[:return_to] || default)
|
||||
session[:return_to] = nil
|
||||
end
|
||||
|
||||
def domain
|
||||
u = request.url
|
||||
begin
|
||||
# the number 12 is the position at which to begin searching for '/', so we don't get the intitial '/' from http://
|
||||
u = u[0..u.index('/', 12)]
|
||||
rescue
|
||||
u += '/'
|
||||
end
|
||||
# uncomment the line below for https support in a production environment
|
||||
#u = u.sub(/http:/, 'https:') if Rails.env == 'production'
|
||||
return u
|
||||
end
|
||||
def domain(ssl=true)
|
||||
u = request.url
|
||||
begin
|
||||
# the number 12 is the position at which to begin searching for '/', so we don't get the intitial '/' from http://
|
||||
u = u[0..u.index('/', 12)]
|
||||
rescue
|
||||
u += '/'
|
||||
end
|
||||
u = u.sub(/http:/, 'https:') if (Rails.env == 'production' and ssl)
|
||||
return u
|
||||
end
|
||||
|
||||
# gets the api key
|
||||
def get_userkey
|
||||
return get_header_value('THINGSPEAKAPIKEY') || params[:key] || params[:api_key] || params[:apikey]
|
||||
end
|
||||
def ssl
|
||||
(Rails.env == 'production') ? 'https' : 'http'
|
||||
end
|
||||
|
||||
# get specified header value
|
||||
def get_header_value(name)
|
||||
value = nil
|
||||
for header in request.env
|
||||
value = header[1] if (header[0].upcase.index(name.upcase))
|
||||
end
|
||||
return value
|
||||
end
|
||||
# domain for the api
|
||||
def api_domain
|
||||
(Rails.env == 'production') ? API_DOMAIN : domain
|
||||
end
|
||||
|
||||
# ssl domain for the api
|
||||
def ssl_api_domain; (Rails.env == 'production') ? api_domain.sub('http', 'https'): api_domain; end
|
||||
|
||||
# gets the api key
|
||||
def get_apikey
|
||||
key = get_header_value(HTTP_HEADER_API_KEY_NAME) || params[:key] || params[:api_key] || params[:apikey]
|
||||
key.strip if key.present?
|
||||
return key
|
||||
end
|
||||
|
||||
# get specified header value
|
||||
def get_header_value(name)
|
||||
name.upcase!
|
||||
request.env.select {|header| header.upcase.index(name) }.values[0]
|
||||
end
|
||||
|
||||
# generates a hash key unique to the user and url
|
||||
def cache_key(type)
|
||||
cache_key = request.host + request.path
|
||||
user_id = current_user ? current_user.id : '0'
|
||||
|
||||
params.each do |key, value|
|
||||
# add the parameter if appropriate
|
||||
cache_key += "&#{key}=#{value}" if key != 'callback' && key != 'controller' && key != 'action' && key != 'format'
|
||||
end
|
||||
|
||||
return "#{user_id}-#{type}-#{cache_key}"
|
||||
end
|
||||
|
||||
# reads a file using the relative path to the file
|
||||
def read_file(file_path)
|
||||
path = file_path[0, file_path.rindex('/')]
|
||||
filename = file_path[file_path.rindex('/') + 1, file_path.length]
|
||||
output = ''
|
||||
|
||||
File.open("#{File.expand_path(path)}/#{filename}", 'r') do |f|
|
||||
while line = f.gets
|
||||
output += line
|
||||
end
|
||||
end
|
||||
|
||||
return output
|
||||
end
|
||||
|
||||
# prepends or appends text
|
||||
def add_prepend_append(input)
|
||||
output = input.to_s
|
||||
output = params[:prepend] + output if params[:prepend]
|
||||
output += params[:append] if params[:append]
|
||||
return output
|
||||
end
|
||||
|
||||
# gets the same data for showing or editing
|
||||
def get_channel_data
|
||||
@channel = current_user.channels.find(params[:channel_id]) if params[:channel_id]
|
||||
@channel = current_user.channels.find(params[:id]) if @channel.nil? and params[:id]
|
||||
|
||||
if @channel.ranking.blank?
|
||||
@channel.ranking = @channel.calc_ranking
|
||||
end
|
||||
|
||||
@key = @channel.api_keys.write_keys.first.try(:api_key) || ""
|
||||
end
|
||||
|
||||
def check_permissions(channel)
|
||||
render :text => t(:channel_permission) and return if (current_user.nil? || (channel.user_id != current_user.id))
|
||||
end
|
||||
def check_permissions(channel)
|
||||
render :text => t(:channel_permission) and return if (current_user.nil? || (channel.user_id != current_user.id))
|
||||
end
|
||||
|
||||
# checks permission for channel using api_key
|
||||
def channel_permission?(channel, api_key)
|
||||
if channel.public_flag or (api_key and api_key.channel_id == channel.id) or (current_user and channel.user_id == current_user.id)
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
# checks permission for channel using api_key
|
||||
def channel_permission?(channel, api_key)
|
||||
if channel.public_flag or (api_key and api_key.channel_id == channel.id) or (current_user and channel.user_id == current_user.id)
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
# outputs error for bad channel
|
||||
def bad_channel_xml
|
||||
channel_unauthorized = Channel.new
|
||||
channel_unauthorized.id = -1
|
||||
return channel_unauthorized.to_xml(:only => :id)
|
||||
end
|
||||
# outputs error for bad channel
|
||||
def bad_channel_xml
|
||||
channel_unauthorized = Channel.new
|
||||
channel_unauthorized.id = -1
|
||||
return channel_unauthorized.to_xml(:only => :id)
|
||||
end
|
||||
|
||||
# outputs error for bad feed
|
||||
def bad_feed_xml
|
||||
feed_unauthorized = Feed.new
|
||||
feedl_unauthorized.id = -1
|
||||
return feed_unauthorized.to_xml(:only => :entry_id)
|
||||
end
|
||||
# outputs error for bad feed
|
||||
def bad_feed_xml
|
||||
feed_unauthorized = Feed.new
|
||||
feed_unauthorized.id = -1
|
||||
return feed_unauthorized.to_xml(:only => :entry_id)
|
||||
end
|
||||
|
||||
# options: days = how many days ago, start = start date, end = end date, offset = timezone offset
|
||||
def get_date_range(params)
|
||||
# set timezone correctly
|
||||
set_time_zone(params)
|
||||
# options: days = how many days ago, start = start date, end = end date, offset = timezone offset
|
||||
def get_date_range(params)
|
||||
# set timezone correctly
|
||||
set_time_zone(params)
|
||||
|
||||
# if results are specified without start or days parameters, allow start date to be larger
|
||||
get_old_data = (params[:results] && params[:start].blank? and params[:days].blank?) ? true : false
|
||||
# allow more past data if necessary
|
||||
get_old_data = (params[:results].present? || params[:start].present? || params[:days].present?) ? true : false
|
||||
|
||||
start_date = (get_old_data) ? (Time.now - 1.year) : (Time.now - 1.day)
|
||||
end_date = Time.now
|
||||
start_date = (Time.now - params[:days].to_i.days) if params[:days]
|
||||
start_date = DateTime.strptime(params[:start]) if params[:start]
|
||||
end_date = DateTime.strptime(params[:end]) if params[:end]
|
||||
date_range = (start_date..end_date)
|
||||
# only get a maximum of 30 days worth of data
|
||||
date_range = (end_date - 30.days..end_date) if ((end_date - start_date) > 30.days and !get_old_data)
|
||||
|
||||
return date_range
|
||||
end
|
||||
start_date = (get_old_data) ? Time.parse('2010-01-01') : (Time.now - 1.day)
|
||||
end_date = Time.now
|
||||
start_date = (Time.now - params[:days].to_i.days) if params[:days]
|
||||
start_date = DateTime.parse(params[:start]) if params[:start]
|
||||
end_date = DateTime.parse(params[:end]) if params[:end]
|
||||
date_range = (start_date..end_date)
|
||||
# only get a maximum of 30 days worth of data
|
||||
date_range = (end_date - 30.days..end_date) if ((end_date - start_date) > 30.days and !get_old_data)
|
||||
return date_range
|
||||
end
|
||||
|
||||
|
||||
def is_a_number?(s)
|
||||
s.to_s.gsub(/,/, '.').match(/\A[+-]?\d+?(\.\d+)?\Z/) == nil ? false : true
|
||||
end
|
||||
|
||||
def set_time_zone(params)
|
||||
# set timezone correctly
|
||||
if params[:offset]
|
||||
def set_time_zone(params)
|
||||
# set timezone correctly
|
||||
if params[:offset]
|
||||
# check for 0 offset first since it's the most common
|
||||
if params[:offset] == '0'
|
||||
Time.zone = 'UTC'
|
||||
else
|
||||
Time.zone = set_timezone_from_offset(params[:offset])
|
||||
Time.zone = set_timezone_from_offset(params[:offset])
|
||||
end
|
||||
elsif current_user
|
||||
Time.zone = current_user.time_zone
|
||||
else
|
||||
Time.zone = 'UTC'
|
||||
end
|
||||
end
|
||||
elsif current_user
|
||||
Time.zone = current_user.time_zone
|
||||
else
|
||||
Time.zone = 'UTC'
|
||||
end
|
||||
end
|
||||
|
||||
# use the offset to find an appropriate timezone
|
||||
def set_timezone_from_offset(offset)
|
||||
offset = offset.to_i
|
||||
# keep track of whether a match was found
|
||||
found = false
|
||||
|
||||
|
||||
# loop through each timezone
|
||||
ActiveSupport::TimeZone.zones_map.each do |z|
|
||||
# set time zone
|
||||
Time.zone = z[0]
|
||||
timestring = Time.zone.now.to_s
|
||||
|
||||
|
||||
# if time zone matches the offset, leave it as the current timezone
|
||||
if (timestring.slice(-5..-3).to_i == offset and timestring.slice(-2..-1).to_i == 0)
|
||||
found = true
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# if no time zone found, set to utc
|
||||
Time.zone = 'UTC' if !found
|
||||
|
||||
|
||||
return Time.zone
|
||||
end
|
||||
|
||||
def help
|
||||
Helper.instance
|
||||
end
|
||||
|
||||
class Helper
|
||||
include Singleton
|
||||
include ActionView::Helpers::TextHelper
|
||||
end
|
||||
end
|
||||
|
||||
|
9
app/controllers/apps_controller.rb
Normal file
9
app/controllers/apps_controller.rb
Normal file
@ -0,0 +1,9 @@
|
||||
class AppsController < ApplicationController
|
||||
|
||||
def index
|
||||
@menu = 'apps'
|
||||
@title = 'Internet of Things Apps' if current_user.nil?
|
||||
# @twitters = TwitterAccount.find(:all, :conditions => { :user_id => current_user.id }) if current_user
|
||||
end
|
||||
|
||||
end
|
@ -1,258 +1,474 @@
|
||||
class ChannelsController < ApplicationController
|
||||
before_filter :require_user, :except => [ :show, :post_data ]
|
||||
before_filter :set_channels_menu
|
||||
protect_from_forgery :except => :post_data
|
||||
require 'csv'
|
||||
include ChannelsHelper, ApiKeys
|
||||
before_filter :require_user, :except => [ :show, :post_data, :social_show, :social_feed, :public]
|
||||
before_filter :set_channels_menu
|
||||
layout 'application', :except => [:social_show, :social_feed]
|
||||
protect_from_forgery :except => :post_data
|
||||
require 'csv'
|
||||
|
||||
def index
|
||||
@channels = current_user.channels
|
||||
end
|
||||
# view list of watched channels
|
||||
def watched
|
||||
@channels = current_user.watched_channels
|
||||
end
|
||||
|
||||
def show
|
||||
@channel = Channel.find(params[:id]) if params[:id]
|
||||
@domain = domain
|
||||
# user watches a channel
|
||||
def watch
|
||||
@watching = Watching.find_by_user_id_and_channel_id(current_user.id, params[:id])
|
||||
|
||||
# if owner of channel
|
||||
get_channel_data if current_user and @channel.user_id == current_user.id
|
||||
end
|
||||
# add watching
|
||||
if params[:flag] == 'true'
|
||||
@watching = Watching.new(:user_id => current_user.id, :channel_id => params[:id]) if @watching.nil?
|
||||
@watching.save
|
||||
# delete watching
|
||||
else
|
||||
@watching.delete if !@watching.nil?
|
||||
end
|
||||
|
||||
def edit
|
||||
get_channel_data
|
||||
end
|
||||
render :text => '1'
|
||||
end
|
||||
|
||||
def update
|
||||
@channel = current_user.channels.find(params[:id])
|
||||
@channel.update_attributes(params[:channel])
|
||||
# list public channels
|
||||
def public
|
||||
# get channels by ids
|
||||
if params[:channel_ids].present?
|
||||
flash[:notice] = t(:selected_channels)
|
||||
@channels = Channel.public_viewable.by_array(params[:channel_ids]).order('ranking desc, updated_at DESC').paginate :page => params[:page]
|
||||
# get channels that match a tag
|
||||
elsif params[:tag].present?
|
||||
flash[:notice] = "#{t(:tag).capitalize}: #{params[:tag]}"
|
||||
@channels = Channel.public_viewable.active.order('ranking desc, updated_at DESC').with_tag(params[:tag]).paginate :page => params[:page]
|
||||
# normal channel list
|
||||
else
|
||||
flash[:notice] = t(:featured_channels)
|
||||
@channels = Channel.public_viewable.active.order('ranking desc, updated_at DESC').paginate :page => params[:page]
|
||||
end
|
||||
|
||||
redirect_to channel_path(@channel.id)
|
||||
end
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.json { render :json => Channel.paginated_hash(@channels).to_json }
|
||||
format.xml { render :xml => Channel.paginated_hash(@channels).to_xml(:root => 'response') }
|
||||
end
|
||||
end
|
||||
|
||||
# widget for social feeds
|
||||
def social_feed
|
||||
# get domain based on ssl
|
||||
@domain = domain((get_header_value('x_ssl') == 'true'))
|
||||
end
|
||||
|
||||
# main page for a socialsensornetwork.com project
|
||||
def social_show
|
||||
@channel = Channel.find_by_slug(params[:slug])
|
||||
|
||||
# redirect home if wrong slug
|
||||
redirect_to '/' and return if @channel.nil?
|
||||
|
||||
api_key = ApiKey.find(:first, :conditions => { :channel_id => @channel.id, :write_flag => 1 } )
|
||||
@post_url = "/update?key=#{api_key.api_key}"
|
||||
|
||||
# names of non-blank channel fields
|
||||
@fields = []
|
||||
@channel.attribute_names.each do |attr|
|
||||
@fields.push(attr) if attr.index('field') and !@channel[attr].blank?
|
||||
end
|
||||
end
|
||||
|
||||
def social_new
|
||||
@channel = Channel.new
|
||||
end
|
||||
|
||||
def social_create
|
||||
@channel = Channel.new(channel_params)
|
||||
|
||||
# check for blank name
|
||||
@channel.errors.add(:base, t(:social_channel_error_name_blank)) if @channel.name.blank?
|
||||
|
||||
# check for blank slug
|
||||
@channel.errors.add(:base, t(:social_channel_error_slug_blank)) if @channel.slug.blank?
|
||||
|
||||
# check for at least one field
|
||||
fields = false
|
||||
@channel.attribute_names.each do |attr|
|
||||
if (attr.index('field') or attr.index('status')) and !@channel[attr].blank?
|
||||
fields = true
|
||||
break
|
||||
end
|
||||
end
|
||||
@channel.errors.add(:base, t(:social_channel_error_fields)) if !fields
|
||||
|
||||
# check for existing slug
|
||||
if @channel.errors.count == 0
|
||||
@channel.errors.add(:base, t(:social_channel_error_slug_exists)) if Channel.find_by_slug(@channel.slug)
|
||||
end
|
||||
|
||||
# if there are no errors
|
||||
if @channel.errors.count == 0
|
||||
@channel.user_id = current_user.id
|
||||
@channel.social = true
|
||||
@channel.public_flag = true
|
||||
@channel.save
|
||||
|
||||
# create an api key for this channel
|
||||
channel.add_write_api_key
|
||||
|
||||
redirect_to channels_path
|
||||
else
|
||||
render :action => :social_new
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def index
|
||||
|
||||
@channels = current_user.channels
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.json { render :json => @channels }
|
||||
end
|
||||
end
|
||||
|
||||
def show
|
||||
|
||||
@channel = Channel.find(params[:id]) if params[:id]
|
||||
|
||||
@title = @channel.name
|
||||
@domain = domain
|
||||
@mychannel = (current_user && current_user.id == @channel.user_id)
|
||||
@width = Chart.default_width
|
||||
@height = Chart.default_height
|
||||
|
||||
api_index @channel.id
|
||||
# if owner of channel
|
||||
get_channel_data if @mychannel
|
||||
respond_to do |format|
|
||||
format.html do
|
||||
if @mychannel
|
||||
render "private_show"
|
||||
session[:errors] = nil
|
||||
else
|
||||
render "public_show"
|
||||
session[:errors] = nil
|
||||
end
|
||||
end
|
||||
format.json { render :json => @channel }
|
||||
end
|
||||
end
|
||||
|
||||
def edit
|
||||
get_channel_data
|
||||
end
|
||||
|
||||
|
||||
def update
|
||||
|
||||
@channel = current_user.channels.find(params[:id])
|
||||
puts params[:channel].inspect
|
||||
# make sure channel isn't social
|
||||
#render :text => '' and return if @channel.social
|
||||
if params["channel"]["video_type"].blank? && !params["channel"]["video_id"].blank?
|
||||
@channel.errors.add(:base, t(:channel_video_type_blank))
|
||||
end
|
||||
if @channel.errors.count <= 0
|
||||
@channel.save_tags(params[:tags][:name])
|
||||
@channel.assign_attributes(channel_params)
|
||||
@channel.set_windows
|
||||
@channel.save
|
||||
else
|
||||
session[:errors] = @channel.errors
|
||||
redirect_to channel_path(@channel.id, :anchor => "channelsettings") and return
|
||||
end
|
||||
|
||||
flash[:notice] = t(:channel_update_success)
|
||||
redirect_to channel_path(@channel.id)
|
||||
|
||||
end
|
||||
|
||||
def create
|
||||
channel = current_user.channels.create(:field1 => "#{t(:channel_default_field)} 1")
|
||||
channel.set_windows
|
||||
channel.save
|
||||
channel.add_write_api_key
|
||||
|
||||
# redirect to edit the newly created channel
|
||||
redirect_to edit_channel_path(channel)
|
||||
@channel_id = channel.id
|
||||
redirect_to channel_path(@channel_id, :anchor => "channelsettings")
|
||||
end
|
||||
|
||||
# clear all data from a channel
|
||||
def clear
|
||||
channel = current_user.channels.find(params[:id])
|
||||
channel.delete_feeds
|
||||
channel.update_attribute(:last_entry_id, nil)
|
||||
redirect_to channel_path(channel.id)
|
||||
end
|
||||
|
||||
def destroy
|
||||
channel = current_user.channels.find(params[:id])
|
||||
channel.destroy
|
||||
redirect_to channels_path
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
channel = current_user.channels.find(params[:id])
|
||||
channel.destroy
|
||||
# response is '0' if failure, 'entry_id' if success
|
||||
def post_data
|
||||
|
||||
redirect_to channels_path
|
||||
end
|
||||
status = '0'
|
||||
feed = Feed.new
|
||||
|
||||
# response is '0' if failure, 'entry_id' if success
|
||||
def post_data
|
||||
status = '0'
|
||||
feed = Feed.new
|
||||
|
||||
api_key = ApiKey.find_by_api_key(get_userkey)
|
||||
api_key = ApiKey.find_by_api_key(get_apikey)
|
||||
|
||||
# if write persmission, allow post
|
||||
if (api_key && api_key.write_flag)
|
||||
channel = Channel.find(api_key.channel_id)
|
||||
# if write permission, allow post
|
||||
if (api_key && api_key.write_flag)
|
||||
channel = api_key.channel
|
||||
|
||||
# update entry_id for channel and feed
|
||||
entry_id = channel.last_entry_id.nil? ? 1 : channel.last_entry_id + 1
|
||||
channel.last_entry_id = entry_id
|
||||
feed.entry_id = entry_id
|
||||
# don't rate limit if tstream parameter is present
|
||||
tstream = params[:tstream] || false;
|
||||
|
||||
# try to get created_at datetime if appropriate
|
||||
if params[:created_at]
|
||||
begin
|
||||
feed.created_at = DateTime.parse(params[:created_at])
|
||||
# if invalid datetime, don't do anything--rails will set created_at
|
||||
rescue
|
||||
end
|
||||
end
|
||||
|
||||
# modify parameters
|
||||
params.each do |key, value|
|
||||
# strip line feeds from end of parameters
|
||||
params[key] = value.sub(/\\n$/, '').sub(/\\r$/, '') if value
|
||||
# use ip address if found
|
||||
params[key] = request.remote_addr if value.upcase == 'IP_ADDRESS'
|
||||
end
|
||||
|
||||
# set feed details
|
||||
feed.channel_id = channel.id
|
||||
feed.raw_data = params
|
||||
feed.field1 = params[:field1] if params[:field1]
|
||||
feed.field2 = params[:field2] if params[:field2]
|
||||
feed.field3 = params[:field3] if params[:field3]
|
||||
feed.field4 = params[:field4] if params[:field4]
|
||||
feed.field5 = params[:field5] if params[:field5]
|
||||
feed.field6 = params[:field6] if params[:field6]
|
||||
feed.field7 = params[:field7] if params[:field7]
|
||||
feed.field8 = params[:field8] if params[:field8]
|
||||
feed.status = params[:status] if params[:status]
|
||||
feed.latitude = params[:lat] if params[:lat]
|
||||
feed.latitude = params[:latitude] if params[:latitude]
|
||||
feed.longitude = params[:long] if params[:long]
|
||||
feed.longitude = params[:longitude] if params[:longitude]
|
||||
feed.elevation = params[:elevation] if params[:elevation]
|
||||
# don't rate limit if talkback_key parameter is present
|
||||
talkback_key = params[:talkback_key] || false;
|
||||
|
||||
if channel.save && feed.save
|
||||
status = entry_id
|
||||
end
|
||||
end
|
||||
|
||||
# output response code
|
||||
render :text => '0', :status => 400 and return if status == '0'
|
||||
render :text => status
|
||||
end
|
||||
# rate limit posts if channel is not social and timespan is smaller than the allowed window
|
||||
render :text => '0' and return if (RATE_LIMIT && !tstream && !talkback_key && !channel.social && Time.now < channel.updated_at + RATE_LIMIT_FREQUENCY.to_i.seconds)
|
||||
|
||||
# if social channel, latitude MUST be present
|
||||
render :text => '0' and return if (channel.social && params[:latitude].blank?)
|
||||
|
||||
# update entry_id for channel and feed
|
||||
entry_id = channel.next_entry_id
|
||||
channel.last_entry_id = entry_id
|
||||
feed.entry_id = entry_id
|
||||
|
||||
# try to get created_at datetime if appropriate
|
||||
if params[:created_at].present?
|
||||
begin
|
||||
feed.created_at = DateTime.parse(params[:created_at])
|
||||
# if invalid datetime, don't do anything--rails will set created_at
|
||||
rescue
|
||||
end
|
||||
end
|
||||
|
||||
# modify parameters
|
||||
params.each do |key, value|
|
||||
# this fails so much due to encoding problems that we need to ignore errors
|
||||
begin
|
||||
# strip line feeds from end of parameters
|
||||
params[key] = value.sub(/\\n$/, '').sub(/\\r$/, '') if value
|
||||
# use ip address if found
|
||||
params[key] = get_header_value('X_REAL_IP') if value.try(:upcase) == 'IP_ADDRESS'
|
||||
rescue
|
||||
end
|
||||
end
|
||||
|
||||
# set feed details
|
||||
feed.channel_id = channel.id
|
||||
feed.field1 = params[:field1] || params['1'] if params[:field1] || params['1']
|
||||
feed.field2 = params[:field2] || params['2'] if params[:field2] || params['2']
|
||||
feed.field3 = params[:field3] || params['3'] if params[:field3] || params['3']
|
||||
feed.field4 = params[:field4] || params['4'] if params[:field4] || params['4']
|
||||
feed.field5 = params[:field5] || params['5'] if params[:field5] || params['5']
|
||||
feed.field6 = params[:field6] || params['6'] if params[:field6] || params['6']
|
||||
feed.field7 = params[:field7] || params['7'] if params[:field7] || params['7']
|
||||
feed.field8 = params[:field8] || params['8'] if params[:field8] || params['8']
|
||||
feed.status = params[:status] if params[:status]
|
||||
feed.latitude = params[:lat] if params[:lat]
|
||||
feed.latitude = params[:latitude] if params[:latitude]
|
||||
feed.longitude = params[:long] if params[:long]
|
||||
feed.longitude = params[:longitude] if params[:longitude]
|
||||
feed.elevation = params[:elevation] if params[:elevation]
|
||||
feed.location = params[:location] if params[:location]
|
||||
|
||||
# if the saves were successful
|
||||
if channel.save && feed.save
|
||||
status = entry_id
|
||||
|
||||
# check for tweet
|
||||
if params[:twitter] && params[:tweet]
|
||||
# check username
|
||||
twitter_account = TwitterAccount.find_by_user_id_and_screen_name(api_key.user_id, params[:twitter])
|
||||
if twitter_account
|
||||
twitter_account.tweet(params[:tweet])
|
||||
end
|
||||
end
|
||||
else
|
||||
raise "Channel or Feed didn't save correctly"
|
||||
end
|
||||
end
|
||||
|
||||
# if there is a talkback to execute
|
||||
if params[:talkback_key].present?
|
||||
talkback = Talkback.find_by_api_key(params[:talkback_key])
|
||||
command = talkback.execute_command! if talkback.present?
|
||||
end
|
||||
|
||||
# output response code
|
||||
render(:text => '0', :status => 400) and return if status == '0'
|
||||
|
||||
# if there is a talkback_key and a command that was executed
|
||||
if params[:talkback_key].present? && command.present?
|
||||
respond_to do |format|
|
||||
format.html { render :text => command.command_string }
|
||||
format.json { render :json => command.to_json }
|
||||
format.xml { render :xml => command.to_xml(Command.public_options) }
|
||||
end and return
|
||||
end
|
||||
|
||||
# if there is a talkback_key but no command
|
||||
respond_with_blank and return if params[:talkback_key].present? && command.blank?
|
||||
|
||||
# normal route, respond with the entry id of the feed
|
||||
render :text => status
|
||||
end
|
||||
|
||||
# import view
|
||||
def import
|
||||
get_channel_data
|
||||
end
|
||||
|
||||
# upload csv file to channel
|
||||
def upload
|
||||
channel = Channel.find(params[:id])
|
||||
check_permissions(channel)
|
||||
|
||||
# if no data
|
||||
if params[:upload].blank? || params[:upload][:csv].blank?
|
||||
flash[:error] = t(:upload_no_file)
|
||||
redirect_to channel_path(channel.id, :anchor => "dataimport") and return
|
||||
end
|
||||
|
||||
# set time zone
|
||||
Time.zone = params[:feed][:time_zone]
|
||||
|
||||
# read data from uploaded file
|
||||
csv_array = CSV.parse(params[:upload][:csv].read)
|
||||
if csv_array.nil? || csv_array.blank?
|
||||
flash[:error] = t(:upload_no_data)
|
||||
redirect_to channel_path(channel.id, :anchor => "dataimport") and return
|
||||
end
|
||||
|
||||
# does the column have headers
|
||||
headers = has_headers?(csv_array)
|
||||
|
||||
# remember the column positions
|
||||
entry_id_column = -1
|
||||
latitude_column = -1
|
||||
longitude_column = -1
|
||||
elevation_column = -1
|
||||
location_column = -1
|
||||
status_column = -1
|
||||
if headers
|
||||
csv_array[0].each_with_index do |column, index|
|
||||
entry_id_column = index if column.downcase == 'entry_id'
|
||||
latitude_column = index if column.downcase == 'latitude'
|
||||
longitude_column = index if column.downcase == 'longitude'
|
||||
elevation_column = index if column.downcase == 'elevation'
|
||||
location_column = index if column.downcase == 'location'
|
||||
status_column = index if column.downcase == 'status'
|
||||
end
|
||||
end
|
||||
|
||||
# delete the first row if it contains headers
|
||||
csv_array.delete_at(0) if headers
|
||||
|
||||
# determine if the date can be parsed
|
||||
parse_date = date_parsable?(csv_array[0][0]) unless csv_array[0].nil? || csv_array[0][0].nil?
|
||||
|
||||
# if 2 or more rows
|
||||
if !csv_array[1].blank?
|
||||
date1 = parse_date ? Time.parse(csv_array[0][0]) : Time.at(csv_array[0][0])
|
||||
date2 = parse_date ? Time.parse(csv_array[1][0]) : Time.at(csv_array[1][0])
|
||||
|
||||
# reverse the array if 1st date is larger than 2nd date
|
||||
csv_array = csv_array.reverse if date1 > date2
|
||||
end
|
||||
|
||||
# loop through each row
|
||||
csv_array.each do |row|
|
||||
# if row isn't blank
|
||||
if !row.blank?
|
||||
feed = Feed.new
|
||||
|
||||
# set location and status then delete the rows
|
||||
# these 5 deletes must be performed in the proper (reverse) order
|
||||
feed.status = row.delete_at(status_column) if status_column > 0
|
||||
feed.location = row.delete_at(location_column) if location_column > 0
|
||||
feed.elevation = row.delete_at(elevation_column) if elevation_column > 0
|
||||
feed.longitude = row.delete_at(longitude_column) if longitude_column > 0
|
||||
feed.latitude = row.delete_at(latitude_column) if latitude_column > 0
|
||||
|
||||
# remove entry_id column if necessary
|
||||
row.delete_at(entry_id_column) if entry_id_column > 0
|
||||
|
||||
# update entry_id for channel and feed
|
||||
entry_id = channel.last_entry_id.nil? ? 1 : channel.last_entry_id + 1
|
||||
channel.last_entry_id = entry_id
|
||||
feed.entry_id = entry_id
|
||||
|
||||
# set feed data
|
||||
feed.channel_id = channel.id
|
||||
feed.created_at = parse_date ? Time.zone.parse(row[0]) : Time.zone.at(row[0].to_f)
|
||||
feed.field1 = row[1]
|
||||
feed.field2 = row[2]
|
||||
feed.field3 = row[3]
|
||||
feed.field4 = row[4]
|
||||
feed.field5 = row[5]
|
||||
feed.field6 = row[6]
|
||||
feed.field7 = row[7]
|
||||
feed.field8 = row[8]
|
||||
|
||||
# save channel and feed
|
||||
feed.save
|
||||
channel.save
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
# set the user's time zone back
|
||||
set_time_zone(params)
|
||||
|
||||
# redirect
|
||||
flash[:notice] = t(:upload_successful)
|
||||
redirect_to channel_path(channel.id, :anchor => "dataimport")
|
||||
end
|
||||
|
||||
|
||||
# import view
|
||||
def import
|
||||
get_channel_data
|
||||
end
|
||||
private
|
||||
|
||||
# upload csv file to channel
|
||||
def upload
|
||||
# if no data
|
||||
render :text => t(:select_file) and return if params[:upload].blank? or params[:upload][:csv].blank?
|
||||
# only allow these params
|
||||
def channel_params
|
||||
params.require(:channel).permit(:name, :url, :description, :latitude, :longitude, :field1, :field2, :field3, :field4, :field5, :field6, :field7, :field8, :elevation, :public_flag, :status, :video_id, :video_type)
|
||||
end
|
||||
|
||||
channel = Channel.find(params[:channel_id])
|
||||
channel_id = channel.id
|
||||
# make sure channel belongs to current user
|
||||
check_permissions(channel)
|
||||
|
||||
# set time zone
|
||||
Time.zone = params[:feed][:time_zone]
|
||||
# determine if the date can be parsed
|
||||
def date_parsable?(date)
|
||||
return !is_a_number?(date)
|
||||
end
|
||||
|
||||
# read data from uploaded file
|
||||
csv_array = CSV.parse(params[:upload][:csv].read)
|
||||
# determine if the csv file has headers
|
||||
def has_headers?(csv_array)
|
||||
headers = false
|
||||
|
||||
# does the column have headers
|
||||
headers = has_headers?(csv_array)
|
||||
# if there are at least 2 rows
|
||||
if (csv_array[0] and csv_array[1])
|
||||
row0_integers = 0
|
||||
row1_integers = 0
|
||||
|
||||
# remember the column positions
|
||||
entry_id_column = -1
|
||||
latitude_column = -1
|
||||
longitude_column = -1
|
||||
elevation_column = -1
|
||||
status_column = -1
|
||||
if headers
|
||||
csv_array[0].each_with_index do |column, index|
|
||||
entry_id_column = index if column.downcase == 'entry_id'
|
||||
latitude_column = index if column.downcase == 'latitude'
|
||||
longitude_column = index if column.downcase == 'longitude'
|
||||
elevation_column = index if column.downcase == 'elevation'
|
||||
status_column = index if column.downcase == 'status'
|
||||
end
|
||||
end
|
||||
# if first row, first value contains 'create' or 'date', assume it has headers
|
||||
if (csv_array[0][0].downcase.include?('create') or csv_array[0][0].downcase.include?('date'))
|
||||
headers = true
|
||||
else
|
||||
# count integers in row0
|
||||
csv_array[0].each_with_index do |value, i|
|
||||
row0_integers += 1 if is_a_number?(value)
|
||||
end
|
||||
|
||||
# delete the first row if it contains headers
|
||||
csv_array.delete_at(0) if headers
|
||||
# count integers in row1
|
||||
csv_array[1].each_with_index do |value, i|
|
||||
row1_integers += 1 if is_a_number?(value)
|
||||
end
|
||||
|
||||
# determine if the date can be parsed
|
||||
parse_date = date_parsable?(csv_array[0][0])
|
||||
# if row1 has more integers, assume row0 is headers
|
||||
headers = true if row1_integers > row0_integers
|
||||
end
|
||||
end
|
||||
|
||||
# if 2 or more rows
|
||||
if !csv_array[1].blank?
|
||||
date1 = parse_date ? Time.parse(csv_array[0][0]) : Time.at(csv_array[0][0])
|
||||
date2 = parse_date ? Time.parse(csv_array[1][0]) : Time.at(csv_array[1][0])
|
||||
return headers
|
||||
end
|
||||
|
||||
# reverse the array if 1st date is larger than 2nd date
|
||||
csv_array = csv_array.reverse if date1 > date2
|
||||
end
|
||||
end
|
||||
|
||||
# loop through each row
|
||||
csv_array.each do |row|
|
||||
# if row isn't blank
|
||||
if !row.blank?
|
||||
feed = Feed.new
|
||||
|
||||
# set location and status then delete the rows
|
||||
# these 4 deletes must be performed in the proper (reverse) order
|
||||
feed.status = row.delete_at(status_column) if status_column > 0
|
||||
feed.elevation = row.delete_at(elevation_column) if elevation_column > 0
|
||||
feed.longitude = row.delete_at(longitude_column) if longitude_column > 0
|
||||
feed.latitude = row.delete_at(latitude_column) if latitude_column > 0
|
||||
|
||||
# remove entry_id column if necessary
|
||||
row.delete_at(entry_id_column) if entry_id_column > 0
|
||||
|
||||
# update entry_id for channel and feed
|
||||
entry_id = channel.last_entry_id.nil? ? 1 : channel.last_entry_id + 1
|
||||
channel.last_entry_id = entry_id
|
||||
feed.entry_id = entry_id
|
||||
|
||||
# set feed data
|
||||
feed.channel_id = channel_id
|
||||
feed.created_at = parse_date ? Time.zone.parse(row[0]) : Time.zone.at(row[0].to_f)
|
||||
feed.raw_data = row.to_s
|
||||
feed.field1 = row[1]
|
||||
feed.field2 = row[2]
|
||||
feed.field3 = row[3]
|
||||
feed.field4 = row[4]
|
||||
feed.field5 = row[5]
|
||||
feed.field6 = row[6]
|
||||
feed.field7 = row[7]
|
||||
feed.field8 = row[8]
|
||||
|
||||
# save channel and feed
|
||||
feed.save
|
||||
channel.save
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
# set the user's time zone back
|
||||
set_time_zone(params)
|
||||
|
||||
# redirect
|
||||
redirect_to channel_path(channel.id)
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
|
||||
# determine if the date can be parsed
|
||||
def date_parsable?(date)
|
||||
return !is_a_number?(date)
|
||||
end
|
||||
|
||||
# determine if the csv file has headers
|
||||
def has_headers?(csv_array)
|
||||
headers = false
|
||||
|
||||
# if there are at least 2 rows
|
||||
if (csv_array[0] and csv_array[1])
|
||||
row0_integers = 0
|
||||
row1_integers = 0
|
||||
|
||||
# if first row, first value contains 'create' or 'date', assume it has headers
|
||||
if (csv_array[0][0].downcase.include?('create') or csv_array[0][0].downcase.include?('date'))
|
||||
headers = true
|
||||
else
|
||||
# count integers in row0
|
||||
csv_array[0].each_with_index do |value, i|
|
||||
row0_integers += 1 if is_a_number?(value)
|
||||
end
|
||||
|
||||
# count integers in row1
|
||||
csv_array[1].each_with_index do |value, i|
|
||||
row1_integers += 1 if is_a_number?(value)
|
||||
end
|
||||
|
||||
# if row1 has more integers, assume row0 is headers
|
||||
headers = true if row1_integers > row0_integers
|
||||
end
|
||||
end
|
||||
|
||||
return headers
|
||||
end
|
||||
|
||||
end
|
@ -1,78 +1,110 @@
|
||||
class ChartsController < ApplicationController
|
||||
before_filter :require_user, :only => [:edit]
|
||||
def edit
|
||||
# params[:id] is the windows ID
|
||||
@channel = current_user.channels.find(params[:channel_id])
|
||||
|
||||
def index
|
||||
set_channels_menu
|
||||
@channel = Channel.find(params[:channel_id])
|
||||
@channel_id = params[:channel_id]
|
||||
@domain = domain
|
||||
window_id = params[:id]
|
||||
logger.debug "Windows ID is #{window_id}"
|
||||
window_detail = @channel.windows.find(window_id).becomes(ChartWindow).window_detail
|
||||
options = window_detail.options unless window_detail.nil?
|
||||
logger.debug "Options for window #{window_id} are " + options.inspect
|
||||
|
||||
# default chart size
|
||||
@width = default_width
|
||||
@height = default_height
|
||||
render :partial => "charts/config", :locals => {
|
||||
:displayconfig => false,
|
||||
:title => @channel.name,
|
||||
:src => "/channels/#{@channel.id}/charts/#{window_id}",
|
||||
:options => options,
|
||||
:index => window_id,
|
||||
:width => Chart.default_width,
|
||||
:height => Chart.default_height
|
||||
}
|
||||
end
|
||||
|
||||
check_permissions(@channel)
|
||||
end
|
||||
def index
|
||||
|
||||
def show
|
||||
# allow these parameters when creating feed querystring
|
||||
feed_params = ['key','days','start','end','round','timescale','average','median','sum']
|
||||
set_channels_menu
|
||||
@channel = Channel.find(params[:channel_id])
|
||||
@channel_id = params[:channel_id]
|
||||
@domain = domain
|
||||
|
||||
# default chart size
|
||||
@width = default_width
|
||||
@height = default_height
|
||||
# default chart size
|
||||
@width = Chart.default_width
|
||||
@height = Chart.default_height
|
||||
|
||||
# add extra parameters to querystring
|
||||
@qs = ''
|
||||
params.each do |p|
|
||||
@qs += "&#{p[0]}=#{p[1]}" if feed_params.include?(p[0])
|
||||
end
|
||||
check_permissions(@channel)
|
||||
end
|
||||
|
||||
# fix chart colors if necessary
|
||||
params[:color] = fix_color(params[:color])
|
||||
params[:bgcolor] = fix_color(params[:bgcolor])
|
||||
def show
|
||||
|
||||
@domain = domain
|
||||
render :layout => false
|
||||
end
|
||||
# allow these parameters when creating feed querystring
|
||||
feed_params = ['key','days','start','end','round','timescale','average','median','sum','results','location','status']
|
||||
|
||||
# save chart options
|
||||
def update
|
||||
@channel = Channel.find(params[:channel_id])
|
||||
@status = 0
|
||||
# default chart size
|
||||
@width = Chart.default_width
|
||||
@height = Chart.default_height
|
||||
|
||||
# check permissions
|
||||
if @channel.user_id == current_user.id
|
||||
# add extra parameters to querystring
|
||||
@qs = ''
|
||||
params.each do |p|
|
||||
@qs += "&#{p[0]}=#{p[1]}" if feed_params.include?(p[0])
|
||||
end
|
||||
|
||||
# save data
|
||||
@channel["options#{params[:id]}"] = params[:options]
|
||||
if @channel.save
|
||||
@status = 1
|
||||
end
|
||||
# fix chart colors if necessary
|
||||
params[:color] = fix_color(params[:color])
|
||||
params[:bgcolor] = fix_color(params[:bgcolor])
|
||||
|
||||
end
|
||||
# set ssl
|
||||
@ssl = (get_header_value('x_ssl') == 'true')
|
||||
@domain = domain(@ssl)
|
||||
|
||||
# return response: 1=success, 0=failure
|
||||
render :json => @status.to_json
|
||||
end
|
||||
# should data be pushed off the end in dynamic chart
|
||||
@push = (params[:push] and params[:push] == 'false') ? false : true
|
||||
@results = params[:results]
|
||||
render :layout => false
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def default_width
|
||||
450
|
||||
end
|
||||
# save chart options
|
||||
def update
|
||||
#Check to see if we're using the new options, or the old
|
||||
|
||||
def default_height
|
||||
250
|
||||
end
|
||||
@channel = Channel.find(params[:channel_id])
|
||||
@status = 0
|
||||
|
||||
# fixes chart color if user forgets the leading '#'
|
||||
def fix_color(color)
|
||||
# check for 3 or 6 character hexadecimal value
|
||||
if (color and color.match(/^([0-9]|[a-f]|[A-F]){3}(([0-9]|[a-f]|[A-F]){3})?$/))
|
||||
color = '#' + color
|
||||
end
|
||||
# check permissions
|
||||
if @channel.user_id == current_user.id
|
||||
logger.debug "Saving Data with new options " + params[:newOptions].to_s
|
||||
# save data
|
||||
if params[:newOptions]
|
||||
logger.debug "Updating new style options on window id #{params[:id]} with #{params[:newOptions][:options]}"
|
||||
chart_window = @channel.windows.find(params[:id]).becomes(ChartWindow)
|
||||
chart_window.window_detail.options = params[:newOptions][:options]
|
||||
if !chart_window.save
|
||||
raise "Couldn't save the Chart Window"
|
||||
end
|
||||
end
|
||||
if @channel.save
|
||||
@status = 1
|
||||
end
|
||||
|
||||
return color
|
||||
end
|
||||
end
|
||||
|
||||
# return response: 1=success, 0=failure
|
||||
render :json => @status.to_json
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# fixes chart color if user forgets the leading '#'
|
||||
def fix_color(color)
|
||||
# check for 3 or 6 character hexadecimal value
|
||||
if (color and color.match(/^([0-9]|[a-f]|[A-F]){3}(([0-9]|[a-f]|[A-F]){3})?$/))
|
||||
color = '#' + color
|
||||
end
|
||||
|
||||
return color
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
47
app/controllers/comments_controller.rb
Normal file
47
app/controllers/comments_controller.rb
Normal file
@ -0,0 +1,47 @@
|
||||
class CommentsController < ApplicationController
|
||||
before_filter :require_user
|
||||
|
||||
def index
|
||||
redirect_to channel_path(:id => params[:channel_id], :public => true)
|
||||
end
|
||||
|
||||
def create
|
||||
render :text => '' and return if params[:userlogin].length > 0
|
||||
|
||||
@channel = Channel.find(params[:channel_id])
|
||||
@comment = @channel.comments.new
|
||||
@comment.user = current_user
|
||||
@comment.ip_address = get_header_value('X_REAL_IP')
|
||||
@comment.parent_id = params[:parent_id]
|
||||
@comment.body = params[:comment][:body].gsub(/<\/?[^>]*>/, '').gsub(/\n/, '<br />')
|
||||
# save comment
|
||||
if @comment.save
|
||||
flash[:success] = "Thanks for adding a comment!"
|
||||
else
|
||||
flash[:error] = "Comment can't be blank!"
|
||||
end
|
||||
redirect_to :back
|
||||
end
|
||||
|
||||
def vote
|
||||
# make sure this is a post
|
||||
render :text => '' and return if !request.post?
|
||||
|
||||
@comment = Comment.find(params[:id])
|
||||
@comment.flags += 1
|
||||
# delete if too many flags
|
||||
if (@comment.flags > 3)
|
||||
@comment.destroy
|
||||
render :text => ''
|
||||
# else save
|
||||
else
|
||||
@comment.save
|
||||
render :text => '1'
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
comment = current_user.comments.find(params[:id]).destroy
|
||||
redirect_to :back
|
||||
end
|
||||
end
|
8
app/controllers/cors_controller.rb
Normal file
8
app/controllers/cors_controller.rb
Normal file
@ -0,0 +1,8 @@
|
||||
class CorsController < ApplicationController
|
||||
skip_before_filter :verify_authenticity_token
|
||||
|
||||
# dummy method that responds with status 200 for CORS preflighting
|
||||
def preflight; render :nothing => true; end
|
||||
|
||||
end
|
||||
|
19
app/controllers/docs_controller.rb
Normal file
19
app/controllers/docs_controller.rb
Normal file
@ -0,0 +1,19 @@
|
||||
class DocsController < ApplicationController
|
||||
|
||||
def index; ;end
|
||||
|
||||
def talkback
|
||||
# default values
|
||||
@talkback_id = 3
|
||||
@talkback_api_key = 'XXXXXXXXXXXXXXXX'
|
||||
|
||||
# if user is signed in
|
||||
if current_user && current_user.talkbacks.any?
|
||||
@talkback = current_user.talkbacks.order('updated_at desc').first
|
||||
@talkback_id = @talkback.id
|
||||
@talkback_api_key = @talkback.api_key
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -1,570 +1,254 @@
|
||||
class FeedController < ApplicationController
|
||||
require 'csv'
|
||||
layout 'application', :except => :index
|
||||
include FeedHelper
|
||||
require 'csv'
|
||||
layout 'application', :except => [:index, :debug]
|
||||
|
||||
def index
|
||||
channel = Channel.find(params[:channel_id])
|
||||
api_key = ApiKey.find_by_api_key(get_userkey)
|
||||
@success = channel_permission?(channel, api_key)
|
||||
def index
|
||||
feed_factory = FeedFactory.new(params)
|
||||
channel = Channel.find(params[:channel_id])
|
||||
api_key = ApiKey.find_by_api_key(get_apikey)
|
||||
@success = channel_permission?(channel, api_key)
|
||||
|
||||
# set timezone correctly
|
||||
set_time_zone(params)
|
||||
# set callback for jsonp
|
||||
@callback = params[:callback] if params[:callback]
|
||||
|
||||
# set limits
|
||||
limit = params[:results].to_i if params[:results]
|
||||
# set csv headers if necessary
|
||||
@csv_headers = feed_factory.feed_select_options if params[:format] == 'csv'
|
||||
|
||||
# check for access
|
||||
if @success
|
||||
# set timezone correctly
|
||||
set_time_zone(params)
|
||||
|
||||
# create options hash
|
||||
channel_options = { :only => channel_select_data(channel) }
|
||||
select_options = feed_select_data(channel)
|
||||
# check for access
|
||||
if @success
|
||||
|
||||
# get feed based on conditions
|
||||
feeds = Feed.find(
|
||||
:all,
|
||||
:conditions => { :channel_id => channel.id, :created_at => get_date_range(params) },
|
||||
:select => select_options,
|
||||
:order => 'created_at desc',
|
||||
:limit => limit
|
||||
)
|
||||
|
||||
# keep track of whether data has been rounded already
|
||||
rounded = false
|
||||
|
||||
# if a feed has data
|
||||
if !feeds.empty?
|
||||
# convert to timescales if necessary
|
||||
if timeparam_valid?(params[:timescale])
|
||||
feeds = feeds_into_timescales(feeds)
|
||||
# convert to sums if necessary
|
||||
elsif timeparam_valid?(params[:sum])
|
||||
feeds = feeds_into_sums(feeds)
|
||||
rounded = true
|
||||
# convert to averages if necessary
|
||||
elsif timeparam_valid?(params[:average])
|
||||
feeds = feeds_into_averages(feeds)
|
||||
rounded = true
|
||||
# convert to medians if necessary
|
||||
elsif timeparam_valid?(params[:median])
|
||||
feeds = feeds_into_medians(feeds)
|
||||
rounded = true
|
||||
end
|
||||
end
|
||||
|
||||
# if a feed needs to be rounded
|
||||
if params[:round] and !rounded
|
||||
feeds = object_round(feeds, params[:round].to_i)
|
||||
if feed_factory.cache_feeds
|
||||
# check cache for stored value
|
||||
feed_output_cache_key = cache_key('feed_output')
|
||||
channel_output_cache_key = cache_key('channel_output')
|
||||
@feed_output = Rails.cache.read(feed_output_cache_key)
|
||||
@channel_output = Rails.cache.read(channel_output_cache_key)
|
||||
end
|
||||
|
||||
# set output correctly
|
||||
if params[:format] == 'xml'
|
||||
@channel_output = channel.to_xml(channel_options).sub('</channel>', '').strip
|
||||
@feed_output = feeds.to_xml(:skip_instruct => true).gsub(/\n/, "\n ").chop.chop
|
||||
elsif params[:format] == 'csv'
|
||||
@feed_output = feeds
|
||||
else
|
||||
@channel_output = channel.to_json(channel_options).chop
|
||||
@feed_output = feeds.to_json
|
||||
end
|
||||
# if cache miss, get data
|
||||
if @feed_output.nil? or @channel_output.nil?
|
||||
|
||||
# else no access, set error code
|
||||
else
|
||||
if params[:format] == 'xml'
|
||||
@channel_output = bad_channel_xml
|
||||
else
|
||||
@channel_output = '-1'.to_json
|
||||
end
|
||||
end
|
||||
# get feeds
|
||||
feeds = feed_factory.get_output_feeds
|
||||
|
||||
# set callback for jsonp
|
||||
@callback = params[:callback] if params[:callback]
|
||||
# set output correctly
|
||||
if params[:format] == 'xml'
|
||||
@channel_output = channel.to_xml(channel.select_options).sub('</channel>', '').strip
|
||||
@feed_output = feeds.to_xml(:skip_instruct => true).gsub(/\n/, "\n ").chop.chop
|
||||
elsif params[:format] == 'csv'
|
||||
@feed_output = feeds
|
||||
else
|
||||
@channel_output = channel.to_json(channel.select_options).chop
|
||||
@feed_output = feeds.to_json(:only => feed_factory.feed_select_options)
|
||||
end
|
||||
|
||||
# set csv headers if necessary
|
||||
@csv_headers = select_options if params[:format] == 'csv'
|
||||
if feed_factory.cache_feeds
|
||||
# save to cache
|
||||
Rails.cache.write(feed_output_cache_key, @feed_output, :expires_in => 5.minutes)
|
||||
Rails.cache.write(channel_output_cache_key, @channel_output, :expires_in => 5.minutes)
|
||||
end
|
||||
|
||||
# output proper http response if error
|
||||
render :text => '-1', :status => 400 and return if !@success
|
||||
end # end if feeds not empty
|
||||
|
||||
# output data in proper format
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.json
|
||||
format.xml
|
||||
format.csv
|
||||
end
|
||||
end
|
||||
# else no access, set error code
|
||||
else
|
||||
if params[:format] == 'xml'
|
||||
@channel_output = bad_channel_xml
|
||||
else
|
||||
@channel_output = '-1'.to_json
|
||||
end
|
||||
end
|
||||
|
||||
def show
|
||||
@channel = Channel.find(params[:channel_id])
|
||||
@api_key = ApiKey.find_by_api_key(get_userkey)
|
||||
output = '-1'
|
||||
# output proper http response if error
|
||||
render :text => '-1', :status => 400 and return if !@success
|
||||
|
||||
# get most recent entry if necessary
|
||||
params[:id] = @channel.last_entry_id if params[:id] == 'last'
|
||||
# output data in proper format
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.json
|
||||
format.xml
|
||||
format.csv
|
||||
end
|
||||
end
|
||||
|
||||
# set timezone correctly
|
||||
set_time_zone(params)
|
||||
def last_sum
|
||||
last_method = method('last_group_call')
|
||||
last_method.call('sums')
|
||||
end
|
||||
|
||||
@feed = Feed.find(
|
||||
:first,
|
||||
:conditions => { :channel_id => @channel.id, :entry_id => params[:id] },
|
||||
:select => feed_select_data(@channel)
|
||||
)
|
||||
@success = channel_permission?(@channel, @api_key)
|
||||
def last_median
|
||||
last_method = method('last_group_call')
|
||||
last_method.call('medians')
|
||||
end
|
||||
|
||||
def last_average
|
||||
last_method = method('last_group_call')
|
||||
last_method.call('averages')
|
||||
end
|
||||
|
||||
def last_group_call(arg)
|
||||
@channel = Channel.find(params[:channel_id])
|
||||
@api_key = ApiKey.find_by_api_key(get_apikey)
|
||||
set_time_zone(params)
|
||||
|
||||
# limit for the number of results to get
|
||||
limit = 30
|
||||
limit = params[:sum].to_i if params[:sum].present?
|
||||
limit = params[:median].to_i if params[:median].present?
|
||||
limit = params[:average].to_i if params[:average].present?
|
||||
# max limit of 100 past results
|
||||
limit = 100 if limit > 100
|
||||
|
||||
# get the last (limit) feeds
|
||||
last_feeds = Feed.where(:channel_id => @channel.id).limit(limit).order('created_at desc')
|
||||
# put feeds in correct order (oldest to most recent)
|
||||
last_feeds.reverse!
|
||||
|
||||
feeds_into = self.method("feeds_into_#{arg}")
|
||||
feed = feeds_into.call(last_feeds, params).last if last_feeds.length > 0
|
||||
create_group_result(feed)
|
||||
end
|
||||
|
||||
def create_group_result(feed)
|
||||
@success = channel_permission?(@channel, @api_key)
|
||||
|
||||
# if a feed needs to be rounded
|
||||
if params[:round] && feed.present?
|
||||
feed = item_round(feed, params[:round].to_i)
|
||||
end
|
||||
|
||||
# check for access
|
||||
if @success && feed.present?
|
||||
# set output correctly
|
||||
if params[:format] == 'xml'
|
||||
output = feed.to_xml
|
||||
elsif params[:format] == 'csv'
|
||||
@csv_headers = Feed.select_options(@channel, params)
|
||||
elsif (params[:format] == 'txt' or params[:format] == 'text')
|
||||
output = add_prepend_append(feed["field#{params[:field_id]}"])
|
||||
else
|
||||
output = feed.to_json
|
||||
end
|
||||
# else set error code
|
||||
else
|
||||
if params[:format] == 'xml'
|
||||
output = bad_feed_xml
|
||||
else
|
||||
output = '-1'.to_json
|
||||
end
|
||||
end
|
||||
|
||||
# output data in proper format
|
||||
respond_to do |format|
|
||||
format.html { render :json => output }
|
||||
format.json { render :json => output, :callback => params[:callback] }
|
||||
format.xml { render :xml => output }
|
||||
format.csv
|
||||
format.text { render :text => output }
|
||||
end
|
||||
end
|
||||
|
||||
def show
|
||||
|
||||
@channel = Channel.find(params[:channel_id])
|
||||
@api_key = ApiKey.find_by_api_key(get_apikey)
|
||||
output = '-1'
|
||||
|
||||
# set timezone correctly
|
||||
set_time_zone(params)
|
||||
|
||||
# make sure field parameter is set correctly, changes "field1" to "1"
|
||||
params[:field_id] = params[:field_id].sub('field', '') if params[:field_id].present?
|
||||
|
||||
# if last entry
|
||||
if params[:id] == 'last' && params[:field_id].present? && params[:field_id].to_i != 0
|
||||
# look for a feed where the value isn't null
|
||||
@feed = Feed.where(:channel_id => @channel.id)
|
||||
.where("field? is not null", params[:field_id].to_i)
|
||||
.select(Feed.select_options(@channel, params))
|
||||
.order('entry_id desc')
|
||||
.first
|
||||
# else get by entry
|
||||
else
|
||||
# get most recent entry if necessary
|
||||
params[:id] = @channel.last_entry_id if params[:id] == 'last'
|
||||
@feed = Feed.where(:channel_id => @channel.id, :entry_id => params[:id]).select(Feed.select_options(@channel, params)).first
|
||||
end
|
||||
|
||||
@success = channel_permission?(@channel, @api_key)
|
||||
|
||||
# if a feed needs to be rounded
|
||||
if params[:round]
|
||||
@feed = item_round(@feed, params[:round].to_i)
|
||||
end
|
||||
|
||||
# check for access
|
||||
if @success
|
||||
# set output correctly
|
||||
if params[:format] == 'xml'
|
||||
output = @feed.to_xml
|
||||
elsif params[:format] == 'csv'
|
||||
@csv_headers = feed_select_data(@channel)
|
||||
elsif (params[:format] == 'txt' or params[:format] == 'text')
|
||||
output = add_prepend_append(@feed["field#{params[:field_id]}"])
|
||||
else
|
||||
output = @feed.to_json
|
||||
end
|
||||
# else set error code
|
||||
else
|
||||
if params[:format] == 'xml'
|
||||
output = bad_feed_xml
|
||||
else
|
||||
output = '-1'.to_json
|
||||
end
|
||||
end
|
||||
# check for access
|
||||
if @success and @feed
|
||||
|
||||
# output data in proper format
|
||||
respond_to do |format|
|
||||
format.html { render :json => output }
|
||||
format.json { render :json => output, :callback => params[:callback] }
|
||||
format.xml { render :xml => output }
|
||||
format.csv
|
||||
format.text { render :text => output }
|
||||
end
|
||||
end
|
||||
# set output correctly
|
||||
if params[:format] == 'xml'
|
||||
output = @feed.to_xml
|
||||
elsif params[:format] == 'csv'
|
||||
@csv_headers = Feed.select_options(@channel, params)
|
||||
elsif (params[:format] == 'txt' or params[:format] == 'text')
|
||||
output = add_prepend_append(@feed["field#{params[:field_id]}"])
|
||||
else
|
||||
output = @feed.to_json
|
||||
|
||||
private
|
||||
|
||||
# only output these fields for channel
|
||||
def channel_select_data(channel)
|
||||
only = [:name, :created_at, :updated_at, :id, :last_entry_id]
|
||||
only += [:description] unless channel.description.blank?
|
||||
only += [:latitude] unless channel.latitude.blank?
|
||||
only += [:longitude] unless channel.longitude.blank?
|
||||
only += [:elevation] unless channel.elevation.blank?
|
||||
only += [:field1] unless channel.field1.blank?
|
||||
only += [:field2] unless channel.field2.blank?
|
||||
only += [:field3] unless channel.field3.blank?
|
||||
only += [:field4] unless channel.field4.blank?
|
||||
only += [:field5] unless channel.field5.blank?
|
||||
only += [:field6] unless channel.field6.blank?
|
||||
only += [:field7] unless channel.field7.blank?
|
||||
only += [:field8] unless channel.field8.blank?
|
||||
|
||||
return only
|
||||
end
|
||||
|
||||
# only output these fields for feed
|
||||
def feed_select_data(channel)
|
||||
only = [:created_at]
|
||||
only += [:entry_id] unless timeparam_valid?(params[:timescale]) or timeparam_valid?(params[:average]) or timeparam_valid?(params[:median]) or timeparam_valid?(params[:sum])
|
||||
only += [:field1] unless channel.field1.blank? or (params[:field_id] and params[:field_id] != '1')
|
||||
only += [:field2] unless channel.field2.blank? or (params[:field_id] and params[:field_id] != '2')
|
||||
only += [:field3] unless channel.field3.blank? or (params[:field_id] and params[:field_id] != '3')
|
||||
only += [:field4] unless channel.field4.blank? or (params[:field_id] and params[:field_id] != '4')
|
||||
only += [:field5] unless channel.field5.blank? or (params[:field_id] and params[:field_id] != '5')
|
||||
only += [:field6] unless channel.field6.blank? or (params[:field_id] and params[:field_id] != '6')
|
||||
only += [:field7] unless channel.field7.blank? or (params[:field_id] and params[:field_id] != '7')
|
||||
only += [:field8] unless channel.field8.blank? or (params[:field_id] and params[:field_id] != '8')
|
||||
|
||||
# add geolocation data if necessary
|
||||
if params[:location] and params[:location].upcase == 'TRUE'
|
||||
only += [:latitude]
|
||||
only += [:longitude]
|
||||
only += [:elevation]
|
||||
end
|
||||
|
||||
# add status if necessary
|
||||
only += [:status] if params[:status] and params[:status].upcase == 'TRUE'
|
||||
|
||||
return only
|
||||
end
|
||||
|
||||
# checks for valid timescale
|
||||
def timeparam_valid?(timeparam)
|
||||
valid_minutes = [10, 15, 20, 30, 60, 240, 720, 1440]
|
||||
if timeparam and valid_minutes.include?(timeparam.to_i)
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
# applies rounding to an enumerable object
|
||||
def object_round(object, round=nil, match='field')
|
||||
object.each_with_index do |o, index|
|
||||
object[index] = item_round(o, round, match)
|
||||
end
|
||||
|
||||
return object
|
||||
# else set error code
|
||||
else
|
||||
if params[:format] == 'xml'
|
||||
output = bad_feed_xml
|
||||
else
|
||||
output = '-1'.to_json
|
||||
end
|
||||
end
|
||||
|
||||
# applies rounding to a single item's attributes if necessary
|
||||
def item_round(item, round=nil, match='field')
|
||||
# for each attribute
|
||||
item.attribute_names.each do |attr|
|
||||
# only add non-null numeric fields
|
||||
if attr.index(match) and !item[attr].nil? and is_a_number?(item[attr])
|
||||
# keep track of whether the value contains commas
|
||||
comma_flag = (item[attr].to_s.index(',')) ? true : false
|
||||
|
||||
# replace commas with decimals if appropriate
|
||||
item[attr] = item[attr].to_s.gsub(/,/, '.') if comma_flag
|
||||
|
||||
# do the actual rounding
|
||||
item[attr] = sprintf "%.#{round}f", item[attr]
|
||||
|
||||
# replace decimals with commas if appropriate
|
||||
item[attr] = item[attr].to_s.gsub(/\./, ',') if comma_flag
|
||||
end
|
||||
end
|
||||
|
||||
# output new item
|
||||
return item
|
||||
# output data in proper format
|
||||
respond_to do |format|
|
||||
format.html { render :json => output }
|
||||
format.json { render :json => output, :callback => params[:callback] }
|
||||
format.xml { render :xml => output }
|
||||
format.csv
|
||||
format.text { render :text => output }
|
||||
end
|
||||
end
|
||||
|
||||
# slice feed into timescales
|
||||
def feeds_into_timescales(feeds)
|
||||
# convert timescale (minutes) into seconds
|
||||
seconds = params[:timescale].to_i * 60
|
||||
# get floored time ranges
|
||||
start_time = get_floored_time(feeds.first.created_at, seconds)
|
||||
end_time = get_floored_time(feeds.last.created_at, seconds)
|
||||
def debug
|
||||
@time_start = Time.now
|
||||
|
||||
# create empty array with appropriate size
|
||||
timeslices = Array.new((((end_time - start_time) / seconds).abs).floor)
|
||||
channel = Channel.find(params[:channel_id])
|
||||
api_key = ApiKey.find_by_api_key(get_apikey)
|
||||
@success = channel_permission?(channel, api_key)
|
||||
|
||||
# create options hash
|
||||
select_options = Feed.select_options(channel, params)
|
||||
|
||||
# create a blank clone of the first feed so that we only get the necessary attributes
|
||||
empty_feed = create_empty_clone(feeds.first)
|
||||
# get feed based on conditions
|
||||
feeds = Feed.find(
|
||||
:all,
|
||||
:conditions => { :channel_id => channel.id, :created_at => get_date_range(params) },
|
||||
:select => select_options,
|
||||
:order => 'created_at desc'
|
||||
)
|
||||
@count = feeds.count
|
||||
@time_after_db = Time.now
|
||||
|
||||
# add feeds to array
|
||||
feeds.each do |f|
|
||||
i = ((f.created_at - start_time) / seconds).floor
|
||||
f.created_at = start_time + i * seconds
|
||||
timeslices[i] = f if timeslices[i].nil?
|
||||
end
|
||||
# sort properly
|
||||
feeds.reverse!
|
||||
|
||||
# fill in empty array elements
|
||||
timeslices.each_index do |i|
|
||||
if timeslices[i].nil?
|
||||
current_feed = empty_feed.clone
|
||||
current_feed.created_at = (start_time + (i * seconds))
|
||||
timeslices[i] = current_feed
|
||||
end
|
||||
end
|
||||
@time_after_sort = Time.now
|
||||
|
||||
return timeslices
|
||||
end
|
||||
@channel_output = channel.to_json(channel.select_options).chop
|
||||
@feed_output = feeds.to_json
|
||||
|
||||
# slice feed into averages
|
||||
def feeds_into_averages(feeds)
|
||||
# convert timescale (minutes) into seconds
|
||||
seconds = params[:average].to_i * 60
|
||||
# get floored time ranges
|
||||
start_time = get_floored_time(feeds.first.created_at, seconds)
|
||||
end_time = get_floored_time(feeds.last.created_at, seconds)
|
||||
|
||||
# create empty array with appropriate size
|
||||
timeslices = Array.new(((end_time - start_time) / seconds).floor)
|
||||
|
||||
# create a blank clone of the first feed so that we only get the necessary attributes
|
||||
empty_feed = create_empty_clone(feeds.first)
|
||||
|
||||
# add feeds to array
|
||||
feeds.each do |f|
|
||||
i = ((f.created_at - start_time) / seconds).floor
|
||||
f.created_at = start_time + i * seconds
|
||||
# create multidimensional array
|
||||
timeslices[i] = [] if timeslices[i].nil?
|
||||
timeslices[i].push(f)
|
||||
end
|
||||
|
||||
# keep track of whether numbers use commas as decimals
|
||||
comma_flag = false
|
||||
|
||||
# fill in array
|
||||
timeslices.each_index do |i|
|
||||
# insert empty values
|
||||
if timeslices[i].nil?
|
||||
current_feed = empty_feed.clone
|
||||
current_feed.created_at = (start_time + (i * seconds))
|
||||
timeslices[i] = current_feed
|
||||
# else average the inner array
|
||||
else
|
||||
sum_feed = empty_feed.clone
|
||||
sum_feed.created_at = timeslices[i].first.created_at
|
||||
# for each feed
|
||||
timeslices[i].each do |f|
|
||||
# for each attribute, add to sum_feed so that we have the total
|
||||
sum_feed.attribute_names.each do |attr|
|
||||
|
||||
# only add non-null integer fields
|
||||
if attr.index('field') and !f[attr].nil? and is_a_number?(f[attr])
|
||||
# set comma_flag once if we find a number with a comma
|
||||
comma_flag = true if !comma_flag and f[attr].to_s.index(',')
|
||||
|
||||
# set initial data
|
||||
if sum_feed[attr].nil?
|
||||
sum_feed[attr] = parsefloat(f[attr])
|
||||
# add data
|
||||
elsif f[attr]
|
||||
sum_feed[attr] = parsefloat(sum_feed[attr]) + parsefloat(f[attr])
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
# set to the averaged feed
|
||||
timeslices[i] = object_average(sum_feed, timeslices[i].length, comma_flag, params[:round])
|
||||
end
|
||||
end
|
||||
|
||||
return timeslices
|
||||
end
|
||||
|
||||
# slice feed into medians
|
||||
def feeds_into_medians(feeds)
|
||||
# convert timescale (minutes) into seconds
|
||||
seconds = params[:median].to_i * 60
|
||||
# get floored time ranges
|
||||
start_time = get_floored_time(feeds.first.created_at, seconds)
|
||||
end_time = get_floored_time(feeds.last.created_at, seconds)
|
||||
|
||||
# create empty array with appropriate size
|
||||
timeslices = Array.new(((end_time - start_time) / seconds).floor)
|
||||
|
||||
# create a blank clone of the first feed so that we only get the necessary attributes
|
||||
empty_feed = create_empty_clone(feeds.first)
|
||||
|
||||
# add feeds to array
|
||||
feeds.each do |f|
|
||||
i = ((f.created_at - start_time) / seconds).floor
|
||||
f.created_at = start_time + i * seconds
|
||||
# create multidimensional array
|
||||
timeslices[i] = [] if timeslices[i].nil?
|
||||
timeslices[i].push(f)
|
||||
end
|
||||
|
||||
# keep track of whether numbers use commas as decimals
|
||||
comma_flag = false
|
||||
|
||||
# fill in array
|
||||
timeslices.each_index do |i|
|
||||
# insert empty values
|
||||
if timeslices[i].nil?
|
||||
current_feed = empty_feed.clone
|
||||
current_feed.created_at = (start_time + (i * seconds))
|
||||
timeslices[i] = current_feed
|
||||
# else get median values for the inner array
|
||||
else
|
||||
|
||||
# create blank hash called 'fields' to hold data
|
||||
fields = {}
|
||||
|
||||
# for each feed
|
||||
timeslices[i].each do |f|
|
||||
|
||||
# for each attribute
|
||||
f.attribute_names.each do |attr|
|
||||
if attr.index('field')
|
||||
|
||||
# create blank array for each field
|
||||
fields["#{attr}"] = [] if fields["#{attr}"].nil?
|
||||
|
||||
# push numeric field data onto its array
|
||||
if is_a_number?(f[attr])
|
||||
# set comma_flag once if we find a number with a comma
|
||||
comma_flag = true if !comma_flag and f[attr].to_s.index(',')
|
||||
|
||||
fields["#{attr}"].push(parsefloat(f[attr]))
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# sort fields arrays
|
||||
fields.each_key do |key|
|
||||
fields[key] = fields[key].compact.sort
|
||||
end
|
||||
|
||||
# get the median
|
||||
median_feed = empty_feed.clone
|
||||
median_feed.created_at = timeslices[i].first.created_at
|
||||
median_feed.attribute_names.each do |attr|
|
||||
median_feed[attr] = object_median(fields[attr], comma_flag, params[:round]) if attr.index('field')
|
||||
end
|
||||
|
||||
timeslices[i] = median_feed
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
return timeslices
|
||||
end
|
||||
|
||||
# slice feed into sums
|
||||
def feeds_into_sums(feeds)
|
||||
# convert timescale (minutes) into seconds
|
||||
seconds = params[:sum].to_i * 60
|
||||
# get floored time ranges
|
||||
start_time = get_floored_time(feeds.first.created_at, seconds)
|
||||
end_time = get_floored_time(feeds.last.created_at, seconds)
|
||||
|
||||
# create empty array with appropriate size
|
||||
timeslices = Array.new(((end_time - start_time) / seconds).floor)
|
||||
|
||||
# create a blank clone of the first feed so that we only get the necessary attributes
|
||||
empty_feed = create_empty_clone(feeds.first)
|
||||
|
||||
# add feeds to array
|
||||
feeds.each do |f|
|
||||
i = ((f.created_at - start_time) / seconds).floor
|
||||
f.created_at = start_time + i * seconds
|
||||
# create multidimensional array
|
||||
timeslices[i] = [] if timeslices[i].nil?
|
||||
timeslices[i].push(f)
|
||||
end
|
||||
|
||||
# keep track of whether numbers use commas as decimals
|
||||
comma_flag = false
|
||||
|
||||
# fill in array
|
||||
timeslices.each_index do |i|
|
||||
# insert empty values
|
||||
if timeslices[i].nil?
|
||||
current_feed = empty_feed.clone
|
||||
current_feed.created_at = (start_time + (i * seconds))
|
||||
timeslices[i] = current_feed
|
||||
# else sum the inner array
|
||||
else
|
||||
sum_feed = empty_feed.clone
|
||||
sum_feed.created_at = timeslices[i].first.created_at
|
||||
# for each feed
|
||||
timeslices[i].each do |f|
|
||||
# for each attribute, add to sum_feed so that we have the total
|
||||
sum_feed.attribute_names.each do |attr|
|
||||
# only add non-null integer fields
|
||||
if attr.index('field') and !f[attr].nil? and is_a_number?(f[attr])
|
||||
|
||||
# set comma_flag once if we find a number with a comma
|
||||
comma_flag = true if !comma_flag and f[attr].to_s.index(',')
|
||||
|
||||
# set initial data
|
||||
if sum_feed[attr].nil?
|
||||
sum_feed[attr] = parsefloat(f[attr])
|
||||
# add data
|
||||
elsif f[attr]
|
||||
sum_feed[attr] = parsefloat(sum_feed[attr]) + parsefloat(f[attr])
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# set to the summed feed
|
||||
timeslices[i] = object_sum(sum_feed, comma_flag, params[:round])
|
||||
end
|
||||
end
|
||||
|
||||
return timeslices
|
||||
end
|
||||
|
||||
def is_a_number?(s)
|
||||
s.to_s.gsub(/,/, '.').match(/\A[+-]?\d+?(\.\d+)?\Z/) == nil ? false : true
|
||||
end
|
||||
|
||||
def parsefloat(number)
|
||||
return number.to_s.gsub(/,/, '.').to_f
|
||||
end
|
||||
|
||||
# gets the median for an object
|
||||
def object_median(object, comma_flag=false, round=nil)
|
||||
return nil if object.nil?
|
||||
length = object.length
|
||||
return nil if length == 0
|
||||
output = ''
|
||||
|
||||
# do the calculation
|
||||
if length % 2 == 0
|
||||
output = (object[(length - 1) / 2] + object[length / 2]) / 2
|
||||
else
|
||||
output = object[(length - 1) / 2]
|
||||
end
|
||||
|
||||
output = sprintf "%.#{round}f", output if round and is_a_number?(output)
|
||||
|
||||
# replace decimals with commas if appropriate
|
||||
output = output.to_s.gsub(/\./, ',') if comma_flag
|
||||
|
||||
return output.to_s
|
||||
end
|
||||
|
||||
# averages a summed object over length
|
||||
def object_average(object, length, comma_flag=false, round=nil)
|
||||
object.attribute_names.each do |attr|
|
||||
# only average non-null integer fields
|
||||
if !object[attr].nil? and is_a_number?(object[attr])
|
||||
if round
|
||||
object[attr] = sprintf "%.#{round}f", (parsefloat(object[attr]) / length)
|
||||
else
|
||||
object[attr] = (parsefloat(object[attr]) / length).to_s
|
||||
end
|
||||
# replace decimals with commas if appropriate
|
||||
object[attr] = object[attr].gsub(/\./, ',') if comma_flag
|
||||
end
|
||||
end
|
||||
|
||||
return object
|
||||
end
|
||||
|
||||
# formats a summed object correctly
|
||||
def object_sum(object, comma_flag=false, round=nil)
|
||||
object.attribute_names.each do |attr|
|
||||
# only average non-null integer fields
|
||||
if !object[attr].nil? and is_a_number?(object[attr])
|
||||
if round
|
||||
object[attr] = sprintf "%.#{round}f", parsefloat(object[attr])
|
||||
else
|
||||
object[attr] = parsefloat(object[attr]).to_s
|
||||
end
|
||||
# replace decimals with commas if appropriate
|
||||
object[attr] = object[attr].gsub(/\./, ',') if comma_flag
|
||||
end
|
||||
end
|
||||
|
||||
return object
|
||||
end
|
||||
|
||||
# creates an empty clone of an object
|
||||
def create_empty_clone(object)
|
||||
empty_clone = object.dup
|
||||
empty_clone.attribute_names.each { |attr| empty_clone[attr] = nil }
|
||||
return empty_clone
|
||||
end
|
||||
|
||||
# gets time floored to proper interval
|
||||
def get_floored_time(input_time, seconds)
|
||||
return Time.zone.at((input_time.to_f / seconds).floor * seconds)
|
||||
end
|
||||
@time_after_json = Time.now
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
@ -1,20 +1,23 @@
|
||||
class MailerController < ApplicationController
|
||||
|
||||
def resetpassword
|
||||
@user = User.find_by_login_or_email(params[:user][:login])
|
||||
def resetpassword
|
||||
# protect against bots
|
||||
render :text => '' and return if params[:userlogin].length > 0
|
||||
|
||||
if @user.nil?
|
||||
session[:mail_message] = t(:account_not_found)
|
||||
else
|
||||
begin
|
||||
@user.reset_perishable_token!
|
||||
# Mailer.password_reset(@user, "https://www.thingspeak.com/users/#{@user.id}/reset_password?token=#{@user.perishable_token}").deliver
|
||||
session[:mail_message] = t(:password_reset_mailed)
|
||||
rescue
|
||||
session[:mail_message] = t(:password_reset_error)
|
||||
end
|
||||
end
|
||||
redirect_to login_path
|
||||
end
|
||||
@user = User.find_by_login_or_email(params[:user][:login])
|
||||
if @user.nil?
|
||||
sleep 2
|
||||
session[:mail_message] = t(:account_not_found)
|
||||
else
|
||||
begin
|
||||
@user.reset_perishable_token!
|
||||
Mailer.password_reset(@user, "#{RESET_PASSWORD_URL}#{@user.id}?token=#{@user.perishable_token}").deliver
|
||||
session[:mail_message] = t(:password_reset_mailed)
|
||||
rescue
|
||||
session[:mail_message] = t(:password_reset_error)
|
||||
end
|
||||
end
|
||||
redirect_to login_path
|
||||
end
|
||||
|
||||
end
|
||||
|
44
app/controllers/maps_controller.rb
Normal file
44
app/controllers/maps_controller.rb
Normal file
@ -0,0 +1,44 @@
|
||||
class MapsController < ApplicationController
|
||||
|
||||
# show map with channel's location
|
||||
def channel_show
|
||||
set_map_vars
|
||||
render :layout => false
|
||||
end
|
||||
|
||||
# show social map with feed points as markers
|
||||
def show
|
||||
set_map_vars
|
||||
render :layout => false
|
||||
end
|
||||
|
||||
# set map variables
|
||||
def set_map_vars
|
||||
# allow these parameters when creating feed querystring
|
||||
feed_params = ['key','days','start','end','round','timescale','average','median','sum','results','status']
|
||||
|
||||
# default map size
|
||||
@width = default_width
|
||||
@height = default_height
|
||||
|
||||
# add extra parameters to querystring
|
||||
@qs = ''
|
||||
params.each do |p|
|
||||
@qs += "&#{p[0]}=#{p[1]}" if feed_params.include?(p[0])
|
||||
end
|
||||
|
||||
# set ssl
|
||||
@ssl = (get_header_value('x_ssl') == 'true')
|
||||
@map_domain = @ssl ? 'https://maps-api-ssl.google.com' : 'http://maps.google.com'
|
||||
@domain = domain(@ssl)
|
||||
end
|
||||
|
||||
private
|
||||
def default_width
|
||||
450
|
||||
end
|
||||
|
||||
def default_height
|
||||
250
|
||||
end
|
||||
end
|
@ -1,7 +1,23 @@
|
||||
class PagesController < ApplicationController
|
||||
layout 'application', :except => [:social_home]
|
||||
|
||||
def home
|
||||
@menu = 'home'
|
||||
end
|
||||
def home
|
||||
@menu = 'home'
|
||||
@title = 'Internet of Things'
|
||||
end
|
||||
|
||||
def social_home; ; end
|
||||
|
||||
def features
|
||||
@menu = 'features'
|
||||
end
|
||||
|
||||
def about
|
||||
@menu = 'about'
|
||||
end
|
||||
|
||||
def headers
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
16
app/controllers/pipes_controller.rb
Normal file
16
app/controllers/pipes_controller.rb
Normal file
@ -0,0 +1,16 @@
|
||||
class PipesController < ApplicationController
|
||||
before_filter :require_admin, :set_admin_menu
|
||||
|
||||
def index
|
||||
@pipes = Pipe.paginate :page => params[:page], :order => 'created_at DESC'
|
||||
end
|
||||
|
||||
def new
|
||||
@pipe = Pipe.new
|
||||
end
|
||||
|
||||
def create
|
||||
|
||||
end
|
||||
|
||||
end
|
161
app/controllers/plugins_controller.rb
Normal file
161
app/controllers/plugins_controller.rb
Normal file
@ -0,0 +1,161 @@
|
||||
class PluginsController < ApplicationController
|
||||
before_filter :require_user, :except => [:show_public, :show]
|
||||
before_filter :set_plugins_menu
|
||||
before_filter :check_permission, :only => ['edit', 'update', 'ajax_update', 'destroy']
|
||||
|
||||
def check_permission
|
||||
@plugin = Plugin.find(params[:id])
|
||||
if @plugin.user_id != current_user.id
|
||||
render :text=> "#{t(:permission)} #{t(:plugin)}", :layout => true
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
def index
|
||||
@plugins = current_user.plugins
|
||||
|
||||
end
|
||||
|
||||
def public_plugins
|
||||
|
||||
channel_id = params[:channel_id].to_i
|
||||
return if channel_id.nil?
|
||||
#private page should display all plugins
|
||||
#plugins = current_user.plugins.where("private_flag = true")
|
||||
@plugin_windows = []
|
||||
plugins = current_user.plugins
|
||||
plugins.each do |plugin|
|
||||
plugin.make_windows channel_id, api_domain #will only make the window the first time
|
||||
@plugin_windows = @plugin_windows + plugin.public_dashboard_windows(channel_id)
|
||||
|
||||
end
|
||||
|
||||
respond_to do |format|
|
||||
format.html { render :partial => 'plugins' }
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def private_plugins
|
||||
channel_id = params[:channel_id].to_i
|
||||
return if channel_id.nil?
|
||||
#private page should display all plugins
|
||||
@plugin_windows = []
|
||||
|
||||
plugins = current_user.plugins
|
||||
|
||||
plugins.each do |plugin|
|
||||
plugin.make_windows channel_id, api_domain #will only make the window the first time
|
||||
@plugin_windows = @plugin_windows + plugin.private_dashboard_windows(channel_id)
|
||||
end
|
||||
respond_to do |format|
|
||||
format.html { render :partial => 'plugins' }
|
||||
end
|
||||
end
|
||||
|
||||
def create
|
||||
# add plugin with defaults
|
||||
@plugin = Plugin.new
|
||||
@plugin.html = read_file('app/views/plugins/default.html')
|
||||
@plugin.css = read_file('app/views/plugins/default.css')
|
||||
@plugin.js = read_file('app/views/plugins/default.js')
|
||||
@plugin.user_id = current_user.id
|
||||
@plugin.private_flag = true
|
||||
@plugin.save
|
||||
|
||||
# now that the plugin is saved, we can create the default name
|
||||
@plugin.name = "#{t(:plugin_default_name)} #{@plugin.id}"
|
||||
@plugin.save
|
||||
|
||||
# redirect to edit the newly created plugin
|
||||
redirect_to edit_plugin_path(@plugin.id)
|
||||
end
|
||||
|
||||
def show
|
||||
# Have to check permissions in the method so I can use show to display public, or private plugins
|
||||
@plugin = Plugin.find(params[:id])
|
||||
if @plugin.private?
|
||||
return if require_user
|
||||
render :text=> "#{t(:permission)} #{t(:plugin)}", :layout => true and return if check_permission
|
||||
end
|
||||
@output = @plugin.html.sub('%%PLUGIN_CSS%%', @plugin.css).sub('%%PLUGIN_JAVASCRIPT%%', @plugin.js)
|
||||
|
||||
if @plugin.private?
|
||||
render :layout => false and return
|
||||
else
|
||||
if request.url.include? api_domain
|
||||
render :layout => false and return
|
||||
else
|
||||
|
||||
protocol = ssl
|
||||
host = api_domain.split('://')[1]
|
||||
|
||||
redirect_to :host => host,
|
||||
:protocol => protocol,
|
||||
:controller => "plugins",
|
||||
:action => "show",
|
||||
:id => @plugin.id and return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def show_public
|
||||
|
||||
@plugin = Plugin.find(params[:id])
|
||||
@output = @plugin.html.sub('%%PLUGIN_CSS%%', @plugin.css).sub('%%PLUGIN_JAVASCRIPT%%', @plugin.js)
|
||||
if @plugin.private?
|
||||
render :layout => false
|
||||
else
|
||||
if request.url.include? 'api_domain'
|
||||
render :layout => false
|
||||
else
|
||||
|
||||
redirect_to :host => api_domain,
|
||||
:controller => "plugins",
|
||||
:action => "show",
|
||||
:id => @plugin.id
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def edit
|
||||
end
|
||||
|
||||
def update
|
||||
@plugin.update_attribute(:name, params[:plugin][:name])
|
||||
@plugin.update_attribute(:private_flag, params[:plugin][:private_flag])
|
||||
@plugin.update_attribute(:css, params[:plugin][:css])
|
||||
@plugin.update_attribute(:js, params[:plugin][:js])
|
||||
@plugin.update_attribute(:html,params[:plugin][:html])
|
||||
|
||||
if @plugin.save
|
||||
|
||||
@plugin.update_all_windows
|
||||
redirect_to plugins_path and return
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def ajax_update
|
||||
status = 0
|
||||
@plugin.update_attribute(:name, params[:plugin][:name])
|
||||
@plugin.update_attribute(:private_flag, params[:plugin][:private_flag])
|
||||
@plugin.update_attribute(:css, params[:plugin][:css])
|
||||
@plugin.update_attribute(:js, params[:plugin][:js])
|
||||
@plugin.update_attribute(:html, params[:plugin][:html])
|
||||
|
||||
if @plugin.save
|
||||
@plugin.update_all_windows
|
||||
status = 1
|
||||
end
|
||||
|
||||
# return response: 1=success, 0=failure
|
||||
render :json => status.to_json
|
||||
end
|
||||
|
||||
def destroy
|
||||
@plugin.destroy
|
||||
redirect_to plugins_path
|
||||
end
|
||||
end
|
@ -1,114 +1,158 @@
|
||||
class StatusController < ApplicationController
|
||||
require 'csv'
|
||||
require 'csv'
|
||||
layout false
|
||||
|
||||
def index
|
||||
@channel = Channel.find(params[:channel_id])
|
||||
@api_key = ApiKey.find_by_api_key(get_userkey)
|
||||
@success = channel_permission?(@channel, @api_key)
|
||||
def recent
|
||||
logger.info "Domain is #{@domain}"
|
||||
channel = Channel.find(params[:channel_id])
|
||||
@channel_id = channel.id
|
||||
if channel.public_flag || (current_user && current_user.id == channel.user_id)
|
||||
@statuses = channel.recent_statuses
|
||||
respond_to do |format|
|
||||
format.html { render :partial => 'status/recent' }
|
||||
format.json { render :json => @statuses}
|
||||
end
|
||||
else
|
||||
respond_to do |format|
|
||||
format.json { render :json => 'Status are not public' }
|
||||
format.html { render :text => 'Sorry the statuses are not public' }
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# check for access
|
||||
if @success
|
||||
# create options hash
|
||||
channel_options = { :only => channel_select_terse(@channel) }
|
||||
|
||||
# display only 1 day by default
|
||||
params[:days] = 1 if !params[:days]
|
||||
def index
|
||||
@channel = Channel.find(params[:channel_id])
|
||||
@api_key = ApiKey.find_by_api_key(get_apikey)
|
||||
@success = channel_permission?(@channel, @api_key)
|
||||
|
||||
# get feed based on conditions
|
||||
@feeds = Feed.find(
|
||||
:all,
|
||||
:conditions => { :channel_id => @channel.id, :created_at => get_date_range(params) },
|
||||
:select => [:created_at, :status],
|
||||
:order => 'created_at'
|
||||
)
|
||||
# check for access
|
||||
if @success
|
||||
# create options hash
|
||||
channel_options = { :only => channel_select_terse(@channel) }
|
||||
|
||||
# set output correctly
|
||||
if params[:format] == 'xml'
|
||||
@channel_output = @channel.to_xml(channel_options).sub('</channel>', '').strip
|
||||
@feed_output = @feeds.to_xml(:skip_instruct => true).gsub(/\n/, "\n ").chop.chop
|
||||
elsif params[:format] == 'csv'
|
||||
@csv_headers = [:created_at, :status]
|
||||
@feed_output = @feeds
|
||||
else
|
||||
@channel_output = @channel.to_json(channel_options).chop
|
||||
@feed_output = @feeds.to_json
|
||||
end
|
||||
# else set error code
|
||||
else
|
||||
if params[:format] == 'xml'
|
||||
@channel_output = bad_channel_xml
|
||||
else
|
||||
@channel_output = '-1'.to_json
|
||||
end
|
||||
end
|
||||
# display only 1 day by default
|
||||
params[:days] = 1 if !params[:days]
|
||||
|
||||
# set callback for jsonp
|
||||
@callback = params[:callback] if params[:callback]
|
||||
|
||||
# output data in proper format
|
||||
respond_to do |format|
|
||||
format.html { render :text => @feed_output }
|
||||
format.json { render "feed/index" }
|
||||
format.xml { render "feed/index" }
|
||||
format.csv { render "feed/index" }
|
||||
end
|
||||
end
|
||||
# set limits
|
||||
limit = (request.format == 'csv') ? 1000000 : 8000
|
||||
limit = params[:results].to_i if (params[:results] and params[:results].to_i < 8000)
|
||||
|
||||
def show
|
||||
@channel = Channel.find(params[:channel_id])
|
||||
@api_key = ApiKey.find_by_api_key(params[:key])
|
||||
output = '-1'
|
||||
# get feed based on conditions
|
||||
@feeds = @channel.feeds.find(
|
||||
:all,
|
||||
:conditions => { :created_at => get_date_range(params) },
|
||||
:select => [:created_at, :entry_id, :status],
|
||||
:order => 'created_at desc',
|
||||
:limit => limit
|
||||
)
|
||||
|
||||
# get most recent entry if necessary
|
||||
params[:id] = @channel.last_entry_id if params[:id] == 'last'
|
||||
# sort properly
|
||||
@feeds.reverse!
|
||||
|
||||
@feed = Feed.find(
|
||||
:first,
|
||||
:conditions => { :channel_id => @channel.id, :entry_id => params[:id] },
|
||||
:select => [:created_at, :status]
|
||||
)
|
||||
@success = channel_permission?(@channel, @api_key)
|
||||
|
||||
# check for access
|
||||
if @success
|
||||
# set output correctly
|
||||
if params[:format] == 'xml'
|
||||
output = @feed.to_xml
|
||||
elsif params[:format] == 'csv'
|
||||
@csv_headers = [:created_at, :entry_id, :status]
|
||||
elsif (params[:format] == 'txt' or params[:format] == 'text')
|
||||
output = add_prepend_append(@feed.status)
|
||||
else
|
||||
output = @feed.to_json
|
||||
end
|
||||
# else set error code
|
||||
else
|
||||
if params[:format] == 'xml'
|
||||
output = bad_feed_xml
|
||||
else
|
||||
output = '-1'.to_json
|
||||
end
|
||||
end
|
||||
# set output correctly
|
||||
if request.format == 'xml'
|
||||
@channel_output = @channel.to_xml(channel_options).sub('</channel>', '').strip
|
||||
@feed_output = @feeds.to_xml(:skip_instruct => true).gsub(/\n/, "\n ").chop.chop
|
||||
elsif request.format == 'csv'
|
||||
@csv_headers = [:created_at, :entry_id, :status]
|
||||
@feed_output = @feeds
|
||||
else
|
||||
@channel_output = @channel.to_json(channel_options).chop
|
||||
@feed_output = @feeds.to_json
|
||||
end
|
||||
# else set error code
|
||||
else
|
||||
if params[:format] == 'xml'
|
||||
@channel_output = bad_channel_xml
|
||||
else
|
||||
@channel_output = '-1'.to_json
|
||||
|
||||
# output data in proper format
|
||||
respond_to do |format|
|
||||
format.html { render :json => output }
|
||||
format.json { render :json => output, :callback => params[:callback] }
|
||||
format.xml { render :xml => output }
|
||||
format.csv { render :action => 'feed/show' }
|
||||
format.text { render :text => output }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# set callback for jsonp
|
||||
@callback = params[:callback] if params[:callback]
|
||||
|
||||
# output data in proper format
|
||||
respond_to do |format|
|
||||
|
||||
format.html { render :template => 'feed/index' }
|
||||
format.json { render :template => 'feed/index' }
|
||||
format.xml { render :template => 'feed/index' }
|
||||
format.csv { render :template => 'feed/index' }
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
def show
|
||||
@channel = Channel.find(params[:channel_id])
|
||||
@api_key = ApiKey.find_by_api_key(get_apikey)
|
||||
output = '-1'
|
||||
|
||||
# get most recent entry if necessary
|
||||
params[:id] = @channel.last_entry_id if params[:id] == 'last'
|
||||
|
||||
|
||||
@feed = @channel.feeds.find(
|
||||
:first,
|
||||
:conditions => { :entry_id => params[:id] },
|
||||
:select => [:created_at, :entry_id, :status]
|
||||
)
|
||||
|
||||
@success = channel_permission?(@channel, @api_key)
|
||||
|
||||
# check for access
|
||||
if @success
|
||||
# set output correctly
|
||||
|
||||
if request.format == 'xml'
|
||||
output = @feed.to_xml
|
||||
elsif request.format == 'csv'
|
||||
@csv_headers = [:created_at, :entry_id, :status]
|
||||
elsif (request.format == 'txt' or request.format == 'text')
|
||||
|
||||
output = add_prepend_append(@feed.status)
|
||||
else
|
||||
output = @feed.to_json
|
||||
end
|
||||
|
||||
# else set error code
|
||||
else
|
||||
if request.format == 'xml'
|
||||
|
||||
output = bad_feed_xml
|
||||
else
|
||||
output = '-1'.to_json
|
||||
end
|
||||
end
|
||||
|
||||
# output data in proper format
|
||||
respond_to do |format|
|
||||
format.html { render :json => output }
|
||||
format.json { render :json => output, :callback => params[:callback] }
|
||||
|
||||
format.xml { render :xml => output }
|
||||
format.csv { render :action => 'feed/show' }
|
||||
|
||||
format.text { render :text => output }
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# only output these fields for channel
|
||||
def channel_select_terse(channel)
|
||||
only = [:name]
|
||||
only += [:latitude] unless channel.latitude.nil?
|
||||
only += [:longitude] unless channel.longitude.nil?
|
||||
only += [:elevation] unless channel.elevation.nil? or channel.elevation.empty?
|
||||
|
||||
return only
|
||||
end
|
||||
|
||||
private
|
||||
# only output these fields for channel
|
||||
def channel_select_terse(channel)
|
||||
only = [:name]
|
||||
only += [:latitude] unless channel.latitude.nil?
|
||||
only += [:longitude] unless channel.longitude.nil?
|
||||
only += [:elevation] unless channel.elevation.nil? or channel.elevation.empty?
|
||||
|
||||
return only
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -1,15 +1,15 @@
|
||||
class SubdomainsController < ApplicationController
|
||||
|
||||
# show a blank page if subdomain
|
||||
def index
|
||||
render :text => ''
|
||||
end
|
||||
# show a blank page if subdomain
|
||||
def index
|
||||
render :text => ''
|
||||
end
|
||||
|
||||
# output the file crossdomain.xml.erb
|
||||
def crossdomain
|
||||
respond_to do |format|
|
||||
format.xml
|
||||
end
|
||||
end
|
||||
# output the file crossdomain.xml.erb
|
||||
def crossdomain
|
||||
respond_to do |format|
|
||||
format.xml
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
37
app/controllers/tags_controller.rb
Normal file
37
app/controllers/tags_controller.rb
Normal file
@ -0,0 +1,37 @@
|
||||
class TagsController < ApplicationController
|
||||
def index
|
||||
|
||||
render 'show' and return if params[:channel_id].nil?
|
||||
|
||||
channel = Channel.find(params[:channel_id])
|
||||
if current_user && channel.nil?
|
||||
tag = Tag.find_by_name(params[:id], :include => :channels, :conditions => ['channels.public_flag = true OR channels.user_id = ?', current_user.id])
|
||||
else
|
||||
channels = []
|
||||
channel.tags.each do |tag|
|
||||
channels << tag.channel_ids
|
||||
end
|
||||
|
||||
channels = channels.flatten.uniq
|
||||
|
||||
end
|
||||
redirect_to public_channels_path(:channel_ids => channels)
|
||||
end
|
||||
|
||||
def create
|
||||
redirect_to tag_path(params[:tag][:name])
|
||||
end
|
||||
|
||||
def show
|
||||
# if user is logged in, search their channels also
|
||||
if current_user
|
||||
tag = Tag.find_by_name(params[:id], :include => :channels, :conditions => ['channels.public_flag = true OR channels.user_id = ?', current_user.id])
|
||||
# else only search public channels
|
||||
else
|
||||
tag = Tag.find_by_name(params[:id], :include => :channels, :conditions => ['channels.public_flag = true'])
|
||||
end
|
||||
|
||||
@results = tag.channels if tag
|
||||
end
|
||||
|
||||
end
|
@ -3,42 +3,53 @@ class UserSessionsController < ApplicationController
|
||||
before_filter :require_user, :only => :destroy
|
||||
|
||||
def new
|
||||
@title = t(:signin)
|
||||
@title = t(:signin)
|
||||
@user_session = UserSession.new
|
||||
@mail_message = session[:mail_message] if !session[:mail_message].nil?
|
||||
@mail_message = session[:mail_message] if !session[:mail_message].nil?
|
||||
end
|
||||
|
||||
def show
|
||||
redirect_to root_path
|
||||
end
|
||||
def show
|
||||
redirect_to root_path
|
||||
end
|
||||
|
||||
def create
|
||||
if params[:userlogin].length > 0
|
||||
render :text => ''
|
||||
else
|
||||
@user_session = UserSession.new(params[:user_session])
|
||||
|
||||
# remember user_id if checkbox is checked
|
||||
if params[:user_session][:remember_id] == '1'
|
||||
cookies['user_id'] = { :value => params[:user_session][:login], :expires => 1.month.from_now }
|
||||
else
|
||||
cookies.delete 'user_id'
|
||||
end
|
||||
if params[:userlogin].length > 0
|
||||
render :text => ''
|
||||
else
|
||||
@user_session = UserSession.new(params[:user_session])
|
||||
|
||||
if @user_session.save
|
||||
redirect_to root_path and return
|
||||
else
|
||||
# prevent timing and brute force password attacks
|
||||
sleep 1
|
||||
@failed = true
|
||||
render :action => :new
|
||||
end
|
||||
end
|
||||
# remember user_id if checkbox is checked
|
||||
if params[:user_session][:remember_id] == '1'
|
||||
cookies['user_id'] = { :value => params[:user_session][:login], :expires => 1.month.from_now }
|
||||
else
|
||||
cookies.delete 'user_id'
|
||||
end
|
||||
|
||||
if @user_session.save
|
||||
# if link_back, redirect back
|
||||
redirect_to session[:link_back] and return if session[:link_back]
|
||||
redirect_to channels_path and return
|
||||
else
|
||||
# log to failedlogins
|
||||
failed = Failedlogin.new
|
||||
failed.login = params[:user_session][:login]
|
||||
failed.password = params[:user_session][:password]
|
||||
failed.ip_address = get_header_value('X_REAL_IP')
|
||||
failed.save
|
||||
|
||||
# prevent timing and brute force password attacks
|
||||
sleep 1
|
||||
@failed = true
|
||||
render :action => :new
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
session[:link_back] = nil
|
||||
current_user_session.destroy
|
||||
reset_session
|
||||
redirect_to root_path
|
||||
reset_session
|
||||
redirect_to root_path
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,85 +1,180 @@
|
||||
class UsersController < ApplicationController
|
||||
include KeyUtilities
|
||||
before_filter :require_no_user, :only => [:new, :create, :forgot_password]
|
||||
before_filter :require_user, :only => [:show, :edit, :update, :change_password]
|
||||
before_filter :require_user, :only => [:show, :edit, :update, :change_password, :edit_profile]
|
||||
|
||||
# generates a new api key
|
||||
def new_api_key
|
||||
current_user.set_new_api_key!
|
||||
redirect_to account_path
|
||||
end
|
||||
|
||||
# edit public profile
|
||||
def edit_profile
|
||||
@user = current_user
|
||||
end
|
||||
|
||||
# update public profile
|
||||
def update_profile
|
||||
@user = current_user # makes our views "cleaner" and more consistent
|
||||
# update
|
||||
@user.update_attributes(user_params)
|
||||
redirect_to account_path
|
||||
end
|
||||
|
||||
# public profile for a user
|
||||
def profile
|
||||
# set params and request.format correctly
|
||||
set_request_details!(params)
|
||||
|
||||
@user = User.find_by_login(params[:id])
|
||||
|
||||
# output error if user not found
|
||||
render :text => t(:user_not_found) and return if @user.nil?
|
||||
|
||||
# if a json or xml request
|
||||
if request.format == :json || request.format == :xml
|
||||
# authenticate the user if api key matches the target user
|
||||
authenticated = (User.find_by_api_key(get_apikey) == @user)
|
||||
# set options correctly
|
||||
options = authenticated ? User.private_options : User.public_options(@user)
|
||||
end
|
||||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.json { render :json => @user.as_json(options) }
|
||||
format.xml { render :xml => @user.to_xml(options) }
|
||||
end
|
||||
end
|
||||
|
||||
# list all public channels for a user
|
||||
def list_channels
|
||||
@user = User.find_by_login(params[:id])
|
||||
|
||||
# output error if user not found
|
||||
render :text => t(:user_not_found) and return if @user.nil?
|
||||
|
||||
# if html request
|
||||
if request.format == :html
|
||||
@title = "Internet of Things - Public Channels for #{@user.login}"
|
||||
@channels = @user.channels.public_viewable.paginate :page => params[:page], :order => 'last_entry_id DESC'
|
||||
# if a json or xml request
|
||||
elsif request.format == :json || request.format == :xml
|
||||
# authenticate the user if api key matches the target user
|
||||
authenticated = (User.find_by_api_key(get_apikey) == @user)
|
||||
# get all channels if authenticated, otherwise only public ones
|
||||
channels = authenticated ? @user.channels : @user.channels.public_viewable
|
||||
# set channels correctly
|
||||
@channels = { channels: channels.as_json(Channel.public_options) }
|
||||
end
|
||||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.json { render :json => @channels }
|
||||
format.xml { render :xml => @channels.to_xml(:root => 'response') }
|
||||
end
|
||||
end
|
||||
|
||||
def new
|
||||
@title = t(:signup)
|
||||
@title = t(:signup)
|
||||
@user = User.new
|
||||
end
|
||||
|
||||
|
||||
def create
|
||||
@user = User.new(params[:user])
|
||||
@user = User.new(user_params)
|
||||
@user.api_key = generate_api_key(16, 'user')
|
||||
|
||||
# save user
|
||||
if @user.valid?
|
||||
if @user.save
|
||||
redirect_back_or_default account_path
|
||||
end
|
||||
else
|
||||
render :action => :new
|
||||
end
|
||||
# save user
|
||||
if @user.valid?
|
||||
|
||||
if @user.save
|
||||
redirect_back_or_default channels_path and return
|
||||
end
|
||||
else
|
||||
render :action => :new
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
def show
|
||||
@menu = 'account'
|
||||
@user = current_user
|
||||
@menu = 'account'
|
||||
@user = @current_user
|
||||
end
|
||||
|
||||
|
||||
def edit
|
||||
@menu = 'account'
|
||||
@user = current_user
|
||||
@menu = 'account'
|
||||
@user = @current_user
|
||||
end
|
||||
|
||||
# displays forgot password page
|
||||
def forgot_password
|
||||
end
|
||||
# displays forgot password page
|
||||
def forgot_password
|
||||
@user = User.new
|
||||
end
|
||||
|
||||
# this action is called from an email link when a password reset is requested
|
||||
def reset_password
|
||||
# if user has been logged in (due to previous form submission)
|
||||
if !current_user.nil?
|
||||
@user = current_user
|
||||
@user.errors.add(t(:password_problem))
|
||||
@valid_link = true
|
||||
else
|
||||
@user = User.find_by_id(params[:id])
|
||||
# make sure tokens match and password reset is within last 10 minutes
|
||||
if @user.perishable_token == params[:token] && @user.updated_at > 600.seconds.ago
|
||||
@valid_link = true
|
||||
# log the user in
|
||||
@user_session = UserSession.new(@user)
|
||||
@user_session.save
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# do the actual password change
|
||||
def change_password
|
||||
# protect against bots
|
||||
render :text => '' and return if params[:userlogin].length > 0
|
||||
# this action is called from an email link when a password reset is requested
|
||||
def reset_password
|
||||
# if user has been logged in (due to previous form submission)
|
||||
if !current_user.nil?
|
||||
@user = current_user
|
||||
@user.errors.add(:base, t(:password_problem))
|
||||
@valid_link = true
|
||||
else
|
||||
@user = User.find_by_id(params[:id])
|
||||
# make sure tokens match and password reset is within last 10 minutes
|
||||
if @user.perishable_token == params[:token] && @user.updated_at > 600.seconds.ago
|
||||
@valid_link = true
|
||||
# log the user in
|
||||
@user_session = UserSession.new(@user)
|
||||
@user_session.save
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# do the actual password change
|
||||
def change_password
|
||||
@user = current_user
|
||||
# if no password entered, redirect
|
||||
redirect_to reset_password_path and return if params[:user][:password].empty?
|
||||
# check current password and update
|
||||
if @user.update_attributes(params[:user])
|
||||
# if no password entered, redirect
|
||||
redirect_to reset_password_path and return if params[:user][:password].empty?
|
||||
# check current password and update
|
||||
if @user.update_attributes(user_params)
|
||||
redirect_to account_path
|
||||
else
|
||||
redirect_to reset_password_path
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
@menu = 'account'
|
||||
@user = current_user # makes our views "cleaner" and more consistent
|
||||
# check current password and update
|
||||
if @user.valid_password?(params[:password_current]) && @user.update_attributes(params[:user])
|
||||
@menu = 'account'
|
||||
@user = @current_user # makes our views "cleaner" and more consistent
|
||||
# check current password and update
|
||||
if @user.valid_password?(params[:password_current]) && @user.update_attributes(user_params)
|
||||
redirect_to account_path
|
||||
else
|
||||
@user.errors.add :base, t(:password_incorrect)
|
||||
render :edit
|
||||
@user.errors.add(:base, t(:password_incorrect))
|
||||
render :action => :edit
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
private
|
||||
|
||||
# only allow these params
|
||||
def user_params
|
||||
params.require(:user).permit(:email, :login, :time_zone, :public_flag, :bio, :website, :password, :password_confirmation)
|
||||
end
|
||||
|
||||
# set params[:id] and request.format correctly
|
||||
def set_request_details!(params)
|
||||
# set format
|
||||
new_format = 'html' if params[:glob].end_with?('.html')
|
||||
new_format = 'json' if params[:glob].end_with?('.json')
|
||||
new_format = 'xml' if params[:glob].end_with?('.xml')
|
||||
|
||||
# remove the format from the end of the glob
|
||||
params[:id] = params[:glob].chomp(".#{new_format}")
|
||||
|
||||
# set the new format if it exists
|
||||
request.format = new_format.to_sym if new_format.present?
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
219
app/controllers/windows_controller.rb
Normal file
219
app/controllers/windows_controller.rb
Normal file
@ -0,0 +1,219 @@
|
||||
class WindowsController < ApplicationController
|
||||
before_filter :require_user, :except => [:index, :html, :iframe]
|
||||
|
||||
def hide
|
||||
window = Window.find(params[:id])
|
||||
window.show_flag = false
|
||||
if window.save
|
||||
render :text => window.id.to_s
|
||||
else
|
||||
render :text => '-1'
|
||||
end
|
||||
end
|
||||
|
||||
# Call WindowsController.display when we want to display a window on the dashboard
|
||||
# params[:visibility_flag] is whether it is the private or public dashboard
|
||||
# params[:plugin] is for displaying a plugin, instead of a window
|
||||
# params[:id] is the window ID for conventional windows, but the plugin_id for plugins
|
||||
# params[:channel_id] is the channel_id
|
||||
def display
|
||||
@visibility = params[:visibility_flag]
|
||||
|
||||
window = Window.find(params[:id])
|
||||
window = Window.new if window.nil?
|
||||
window.show_flag = true
|
||||
#Just save this change, then modify the object before rendering the JSON
|
||||
savedWindow = window.save
|
||||
|
||||
config_window window
|
||||
|
||||
@mychannel = current_user && current_user.id == window.channel.user_id
|
||||
|
||||
if savedWindow
|
||||
render :json => window.to_json
|
||||
else
|
||||
render :json => 'An error occurred'.to_json
|
||||
end
|
||||
end
|
||||
|
||||
def config_window(window)
|
||||
if window.type == "PluginWindow"
|
||||
pluginName = Plugin.find(window.window_detail.plugin_id).name
|
||||
window.title = t(window.title, {:name => pluginName})
|
||||
elsif window.type == "ChartWindow"
|
||||
window.title = t(window.title, {:field_number => window.window_detail.field_number})
|
||||
options = window.becomes(ChartWindow).window_detail.options if !window.becomes(ChartWindow).window_detail.nil?
|
||||
options ||= ""
|
||||
window.html["::OPTIONS::"] = options unless window.html.nil? || window.html.index("::OPTIONS::").nil?
|
||||
else
|
||||
window.title = t(window.title)
|
||||
end
|
||||
end
|
||||
def html
|
||||
window = Window.find(params[:id])
|
||||
options = window.window_detail.options unless window.window_detail.nil? || window.type!="ChartWindow"
|
||||
window.html["::OPTIONS::"] = options unless window.html.nil? || window.html.index("::OPTIONS::").nil?
|
||||
html = window.html
|
||||
|
||||
render :text => html
|
||||
end
|
||||
|
||||
def iframe
|
||||
window = Window.find(params[:id])
|
||||
options = window.window_detail.options unless window.window_detail.nil? || window.type!="ChartWindow"
|
||||
window.html["::OPTIONS::"] = options unless window.html.nil? || window.html.index("::OPTIONS::").nil?
|
||||
iframe_html = window.html
|
||||
|
||||
iframe_html = iframe_html.gsub(/src=\"[\/.]/, 'src="' + api_domain);
|
||||
render :text => iframe_html
|
||||
end
|
||||
|
||||
def index
|
||||
channel = Channel.find(params[:channel_id])
|
||||
|
||||
channel.update_status_portlet false if (channel.windows.select { |w| w.wtype == :status && w.private_flag == false } )
|
||||
channel.update_status_portlet true if (channel.windows.select { |w| w.wtype == :status && w.private_flag == true } )
|
||||
channel.update_video_portlet false if (channel.windows.select { |w| w.wtype == :video && w.private_flag == false } )
|
||||
channel.update_video_portlet true if (channel.windows.select { |w| w.wtype == :video && w.private_flag == true } )
|
||||
channel.update_location_portlet false if (channel.windows.select { |w| w.wtype == :location && w.private_flag == false } )
|
||||
channel.update_location_portlet true if (channel.windows.select { |w| w.wtype == :location && w.private_flag == true } )
|
||||
channel.update_chart_portlets if (channel.windows.select { |w| w.wtype == :chart } )
|
||||
windows = channel.public_windows(true).order(:position) unless params[:channel_id].nil?
|
||||
|
||||
if channel.recent_statuses.nil? || channel.recent_statuses.size <= 0
|
||||
@windows = windows.delete_if { |w| w.wtype == "status" }
|
||||
else
|
||||
@windows = windows
|
||||
end
|
||||
|
||||
@windows.each do |window|
|
||||
|
||||
if window.type == "PluginWindow"
|
||||
pluginName = Plugin.find(window.window_detail.plugin_id).name
|
||||
window.title = t(window.title, {:name => pluginName})
|
||||
elsif window.type == "ChartWindow"
|
||||
window.title = t(window.title, {:field_number => window.window_detail.field_number})
|
||||
options = window.becomes(ChartWindow).window_detail.options if !window.becomes(ChartWindow).window_detail.nil?
|
||||
options ||= ""
|
||||
window.html["::OPTIONS::"] = options unless window.html.nil? || window.html.index("::OPTIONS::").nil?
|
||||
else
|
||||
window.title = t(window.title)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.json { render :json => @windows.as_json( :include => [:window_detail] ) }
|
||||
end
|
||||
end
|
||||
|
||||
# This is going to display windows that are hidden (show_flag = false)
|
||||
# The "visibility_flag" param indicates whether it's public or private visibility
|
||||
def hidden_windows
|
||||
@visibility = params[:visibility_flag]
|
||||
channel = Channel.find(params[:channel_id])
|
||||
|
||||
if @visibility == "private"
|
||||
@windows = channel.private_windows(false) unless channel.nil?
|
||||
else
|
||||
@windows = channel.public_windows(false) unless channel.nil?
|
||||
end
|
||||
@windows.reject! { |window| window.type == "PluginWindow" }
|
||||
@windows.each do |window|
|
||||
if window.type == "PluginWindow"
|
||||
elsif window.type == "ChartWindow"
|
||||
window.title = t(window.title, {:field_number => window.window_detail.field_number})
|
||||
options = window.becomes(ChartWindow).window_detail.options unless window.becomes(ChartWindow).window_detail.nil?
|
||||
options ||= ""
|
||||
window.html["::OPTIONS::"] = options unless window.html.nil? || window.html.index("::OPTIONS::").nil?
|
||||
else
|
||||
window.title = t(window.title)
|
||||
end
|
||||
end
|
||||
|
||||
respond_to do |format|
|
||||
format.html { render :partial => "hidden_windows" }
|
||||
# format.json { render :json => @windows.as_json( :include => [:window_detail] ) }
|
||||
end
|
||||
end
|
||||
|
||||
def private_windows
|
||||
channel = Channel.find(params[:channel_id])
|
||||
|
||||
channel.update_status_portlet false if (channel.windows.select { |w| w.wtype == :status && w.private_flag == false } )
|
||||
channel.update_status_portlet true if (channel.windows.select { |w| w.wtype == :status && w.private_flag == true } )
|
||||
channel.update_video_portlet false if (channel.windows.select { |w| w.wtype == :video && w.private_flag == false } )
|
||||
channel.update_video_portlet true if (channel.windows.select { |w| w.wtype == :video && w.private_flag == true } )
|
||||
channel.update_location_portlet false if (channel.windows.select { |w| w.wtype == :location && w.private_flag == false } )
|
||||
channel.update_location_portlet true if (channel.windows.select { |w| w.wtype == :location && w.private_flag == true } )
|
||||
channel.update_chart_portlets if (channel.windows.select { |w| w.wtype == :chart } )
|
||||
|
||||
windows = channel.private_windows(true).order(:position) unless params[:channel_id].nil?
|
||||
|
||||
if channel.recent_statuses.nil? || channel.recent_statuses.size <= 0
|
||||
@windows = windows.delete_if { |w| w.wtype == "status" }
|
||||
else
|
||||
@windows = windows
|
||||
end
|
||||
|
||||
@windows.each do |window|
|
||||
if window.type == "PluginWindow"
|
||||
windowDetail = window.window_detail
|
||||
pluginName = Plugin.find(windowDetail.plugin_id).name
|
||||
window.title = t(window.title, {:name => pluginName})
|
||||
elsif window.type == "ChartWindow"
|
||||
window.title = t(window.title, {:field_number => window.window_detail.field_number})
|
||||
options = window.becomes(ChartWindow).window_detail.options unless window.becomes(ChartWindow).window_detail.nil?
|
||||
options ||= ""
|
||||
window.html["::OPTIONS::"] = options unless window.html.nil? || window.html.index("::OPTIONS::").nil?
|
||||
else
|
||||
window.title = t(window.title)
|
||||
end
|
||||
end
|
||||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.json { render :json => @windows.as_json( :include => [:window_detail] ) }
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def update
|
||||
logger.info "We're trying to update the windows with " + params.to_s
|
||||
#params for this put are going to look like
|
||||
# page"=>"{\"col\":0,\"positions\":[1,2,3]}"
|
||||
#So.. the position values are Windows.id They should get updated with the ordinal value based
|
||||
# on their array position and the column should get updated according to col value.
|
||||
# Since the windows are order by position, when a window record changes from
|
||||
# col1,position0 -> col0,position0 the entire new column is reordered.
|
||||
# The old column is missing a position, but the remaining are just left to their order
|
||||
# (ie., 0,1,2 become 1,2) Unless they are also changed
|
||||
|
||||
# First parse the JSON in params["page"] ...
|
||||
values = JSON(params[:page])
|
||||
|
||||
# .. then find each window and update with new ordinal position and col.
|
||||
logger.info "Channel id = " + params[:channel_id].to_s
|
||||
@channel = current_user.channels.find(params[:channel_id])
|
||||
col = values["col"]
|
||||
saved = true
|
||||
values["positions"].each_with_index do |p,i|
|
||||
windows = @channel.windows.where({:id => p}) unless p.nil?
|
||||
unless windows.nil? || windows.empty?
|
||||
w = windows[0]
|
||||
w.position = i
|
||||
w.col = col
|
||||
if !w.save
|
||||
saved = false
|
||||
end
|
||||
end
|
||||
end
|
||||
if saved
|
||||
render :text => '0'
|
||||
else
|
||||
render :text => '-1'
|
||||
end
|
||||
|
||||
end
|
||||
end
|
Reference in New Issue
Block a user