update with changes from Production branch

This commit is contained in:
Lee Lawlor
2014-02-17 12:05:39 -05:00
parent 5b640cf9d8
commit a4937fb2e5
384 changed files with 14690 additions and 2242 deletions

View File

@@ -0,0 +1,52 @@
<div class="FL">
<h3><%= t(:api_key_write) %></h3>
<%= @write_key %>
<br /><br />
<%= button_to t(:api_key_write_new), channel_api_keys_path(@channel, :write => 1), :data => { :confirm => t(:confirm_new_api_key) } %>
<br /><br />
<h3><%= t(:api_key_read) %></h3>
<% @read_keys.each do |read_key| %>
<table>
<tr>
<td><%= t(:api_key_key) %>:</td>
<td><%= read_key %></td>
</tr>
<tr>
<td class="VAT"><%= t(:note) %>:</td>
<td>
<%= form_for read_key, :as => :api_key, :url => channel_api_key_path(@channel, read_key), :html => {:method => 'put'} do |f| %>
<%= f.text_area :note, :cols => 30, :rows => 4 %>
</td>
</tr>
<tr>
<td></td>
<td>
<div class="FL"><%= f.submit t(:note_save) %></div>
<% end %>
<%= button_to t(:api_key_delete), channel_api_key_path(@channel, read_key), :method => 'delete', :data => { :confirm => t(:confirm_read_key_delete) } %></td>
</tr>
</table>
<br /><br />
<% end %>
<%= button_to t(:api_key_read_new), channel_api_keys_path(@channel, :write => 0) %>
<br />
</div>
<div id="sidebar">
<ul>
<li>
<div class="helplink">(<a target="_blank" href="http://community.thingspeak.com/documentation/api/#api_keys"><%= t(:help_options) %></a>)</div>
<h2><%= t(:help) %></h2>
<%= t(:help_channel_write_key) %>
<br /><br />
<%= t(:help_channel_read_key) %>
<br /><br />
<%= t(:help_channel_read_key_note) %>
</li>
</ul>
</div>

View File

@@ -1,43 +1,4 @@
<h2>
<%= link_to t(:channels), channels_path %> &raquo;
<%= link_to channel_path(@channel.id) do %> <%= t(:channel) %> <%= @channel.id %><% end %> &raquo;
<%= t(:api_keys) %>
</h2>
<h3><%= t(:api_key_write) %></h3>
<%= @write_key %>
<div id="maincontent">
<%= render :partial => "index" %>
</div>
<br /><br />
<%= button_to t(:api_key_write_new), channel_api_keys_path(@channel, :write => 1), :confirm => t(:confirm_new_api_key) %>
<br /><br />
<h3><%= t(:api_key_read) %></h3>
<% @read_keys.each do |read_key| %>
<table>
<tr>
<td><%= t(:api_key_key) %>:</td>
<td><%= read_key %></td>
</tr>
<tr>
<td class="VAT"><%= t(:note) %>:</td>
<td>
<%= form_for read_key, :as => :api_key, :url => channel_api_key_path(@channel, read_key), :html => {:method => 'put'} do |f| %>
<%= f.text_area :note, :cols => 30, :rows => 4 %>
</td>
</tr>
<tr>
<td></td>
<td>
<div class="FL"><%= f.submit t(:note_save) %></div>
<% end %>
<%= button_to t(:api_key_delete), channel_api_key_path(@channel, read_key) , :method => 'delete', :confirm => t(:confirm_read_key_delete) %></td>
</tr>
</table>
<br /><br />
<% end %>
<%= button_to t(:api_key_read_new), channel_api_keys_path(@channel, :write => 0) %>
<br />

View File

@@ -0,0 +1,118 @@
<div class="row">
<div class="col-xs-12 col-sm-6">
<h4 class="breadcrumb"><%= t(:apps) %></h4>
<div class="col-pad">
<div class="apps">
<%= link_to thingtweets_path do %>
<%= image_tag 'thingtweet.png', :size => '104x104' %>
<br />
<%= t(:thingtweet) %>
<% end %>
</div>
<div class="apps">
<%= link_to thinghttp_index_path do %>
<%= image_tag 'thinghttp.png', :size => '104x104' %>
<br />
<%= t(:thinghttp) %>
<% end %>
</div>
<div class="apps">
<%= link_to tweetcontrol_index_path do %>
<%= image_tag 'tweetcontrol.png', :size => '104x104' %>
<br />
<%= t(:tweetcontrol) %>
<% end %>
</div>
<div class="apps">
<%= link_to reacts_path do %>
<%= image_tag 'react.png', :size => '104x104' %>
<br />
<%= t(:react) %>
<% end %>
</div>
<div class="apps">
<%= link_to talkbacks_path do %>
<%= image_tag 'talkback.png', :size => '104x104' %>
<br />
<%= t(:talkback) %>
<% end %>
</div>
<% if is_admin? %>
<div class="apps">
<%= link_to scheduled_thinghttps_path do %>
<%= image_tag 'scheduled_thinghttp.png', :size => '104x104' %>
<br />
<%= t(:scheduled_thinghttp) %>
<% end %>
</div>
<% end %>
</div>
</div>
<div id="sidebar" class="col-xs-12 col-sm-6">
<h4 class="breadcrumb"><%= t(:help) %></h4>
<div class="col-pad">
<h3>
<%= t(:thingtweet) %>
<div class="helplink">(<a href="http://community.thingspeak.com/documentation/apps/thingtweet/"><%= t(:help_options) %></a>)</div>
</h3>
<%= t(:help_apps_thingtweet) %>
<ul>
<li><a href="http://community.thingspeak.com/tutorials/arduino/update-twitter-with-thingtweet-and-arduino-ethernet-shield/">Arduino Tutorial</a></li>
<li><a href="http://community.thingspeak.com/tutorials/iobridge/updating-a-twitter-status-using-the-thingtweet-app-and-iobridge-io-204/">ioBridge Tutorial</a></li>
</ul>
<br>
<h3>
<%= t(:thinghttp) %>
<div class="helplink">(<a href="http://community.thingspeak.com/documentation/apps/thinghttp/"><%= t(:help_options) %></a>)</div>
</h3>
<%= t(:help_apps_thinghttp) %>
<ul>
<li><a href="http://community.thingspeak.com/tutorials/twilio/make-calls-with-twilio-using-the-thinghttp-app/">Twilio Tutorial</a></li>
<li><a href="http://community.thingspeak.com/tutorials/prowl/send-push-updates-using-prowl-and-thinghttp/">Prowl Tutorial</a></li>
</ul>
<br>
<h3>
<%= t(:tweetcontrol) %>
<div class="helplink">(<a href="http://community.thingspeak.com/documentation/apps/tweetcontrol/"><%= t(:help_options) %></a>)</div>
</h3>
<%= t(:help_apps_tweetcontrol) %>
<br><br>
<h3>
<%= t(:react) %>
<div class="helplink">(<a href="http://community.thingspeak.com/documentation/apps/react/"><%= t(:help_options) %></a>)</div>
</h3>
<%= t(:help_apps_react) %>
<br><br>
<h3>
<%= t(:talkback) %>
<div class="helplink">(<a href="/docs/talkback"><%= t(:help_options) %></a>)</div>
</h3>
<%= t(:help_apps_talkback) %>
</div>
</div>
</div>
<script language="javascript">
$(function() {
$("#sidebar a").attr("target", "_blank");
});
</script>

View File

@@ -0,0 +1,2 @@
<div id="addPortlets" ></div>

View File

@@ -0,0 +1,24 @@
<div id="channel_info" class="FL channelInfo" >
<div class="FL" ><h3 class="channel_info"><%= @channel.name %></h3></div>
<div class="FR list_tags"><%= @channel.list_tags %></div>
<div class="CB"></div>
<p>by <%= link_to @channel.user.login, user_profile_path(@channel.user.login) %></p>
<div class="channelDescription" ><p><%= @channel.description %></p></div>
<p></p>
</div> <!-- end channelInfo -->
<div id="channellinks">
<div class="FR developerlink">
<a id="devInfoLink_<%= zone %>" href="#" class="topLink" ><%= t(:developer_info) %></a>
</div>
<% unless @channel.url.blank? %>
<div class="FR developerlink">
<%= link_to t(:for_more_information), @channel.url, :target => '_blank', :class => 'topLink' %>
</div>
<% end %>
<% if @mychannel %>
<div class="FR developerlink" >
<a href="#" id="portletAddLink_<%= zone %>" class="topLink " ><%= t(:add_portlets) %></a>
</div>
<% end %>
</div> <!-- end channellinks -->

View File

@@ -0,0 +1,29 @@
<div id="devInfo" >
<table class="table_no_header dev_info_table1" >
<tr>
<td class="left"><%= @channel.name %> <%= t(:channel_feed) %>:</td>
<td>
<%= link_to 'JSON', "#{@api_domain}channels/#{@channel.id}/feed.json", :target => "_blank" %>
<%= link_to 'XML', "#{@api_domain}channels/#{@channel.id}/feed.xml", :target => "_blank" %>
<%= link_to 'CSV', "#{@api_domain}channels/#{@channel.id}/feed.csv", :target => "_blank" %>
</td>
</tr>
</table >
<table class="table_no_header dev_info_table2">
<% @channel.attribute_names.each do |attr| %>
<% if attr.index('field') and @channel[attr] and !@channel[attr].empty? %>
<tr>
<td class="left" ><%= t(:field) %> <%= attr[-1] %> <%= t(:data) %>: <%= @channel[attr] %> </td>
<td>
<%= link_to 'JSON', "#{@api_domain}channels/#{@channel.id}/field/#{attr[-1]}.json", :target => "_blank" %>
<%= link_to 'XML', "#{@api_domain}channels/#{@channel.id}/field/#{attr[-1]}.xml", :target => "_blank" %>
<%= link_to 'CSV', "#{@api_domain}channels/#{@channel.id}/field/#{attr[-1]}.csv", :target => "_blank" %>
</td>
</tr>
<% end %>
<% end %>
</table>
</div> <!-- end devInfo -->

View File

@@ -0,0 +1,174 @@
<div class="FL">
<% flash.each do |name, msg| %>
<div id="<%= name %>" class="fade" >
<p><%= msg %></p>
<div class="clear"></div>
</div>
<% end %>
<%= form_for @channel, :html => {:method => 'put'} do |c| %>
<% unless session[:errors].nil?
session[:errors].each do |attr, msg|
@channel.errors.add(attr, msg)
end
session[:errors] = nil %>
<% end %>
<p>
<%= error_messages_for 'channel', :header_message => t(:try_again), :message => t(:channel_error) %>
</p>
<input name='userlogin' class='userlogin' />
<table class="table_no_header">
<tr>
<td class="left"><%= t(:channel_ranking) %></td>
<td><%= @channel.ranking %>%</td>
</tr>
<tr>
<td class="left"><%= t(:channel_id) %></td>
<td><%= @channel.id %></td>
</tr>
<tr>
<td class="left"><%= t(:channel_name) %></td>
<td><%= c.text_field :name %></td>
</tr>
<tr>
<td class="left"><%= t(:channel_description) %></td>
<td><%= c.text_area :description, :cols => 30, :rows => 4 %></td>
</tr>
<%= fields_for :tags do |t| %>
<tr>
<td class="left"><%= t(:tags) %></td>
<td><%= t.text_area :name, :cols => 30, :rows => 2, :value => @channel.list_tags %></td>
</tr>
<% end %>
<tr>
<td class="left"><%= t(:latitude) %></td>
<td><%= c.text_field :latitude %></td>
</tr>
<tr>
<td class="left"><%= t(:longitude) %></td>
<td><%= c.text_field :longitude %></td>
</tr>
<tr>
<td class="left"><%= t(:elevation) %></td>
<td><%= c.text_field :elevation %></td>
</tr>
<tr>
<td class="left"><%= t(:public) %></td>
<td><%= c.check_box :public_flag %></td>
</tr>
<tr>
<td class="left"><%= t(:channel_url) %></td>
<td><%= c.text_field :url %></td>
</tr>
<tr>
<td class="left"><%= t(:video_id) %></td>
<td >
<%= c.text_field :video_id, :class=>'video_narrow'%>
<%= c.radio_button :video_type, 'youtube' %>
<span class="small"><%= t(:youtube) %></span>
<%= c.radio_button :video_type, 'vimeo' %>
<span class="small"><%= t(:vimeo) %></span>
</td>
</tr>
<tr>
<td class="left"><%= t(:field) %> 1</td>
<td><%= c.text_field :field1, :class => 'field' %></td>
</tr>
<tr>
<td class="left"><%= t(:field) %> 2</td>
<td><%= c.text_field :field2, :class => 'field' %></td>
</tr>
<tr>
<td class="left"><%= t(:field) %> 3</td>
<td><%= c.text_field :field3, :class => 'field' %></td>
</tr>
<tr>
<td class="left"><%= t(:field) %> 4</td>
<td><%= c.text_field :field4, :class => 'field' %></td>
</tr>
<tr>
<td class="left"><%= t(:field) %> 5</td>
<td><%= c.text_field :field5, :class => 'field' %></td>
</tr>
<tr>
<td class="left"><%= t(:field) %> 6</td>
<td><%= c.text_field :field6, :class => 'field' %></td>
</tr>
<tr>
<td class="left"><%= t(:field) %> 7</td>
<td><%= c.text_field :field7, :class => 'field' %></td>
</tr>
<tr>
<td class="left"><%= t(:field) %> 8</td>
<td><%= c.text_field :field8, :class => 'field' %></td>
</tr>
<tr>
<td class="left"></td>
<td><%= c.submit t(:channel_update) %></td>
</tr>
</table>
<% end %>
<br /><br />
<h2><%= t(:channel_clear_message) %></h2>
<%= button_to t(:channel_clear), { :controller => 'channels', :action => 'clear', :id => @channel.id }, :data => { :confirm => t(:confirm_channel_clear) } %>
<br /><br />
<h2><%= t(:channel_delete_message) %></h2>
<%= button_to t(:channel_delete), channel_path(@channel.id), :method => 'delete', :data => { :confirm => t(:confirm_channel_delete) } %>
</div>
<div id="sidebar">
<ul>
<li>
<h2><%= t(:help) %></h2>
<%= t(:help_channel_public) %>
<br /><br />
<%= t(:help_channel_url) %>
<br /><br />
<%= t(:help_channel_video) %>
<br /><br />
<%= t(:help_channel_fields) %>
<br /><br />
<%= t(:help_channel_clear) %>
<br /><br />
<%= t(:help_channel_ranking) %>
<br /><br />
</li>
</ul>
</div>
<script type="text/javascript">
// remember default field label
var default_label = '<%= t(:channel_default_field) %>';
// when document is ready
$(function() {
// iterate through each field textbox
$('.field').each(function() {
// if a value is present, show the 'remove' checkbox
if ($(this).val()) {
$(this).after('<span class="small" id="span_' + $(this).attr('id') + '"><input type="checkbox" onclick="removeField(\'' + $(this).attr('id') + '\')" /><span class="up2">remove field</span></span>');
// else disable
} else {
$(this).after('<span class="small" id="span_' + $(this).attr('id') + '"><input type="checkbox" onclick="addField(\'' + $(this).attr('id') + '\')" /><span class="up2">add field</span></span>');
}
});
});
// adds a field
function addField(id) {
$('#span_'+id).remove()
$('#'+id).val(default_label + ' ' + id.substring(id.length-1));
$('#'+id).after('<span class="small" id="span_' + id + '"><input type="checkbox" onclick="removeField(\'' + id + '\')" /><span class="up2">remove field</span></span>');
$('#'+id).select();
}
// removes a field
function removeField(id) {
$('#span_'+id).remove();
$('#'+id).val('');
$('#'+id).after('<span class="small" id="span_' + id + '"><input type="checkbox" onclick="addField(\'' + id + '\')" /><span class="up2">add field</span></span>');
}
</script>

View File

@@ -0,0 +1,48 @@
<div class="FL">
<%= t(:upload_select) %>
<br /><br />
<% flash.each do |name, msg| %>
<div id="<%= name %>" class="fade" >
<p><%= msg %></p>
<div class="clear"></div>
</div>
<% end %>
<%= form_for :upload, :url => upload_channel_path(@channel), :html => { :multipart => true } do |f| %>
<%= f.file_field :csv %>
<br /><br />
<%= t(:time_zone) %>
<%= time_zone_select 'feed', 'time_zone', nil, :default => 'UTC' %>
<br /><br />
<%= f.submit t(:upload), :disable_with => t(:uploading) %>
<% end %>
</div>
<div id="sidebar" >
<ul>
<li>
<div class="helplink">(<a target="_blank" href="http://community.thingspeak.com/documentation/api/#send_data"><%= t(:help_options) %></a>)</div>
<h2><%= t(:help_channel_update) %></h2>
<%= t(:help_channel_post) %>
<div class="code"><%= "#{@api_domain}update" %></div>
<%= t(:help_channel_post_example) %>
<div class="code"><%= "#{@api_domain}update?key=#{@key}&field1=0" %></div>
<br /><br />
<div class="helplink">(<a target="_blank" href="http://community.thingspeak.com/documentation/api/#view_data"><%= t(:help_options) %></a>)</div>
<h2><%= t(:help_channel_feed) %></h2>
<%= t(:help_channel_view) %>
<br />
<div class="code"><%= link_to "#{@api_domain}channels/#{@channel.id}/feed.json?key=#{@key}", "#{@api_domain}channels/#{@channel.id}/feed.json?key=#{@key}", :target => '_blank' %></div>
<br />
</li>
<li>
<div class="helplink">(<a target="_blank" href="http://community.thingspeak.com/documentation/#importer"><%= t(:help_options) %></a>)</div>
<h2><%= t(:help) %></h2>
<%= t(:help_channel_import) %>
</li>
</ul>
</div>

View File

@@ -0,0 +1,23 @@
<div style="width:90%;">
<% @channels.each do |channel| %>
<% channel.ranking = channel.calc_ranking if channel.ranking.blank? %>
<div class="public_channel_box">
<div class="public_channel_inner">
<p class="public_channel_name">
<%= link_to channel.name, channel_path(channel.id), :id => "showsite_#{channel.id}" %>
</p>
<p class="public_channel_user" >by <%= channel.user.login %></p>
<p class="public_channel_desc"><%= channel.description %></p>
<div class="progressbar" rel="<%= channel.ranking %>"></div>
<p class="public_channel_tags">
<% channel.tags.each do |tag| %>
<a href="/channels/public?tag=<%=u tag.name %>"><%= tag.name %></a><% unless tag == channel.tags.last %>, <% end %>
<% end %>
</p>
</div>
</div>
<% end %>
</div>

View File

@@ -0,0 +1,31 @@
<%= render :partial => 'channelinfo', :locals => { :zone => "private" } %>
<div class="channel_stats_location">
<span class="channel_stats_text">Channel Stats</span>
<table>
<tr><td>Created</td><td ><abbr class="timeago channel_time_text" title="<%= @channel.created_at %>" ><%= @channel.created_at %></abbr></td></tr>
<tr><td>Updated</td><td ><abbr class="timeago channel_time_text" title="<%= @channel.updated_at %>" ><%= @channel.updated_at %></abbr></td></tr>
</table>
<span><%= @channel.feeds.count %> Entries</span>
</div>
<div class="CB" >
<div id="private_dialog0" class="column" > </div>
<div id="private_dialog1" class="column" > </div>
</div>
<script>
$(function() {
$("#devInfoLink_private").click(
function(e) {
var element = $("#devInfo");
openDialogCenter(element);
});
$("#portletAddLink_private").click(
function(e) {
$("#addPortlets").load('/channels/<%=@channel.id %>/hidden_windows?visibility_flag=private',
function(e) {
var element = $("#addPortlets");
openDialogCenter(element);
}) ;
});
});
</script>

View File

@@ -0,0 +1,75 @@
<% if @channel.public? %>
<%= render :partial => 'channelinfo', :locals => { :zone => "public" } %>
<div class="CB">
<div id="public_dialog0" class="column" > </div>
<div id="public_dialog1" class="column" > </div>
</div>
<div class="commentlink" >
<% if !current_user %>
<%= link_to t(:comment_add), channel_comments_path(@channel), :class => 'boldlink' %>
<% else %>
<span class="mainlink spanlink boldlink" onclick="$('#commentmain').toggle();"><%= t(:comment_add) %></span>
<% end %>
<div id="commentmain" style="display:none" >
<%= form_for :comment, :url => channel_comments_path(@channel) do |f| %>
<%= f.error_messages %>
<input name='userlogin' class='userlogin' />
<%= f.text_area :body, :rows => 7, :cols => 54 %>
<br />
<%= submit_tag %>
<% end %>
</div>
<br/><br/>
<div id='comments' >
<% @channel.comments.each do |c| %>
<%= render :partial => 'comments/comment', :object => c if c.parent_id.nil? %>
<% end %>
</div>
</div>
<script>
$("#devInfoLink_public").click(function() {
var element = $("#devInfo");
openDialogCenter(element);
});
$("#portletAddLink_public").click(function()
{
$("#addPortlets").load('/channels/<%=@channel.id %>/hidden_windows?visibility_flag=public',
function() {
var element = $("#addPortlets");
openDialogCenter(element);
})
});
// comment flag function
function commentflag(m_id, user_id)
{
$.ajax({
url: '/comments/vote/' + m_id,
type: 'POST',
data: {user_id : user_id},
success: function(data) {
$('#commentflag' + m_id).parent().parent().append("<span id='votemsg" + m_id + "'><br /><br /><%= t(:comment_reported) %></span>");
$('#imgflag' + m_id).attr('src', '/images/flag_red.gif');
$('#flaglink' + m_id).removeAttr('onclick');
$('#flaglink' + m_id).unbind('mouseenter mouseleave');
setTimeout(function() { $("#votemsg" + m_id).fadeOut(); }, 2600);
}
});
return false;
}
</script>
<% else %>
<div class="FL" >
<h3 class="channel_info"><%= t(:channel_not_public) %></h3>
</div>
<% end %>

View File

@@ -0,0 +1,26 @@
<div class="socialButtons" >
<% if current_user %>
<div class="buttonlets padded watchButtonPadding">
<%= check_box_tag 'watch', 1, current_user.watchings.check(current_user.id, @channel.id) %>
<label for="watch" class="watchButtonLabel" >
<div class="watchButtonImage"></div>
<div id="watchText" class="watchButtonText">Watch</div>
</label>
</div>
<% end %>
<div class="addthis_toolbox addthis_default_style buttonlets padded tweetButton" >
<a class="addthis_button_tweet"></a>
</div>
<div class="addthis_toolbox addthis_default_style buttonlets padded facebookButton" >
<a class="addthis_button_facebook_like" fb:like:layout="button_count"></a>
</div>
<div class="addthis_toolbox addthis_default_style buttonlets padded googleplusButton" >
<a class="addthis_button_google_plusone" g:plusone:size="medium"></a>
</div>
<div class="addthis_toolbox addthis_default_style buttonlets padded" >
<a class="addthis_counter addthis_pill_style"></a>
</div>
</div>
<script type="text/javascript" src="https://s7.addthis.com/js/250/addthis_widget.js#pubid=xa-4f9168ce642d4694"></script>

View File

@@ -1,25 +1,79 @@
<h2><%= t(:channels) %></h2>
<% if @channels.length > 0 %>
<table class="nicetable">
<tr class="header TAC">
<td><%= t(:channel_id) %></td>
<td><%= t(:channel_name) %></td>
</tr>
<% @channels.each do |d| %>
<tr>
<td class="left"><%= link_to d.id, channel_path(d.id) %></td>
<td><%= link_to d.name, channel_path(d.id) %></td>
</tr>
<div class="row">
<div class="col-xs-12 col-sm-6">
<h4 class="breadcrumb"><%= t(:channels_my) %></h4>
<div class="col-pad">
<% if @channels.length > 0 %>
<table class="nicetable-borderless">
<% @channels.each do |channel| %>
<% if !channel.social %>
<tr>
<td>
<h3 class="signed_in_channel_header" ><%= link_to channel.name, channel_path(channel.id), :id => "showsite_#{channel.id}" %></h3>
<div class="public_private_icon">
<%= channel.public_flag ? image_tag('icons/Unlocked.png', :title=> t(:public_true)) : image_tag('icons/Locked.png', :title=> t(:channel_not_public)) %>
</div>
</td>
</tr>
<tr><td><p><%= link_to t(:private_link), channel_path(channel.id, :anchor => 'privateview') %> |
<%= link_to t(:public_link), channel_path(channel.id, :anchor => 'publicview') %> |
<%= link_to t(:settings_link), channel_path(channel.id, :anchor => 'channelsettings') %> |
<%= link_to t(:api_key_link), channel_path(channel.id, :anchor => 'apikeys') %> |
<%= link_to t(:data_import_link), channel_path(channel.id, :anchor => 'dataimport') %> </p></td></tr>
<tr><td><p><%= channel.description %></p></td></tr>
<% end %>
<% end %>
</table>
<br />
<% end %>
</table>
<br /><br />
<% end %>
<%= form_for :channel do |d| %>
<input name='userlogin' class='userlogin' />
<%= d.submit t(:channel_create) %>
<% end %>
<%= form_for :channel do |d| %>
<input name='userlogin' class='userlogin' />
<%= d.submit t(:channel_create), :class => 'btn btn-primary' %>
<% end %>
<% if is_admin? %>
<br /><br /><br />
<% @channels.each do |c| %>
<% if c.social %>
<%= t(:social_channel) %>: <%= link_to c.name, (Rails.env == 'production') ? "http://www.socialsensornetwork.com/#{c.slug}" : "/s/#{c.slug}" %>
<br />
<% end %>
<% end %>
<br />
<%= link_to t(:social_channel_create), :controller => 'channels', :action => 'social_new' %>
<% end %>
</div>
</div>
<div id="sidebar" class="col-xs-12 col-sm-6">
<h4 class="breadcrumb"><%= t(:help) %></h4>
<div class="col-pad">
<%= t(:help_channel) %>
(<a href="http://community.thingspeak.com/documentation/api/"><%= t(:help_options) %></a>)
<ul>
<li><a href="http://community.thingspeak.com/tutorials/arduino/using-an-arduino-ethernet-shield-to-update-a-thingspeak-channel/">Arduino Tutorial</a></li>
<li><a href="http://community.thingspeak.com/tutorials/netduino/create-your-own-web-of-things-using-the-netduino-plus-and-thingspeak/">Netduino Plus Tutorial</a></li>
</ul>
</div>
</div>
</div>

View File

@@ -0,0 +1,133 @@
<%= render :partial => "devinfo" %>
<%= render :partial => "addportlet" %>
<div class="col-xs-12 col-sm-6">
<ol class="breadcrumb">
<li><%= link_to t(:channels), channels_path %></li>
<li class="active"><%= t(:channel) %> <%= @channel.id %></li>
</ol>
</div>
<%= render :partial => "socialbuttons" %>
<div id="maincontent" >
<ul>
<li><a href="#privateview"><%= t("private_view") %></a></li>
<li><a href="#publicview"><%= t("public_view") %></a></li>
<li><a href="#channelsettings"><%= t("channel_settings") %></a></li>
<li><a href="#apikeys"><%= t("api_keys") %></a></li>
<li><a href="#dataimport"><%= t("data_import") %></a></li>
</ul>
<div id="privateview">
<%= render :partial => "private_show" %>
</div>
<div id="publicview">
<%= render :partial => "public_show" %>
</div>
<div id="channelsettings">
<%= render :partial => "edit" %>
</div>
<div id="apikeys">
<%= render :partial => "api_keys/index" %>
</div>
<div id="dataimport">
<%= render :partial => "import" %>
</div>
</div>
<script type="text/javascript">
$('#watch').click(function() {
$.update(
'/channels/<%= @channel.id %>/watch',
// data to send
{
flag: this.checked
},
// if post was successful
function (response) {
if ($("#watch").attr("checked")) {
$("#watchText").text("Un-watch");
}
else {
$("#watchText").text("Watch");
}
}
);
});
$(function () {
$(".timeago").timeago();
if(document.location.hash!='') {
$('html').animate({scrollTop:0}, 'normal');//IE, FF
$('body').animate({scrollTop:0}, 'normal');//chrome, don't know if safari works
}
$('.fade').fadeIn('normal').fadeOut(3500, function() {
$(this).remove();
});
$("#devInfo").dialog({
autoOpen:false,
resizable:false,
width:"500px",
title: "<%= t('developer_info') %>",
dialogClass: "dev-info-dialog"
});
$("#addPortlets").dialog({
modal:true,
autoOpen:false,
resizable:false,
width:"500px",
dialogClass: "dev-info-dialog"
});
$("#watch").button();
if ($("#watch").attr("checked")) {
$("#watchText").text("Un-watch");
}
else {
$("#watchText").text("Watch");
}
$("#maincontent").tabs( {
select: function( e, ui)
{
$.cookie('stickyTab', ui.index );
}
}
);
stickyTab = $.cookie( 'stickyTab' );
anchor = window.location.hash;
if (anchor.length > 0) {
stickyTab = anchor.substring(anchor.length - 1);
}
if( ! isNaN( stickyTab ) )
{
$("#maincontent").tabs( 'select', stickyTab );
}
var current_user = "<%= @mychannel %>";
var channel_id = <%= @channel.id %>;
setupColumns(current_user, channel_id);
$.getJSON('/channels/<%=@channel.id %>/private_windows.json', function(data) {
createWindowsWithData (data, current_user, channel_id, "private");
$.getJSON('/channels/<%=@channel.id %>/windows.json',
createWindows (current_user, channel_id, "public")
);
});
});
</script>

View File

@@ -0,0 +1,11 @@
<div class="row">
<div class="col-xs-12 col-sm-12">
<h4 class="breadcrumb"><%= flash[:notice] %></h4>
<%= render :partial => 'list' %>
<br />
<%= will_paginate @channels %>
</div>
</div>

View File

@@ -0,0 +1,92 @@
<%= render :partial => "devinfo" %>
<div class="col-xs-12 col-sm-6">
<ol class="breadcrumb">
<li><%= link_to t(:channels), auth_channels_path %></li>
<li class="active"><%= t(:channel) %> <%= @channel.id %></li>
</ol>
</div>
<%= render :partial=>"socialbuttons" %>
<div id="maincontent">
<ul>
<li><a href="#publicview">Public View</a></li>
</ul>
<div id="publicview">
<%= render :partial => "public_show" %>
</div>
</div>
<script type="text/javascript">
$('#watch').click(function() {
$.update(
'/channels/<%= @channel.id %>/watch',
{
flag: this.checked
},
function (response) {
if ($("#watch").attr("checked")) {
$("#watchText").text("Un-watch");
}
else {
$("#watchText").text("Watch");
}
}
);
});
$("#devInfoLink").click(function() {
$("#devInfo").dialog("open") ;
});
$(function () {
$("#devInfo").dialog({
autoOpen:false,
resizable:false,
width:"500px",
position: {
my: 'top',
at: 'top',
of: $('#maincontent')
},
title: "Developer Info",
dialogClass: "dev-info-dialog"
});
$("#watch").button();
if ($("#watch").attr("checked")) {
$("#watchText").text("Un-watch");
}
else {
$("#watchText").text("Watch");
}
$("#maincontent").tabs( {
select: function( e, ui)
{
$.cookie('stickyTab', ui.index );
}
}
);
stickyTab = $.cookie( 'stickyTab' );
if( ! isNaN( stickyTab ) )
{
$("#maincontent").tabs( 'select', stickyTab );
}
var current_user = "<%= @mychannel %>" ;
var channel_id = <%= @channel.id %>;
$.getJSON('/channels/<%=@channel.id %>/windows.json', createWindows (current_user, channel_id, "public") )
.complete(function() {
setupColumns(current_user, channel_id);
})
});
</script>

View File

@@ -0,0 +1,93 @@
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="<%= @domain %>javascripts/timeago.min.js"></script>
<style type="text/css">
html, body { margin: 0; padding: 0; font-family: Helvetica, Arial, sans-serif; color: #333333; font-size: 16px;}
.indent { margin-left: 28px; padding: 2px;}
.small { font-size: 80%; }
.status { padding: 3px; color: #ffffff; background-color: #62a09d; }
.timeago { font-size: 10px; }
</style>
<script type="text/javascript">
$(document).ready(function() {
var html = '';
var field1, field2, field3, field4, field5, field6, field7, field8;
// get the data with a webservice call
$.getJSON('<%= "#{@domain}channels/#{params[:channel_id]}/feed.json?callback=?&offset=0&results=10&location=true&status=true" %>', function(data) {
// set channel field names
if (data.channel.field1) { field1 = data.channel.field1; }
if (data.channel.field2) { field2 = data.channel.field2; }
if (data.channel.field3) { field3 = data.channel.field3; }
if (data.channel.field4) { field4 = data.channel.field4; }
if (data.channel.field5) { field5 = data.channel.field5; }
if (data.channel.field6) { field6 = data.channel.field6; }
if (data.channel.field7) { field7 = data.channel.field7; }
if (data.channel.field8) { field8 = data.channel.field8; }
// iterate through each feed
$.each(data.feeds.reverse(), function() {
if (this.location) {
html += '<div id="entry_' + this.entry_id + '"><b><img src="<%= "#{@domain}images/icon_location_24.png" %>" width="24" height="24" border="0" align="absbottom" /> ' + this.location + '</b></div>';
if (this.field1) { html += '<div class="indent">' + data.channel.field1 + ': ' + this.field1 + '</div>'; }
if (this.field2) { html += '<div class="indent">' + data.channel.field2 + ': ' + this.field2 + '</div>'; }
if (this.field3) { html += '<div class="indent">' + data.channel.field3 + ': ' + this.field3 + '</div>'; }
if (this.field4) { html += '<div class="indent">' + data.channel.field4 + ': ' + this.field4 + '</div>'; }
if (this.field5) { html += '<div class="indent">' + data.channel.field5 + ': ' + this.field5 + '</div>'; }
if (this.field6) { html += '<div class="indent">' + data.channel.field6 + ': ' + this.field6 + '</div>'; }
if (this.field7) { html += '<div class="indent">' + data.channel.field7 + ': ' + this.field7 + '</div>'; }
if (this.field8) { html += '<div class="indent">' + data.channel.field8 + ': ' + this.field8 + '</div>'; }
if (this.status) { html += '<div class="indent"><span class="status">"' + this.status + '"</span></div>'; }
html += '<div class="indent small"><abbr class="timeago" title="' + this.created_at + '">' + this.created_at + '</abbr></div>';
html += '<div>&nbsp;</div>';
}
});
// write data to page
$('#feed-container').html(html);
// add timeago
$('abbr.timeago').timeago();
// push data every 15 seconds
setInterval(function() {
// get the data with a webservice call
$.getJSON('<%= "#{@domain}channels/#{params[:channel_id]}/feed/last.json?callback=?&offset=0&location=true&status=true" %>', function(data) {
// if data exists and entry id doesn't already exist
if (data.location && $('#entry_' + data.entry_id).length == 0) {
html = '<div id="entry_' + data.entry_id + '"><b><img src="<%= "#{@domain}images/icon_location_24.png" %>" width="24" height="24" border="0" align="absbottom" /> ' + data.location + '</b></div>';
if (data.field1) { html += '<div class="indent">' + field1 + ': ' + data.field1 + '</div>'; }
if (data.field2) { html += '<div class="indent">' + field2 + ': ' + data.field2 + '</div>'; }
if (data.field3) { html += '<div class="indent">' + field3 + ': ' + data.field3 + '</div>'; }
if (data.field4) { html += '<div class="indent">' + field4 + ': ' + data.field4 + '</div>'; }
if (data.field5) { html += '<div class="indent">' + field5 + ': ' + data.field5 + '</div>'; }
if (data.field6) { html += '<div class="indent">' + field6 + ': ' + data.field6 + '</div>'; }
if (data.field7) { html += '<div class="indent">' + field7 + ': ' + data.field7 + '</div>'; }
if (data.field8) { html += '<div class="indent">' + field8 + ': ' + data.field8 + '</div>'; }
if (data.status) { html += '<div class="indent"><span class="status">"' + data.status + '"</span></div>'; }
html += '<div class="indent small"><abbr class="timeago" title="' + data.created_at + '">' + data.created_at + '</abbr></div>';
html += '<div>&nbsp;</div>';
// write data to page
$(html).prependTo('#feed-container').hide().slideDown();
// add timeago
$('abbr.timeago').timeago();
}
});
}, 15000);
});
});
</script>
</head>
<body style='background-color: <%= params[:bgcolor] ? params[:bgcolor] : 'transparent' %>;'>
<div id="feed-container"></div>
</body>
</html>

View File

@@ -0,0 +1,107 @@
<div id="maincontent" class="thin">
<h2>
<%= link_to t(:channels), channels_path %> &raquo;
<%= t(:social_channel_new) %>
</h2>
<%= form_for @channel, :url => { :action => 'social_create' } do |c| %>
<%= error_messages_for 'channel', :header_message => t(:try_again), :message => t(:channel_error) %>
<input name='userlogin' class='userlogin' />
<table class="table_no_header">
<tr>
<td class="left"><%= t(:channel_name) %></td>
<td><%= c.text_field :name %></td>
</tr>
<tr>
<td class="left"><%= t(:slug) %></td>
<td><%= c.text_field :slug %></td>
</tr>
<tr>
<td class="left"><%= t(:channel_directions) %></td>
<td><%= c.text_area :description, :cols => 30, :rows => 4 %></td>
</tr>
<%= fields_for :tags do |t| %>
<tr>
<td class="left"><%= t(:tags) %></td>
<td><%= t.text_area :name, :cols => 30, :rows => 2, :value => @channel.list_tags %></td>
</tr>
<% end %>
<tr>
<td class="left"><%= t(:field) %> 1</td>
<td><%= c.text_field :field1 %></td>
</tr>
<tr>
<td class="left"><%= t(:field) %> 2</td>
<td><%= c.text_field :field2 %></td>
</tr>
<tr>
<td class="left"><%= t(:field) %> 3</td>
<td><%= c.text_field :field3 %></td>
</tr>
<tr>
<td class="left"><%= t(:field) %> 4</td>
<td><%= c.text_field :field4 %></td>
</tr>
<tr>
<td class="left"><%= t(:field) %> 5</td>
<td><%= c.text_field :field5 %></td>
</tr>
<tr>
<td class="left"><%= t(:field) %> 6</td>
<td><%= c.text_field :field6 %></td>
</tr>
<tr>
<td class="left"><%= t(:field) %> 7</td>
<td><%= c.text_field :field7 %></td>
</tr>
<tr>
<td class="left"><%= t(:field) %> 8</td>
<td><%= c.text_field :field8 %></td>
</tr>
<tr>
<td class="left"><%= t(:message_field) %></td>
<td><%= c.text_field :status %></td>
</tr>
<tr>
<td class="left"></td>
<td><%= c.submit t(:social_channel_create) %></td>
</tr>
</table>
<% end %>
</div>
<div id="sidebar" class="ML60 medium">
<ul>
<li>
<h2><%= t(:help) %></h2>
<%= t(:help_social_channel) %>
<br /><br />
<div class="code">http://www.socialsensornetwork.com/<b>slug</b></div>
<br />
<%= t(:help_social_channel_public) %>
</li>
</ul>
</div>
<script type="text/javascript">
// sets the slug field
function slugify() {
$('#channel_slug').val($('#channel_name').val().replace(/ /g, '-').replace(/[^0-9\-a-zA-Z]+/g, '').toLowerCase());
}
// when document is ready
$(function() {
// events to automatically create slug field
$('#channel_name').keyup(function() {
slugify();
});
$('#channel_name').bind('paste', function() {
slugify();
});
});
</script>

View File

@@ -0,0 +1,308 @@
<!DOCTYPE html>
<html>
<head>
<title><%= @channel.name %></title>
<style type="text/css">
html, body { font-family: Helvetica, Arial, sans-serif; color: #333333; font-size: 16px; background-color: #bcd1e4; }
a { color: #55a; }
h2 {
margin: 10px 0 0 0;
font: 45px Tahoma, Helvetica, Arial, Sans-Serif;
text-align: left;
color: #535353;
text-shadow: 0px 2px 3px #62a09d;
}
h3 {
margin: 0 0 0 0;
font: 14px Tahoma, Helvetica, Arial, Sans-Serif;
text-align: center;
color: #656fad;
text-shadow: 0px 1px 2px #62a09d;
}
input[type='text'] { width: 180px; }
textarea { width: 178px; height: 40px; overflow: auto; }
input, #submit {
font: 14px Tahoma, Helvetica, Arial, Sans-Serif;
text-align: left;
color: #656fad;
border: 1px solid #535353;
}
#content {
margin: 0 auto;
text-align: left;
width: 980px;
}
#social {
float:left;
}
#developers { float: right; color: #555; font-size: 13px; }
#developers a { font-size: 11px; text-decoration: none; font-weight: bold; }
#footer { font-size: 80%; margin-left: 5px; }
.CB { clear: both; }
.default_text {
margin: 0 0 0 3px;
font: 15px Tahoma, Helvetica, Arial, Sans-Serif;
color: #353f7d;
}
</style>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-22749436-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
</head>
<body>
<div id="content">
<div id="social">
<script src="http://platform.twitter.com/widgets.js" type="text/javascript"></script>
<a href="http://twitter.com/share?via=socialsensors" class="twitter-share-button">Tweet</a>
<iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fwww.socialsensornetwork.com%2F<%= @channel.slug.gsub('-', '%2D') %>&amp;layout=button_count&amp;show_faces=true&amp;width=450&amp;action=like&amp;font=tahoma&amp;colorscheme=light&amp;height=21" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:450px; height:21px;" allowTransparency="true"></iframe>
</div>
<div id="developers">
Developers?
<%= link_to 'JSON', "#{@api_domain}channels/#{@channel.id}/feed.json?results=100&location=true&offset=0&round=2&status=true" %>
<%= link_to 'XML', "#{@api_domain}channels/#{@channel.id}/feed.xml?results=100&location=true&offset=0&round=2&status=true" %>
<%= link_to 'CSV', "#{@api_domain}channels/#{@channel.id}/feed.csv?results=100&location=true&offset=0&round=2&status=true" %>
</div>
<div style="clear:both;"></div>
<div style="float:left; padding-right: 40px;">
<a href="http://www.socialsensornetwork.com">
<img src='<%= "#{@api_domain}images/social_sensor_network_logo.png "%>' width='120' height='120' border='0' />
</a>
</div>
<div style="display: block; padding-top: 25px;">
<h2><%= @channel.name %></h2>
</div>
<br class="CB" />
<% if !@channel.description.blank? %>
<div class="default_text"><%= t(:channel_directions) %>: <%= @channel.description %></div>
<br />
<% end %>
<%= form_tag "#{@post_url}" do %>
<table>
<% @fields.each do |f| %>
<tr>
<td><%= @channel[f] %></td>
<td><%= text_field_tag "#{f}" %></td>
</tr>
<% end %>
<% if !@channel.status.blank? %>
<tr>
<td style="vertical-align: top;"><div style="padding-top: 5px;"><%= @channel.status %></div></td>
<td><%= text_area_tag :status %></td>
</tr>
<% end %>
<tr>
<td></td>
<td>
<%= submit_tag t(:submit), :id => 'submit' %>
<span id="msg" />
</td>
</tr>
</table>
<% end %>
<br /><br />
<div style="float: left; width: 600px;">
<iframe width="600" height="300" frameborder="0" scrolling="no" style="border: 1px solid #cccccc;" src="<%= @api_domain %>channels/<%= @channel.id %>/maps/default?width=600&height=300&results=100&round=2&status=true&dynamic=true"></iframe>
<% @fields.each do |f| %>
<br /><br />
<iframe width="600" height="300" frameborder="0" style="border: 1px solid #cccccc;" src="<%= @api_domain %>channels/<%= @channel.id %>/charts/<%= f[-1] %>?width=600&height=300&results=100&round=2&color=C46353&location=true&dynamic=true&push=false&max=20000&min=-20000"></iframe>
<% end %>
<div id="footer">
<br /><br />
&copy;2011 Social Sensor Network - Powered by <a href="https://www.thingspeak.com/">ThingSpeak</a>
</div>
</div>
<div style="float: right; width: 300px;">
<iframe width="300" height="1100" frameborder="0" scrolling="no" allowTransparency="true" style="border: 0;" src="<%= @api_domain %>channels/<%= @channel.id %>/social_feed"></iframe>
</div>
</div>
<script type="text/javascript" src="<%= @api_domain %>javascripts/rest.js"></script>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript">
// keep track of whether user entered something in the form
var thingspeak_user_input = 0;
// keep track of whether user has submitted form
var thingspeak_submitted = 0;
// get location from latitude and longitude
function reverseGeocode(latitude, longitude) {
var geocoder = new google.maps.Geocoder();
var latlng = new google.maps.LatLng(latitude,longitude);
var location = '';
geocoder.geocode({'latLng': latlng}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (results) {
$.each(results, function() {
// if city
if (this.types == "locality,political") {
location = this.address_components[0].long_name;
}
if (this.types == "administrative_area_level_1,political") {
if (location.length > 0) { location += ', '; }
location += this.address_components[0].short_name;
}
// if country
if (this.types == "country,political") {
if (location.length > 0) { location += ', '; }
location += this.address_components[0].long_name;
}
});
}
}
// submit the post
submitPost(latitude, longitude, location);
});
}
// set the user's location
function setLocation() {
// Try W3C Geolocation method (Preferred)
if(navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
reverseGeocode(position.coords.latitude, position.coords.longitude);
}, function() {
handleNoGeolocation();
});
// Try Google Gears Geolocation
} else if (google.gears) {
var geo = google.gears.factory.create('beta.geolocation');
reverseGeocode(position.latitude, position.longitude);
} else {
// Browser doesn't support Geolocation
handleNoGeolocation();
}
}
// use maxmind's geoip service
function handleNoGeolocation() {
var latitude = geoip_latitude();
var longitude = geoip_longitude();
var location = geoip_city();
if (location.length > 0 && geoip_region()) { location += ', '; }
location += geoip_region();
if (location.length > 0 && geoip_country_name()) { location += ', '; }
location += geoip_country_name();
submitPost(latitude, longitude, location);
}
// do the form post
function submitPost(latitude, longitude, location) {
if (thingspeak_submitted === 0) {
$.create(
// url to post to
'<%= @post_url %>',
// data to send
{
<% @fields.each do |f| %>
<%= f %>: Number($('#<%= f %>').val().replace(/[^0-9\.\-]+/g, "")),
<% end %>
latitude: latitude,
longitude: longitude,
location: location<%= ',' if !@channel.status.blank? %>
<% if !@channel.status.blank? %>status: $('#status').val()<% end %>
},
// if post was successful
function (response) {
var msg = (response == '0') ? '<%= t(:saved_error) %>' : '<%= t(:social_saved) %>';
$('#msg').html(msg);
clearMsg();
},
// if post failed
function (response) {
$('#msg').html('<%= t(:saved_error) %>');
clearMsg();
}
);
}
// mark the form as submitted
thingspeak_submitted = 1;
}
// clears message
function clearMsg() {
setTimeout(function() {
$('#msg').html('');
}, 3000);
}
// when document is ready
$(function() {
// event to make sure user types something into form
<% @fields.each do |f| %>
$('#<%= f %>').keyup(function() {
thingspeak_user_input = 1;
});
$('#<%= f %>').bind('paste', function() {
thingspeak_user_input = 1;
});
<% end %>
<% if !@channel.status.blank? %>
$('#status').keyup(function() {
thingspeak_user_input = 1;
});
$('#status').bind('paste', function() {
thingspeak_user_input = 1;
});
<% end %>
// event to capture update button click
$('#submit').click(function() {
// if nothing entered into form
if (thingspeak_user_input === 0) {
$('#msg').html('<%= t(:social_channel_no_value) %>');
clearMsg();
} else {
// set geolocation data (and submit the post)
setLocation();
}
return false;
});
});
</script>
<script type="text/javascript" src="http://j.maxmind.com/app/geoip.js"></script>
</body>
</html>

View File

@@ -0,0 +1,18 @@
<div class="row">
<div class="col-xs-12 col-sm-6">
<h4 class="breadcrumb"><%= t(:watched_channels) %></h4>
<div class="col-pad">
<% if @channels.empty? %>
<%= t(:watched_empty) %>
<br /><br />
<%= link_to t(:watched_find), public_channels_path %>
<% else %>
<%= render :partial => 'list' %>
<% end %>
</div>
</div>
</div>

View File

@@ -1,126 +1,196 @@
<% options = '&timescale=10' if options.blank? %>
<div>
<h3><%= title %></h3>
<table class="FL MR60">
<tr>
<td><%= t(:title) %>:</td>
<td><input type="text" class="chart_options<%= index %>" id="title<%= index %>" /></td>
</tr>
<tr>
<td><%= t(:chart_xaxis) %>:</td>
<td><input type="text" class="chart_options<%= index %>" id="xaxis<%= index %>" /></td>
</tr>
<tr>
<td><%= t(:chart_yaxis) %>:</td>
<td><input type="text" class="chart_options<%= index %>" id="yaxis<%= index %>" /></td>
</tr>
<tr>
<td><%= t(:chart_color) %>:</td>
<td><input type="text" class="chart_options<%= index %>" id="color<%= index %>" /></td>
</tr>
<tr>
<td><%= t(:chart_background_color) %>:</td>
<td><input type="text" class="chart_options<%= index %>" id="bgcolor<%= index %>" /></td>
</tr>
<tr>
<td><%= t(:chart_type) %>:</td>
<td>
<select class="chart_options<%= index %>" id="type<%= index %>">
<option>line</option>
<option>bar</option>
<option>column</option>
</select>
</td>
</tr>
<tr>
<td></td>
<td><input type="button" id="button<%= index %>" value="<%= t(:chart_update) %>" /></td>
</tr>
</table>
<div id="chartOptions<%= index %>" class="chartOptions"><%= options %></div>
<table>
<tr>
<td><%= t(:days) %>:</td>
<td><input type="text" class="chart_options<%= index %> shortfield" id="days<%= index %>" /></td>
</tr>
<tr>
<td><%= t(:timescale) %>:</td>
<td><input type="text" class="chart_options<%= index %> shortfield" id="timescale<%= index %>" /></td>
</tr>
<tr>
<td><%= t(:average) %>:</td>
<td><input type="text" class="chart_options<%= index %> shortfield" id="average<%= index %>" /></td>
</tr>
<tr>
<td><%= t(:median) %>:</td>
<td><input type="text" class="chart_options<%= index %> shortfield" id="median<%= index %>" /></td>
</tr>
<tr>
<td><%= t(:sum) %>:</td>
<td><input type="text" class="chart_options<%= index %> shortfield" id="sum<%= index %>" /></td>
</tr>
<tr>
<td><%= t(:chart_round) %>:</td>
<td><input type="text" class="chart_options<%= index %> shortfield" id="round<%= index %>" /></td>
</tr>
<tr>
<td><%= t(:width) %>:</td>
<td><input type="text" class="chart_options<%= index %> shortfield" id="width<%= index %>" /></td>
</tr>
<tr>
<td><%= t(:height) %>:</td>
<td><input type="text" class="chart_options<%= index %> shortfield" id="height<%= index %>" /></td>
</tr>
</table>
<table class="FL MR60">
<tr>
<td><%= t(:title) %>:</td>
<td><input type="text" class="chart_options<%= index %>" id="title_<%= index %>" /></td>
</tr>
<tr>
<td><%= t(:chart_xaxis) %>:</td>
<td><input type="text" class="chart_options<%= index %>" id="xaxis_<%= index %>" /></td>
</tr>
<tr>
<td><%= t(:chart_yaxis) %>:</td>
<td><input type="text" class="chart_options<%= index %>" id="yaxis_<%= index %>" /></td>
</tr>
<tr>
<td><%= t(:chart_color) %>:</td>
<td><input type="text" class="chart_options<%= index %>" id="color_<%= index %>" /></td>
</tr>
<tr>
<td><%= t(:chart_background_color) %>:</td>
<td><input type="text" class="chart_options<%= index %>" id="bgcolor_<%= index %>" /></td>
</tr>
<tr>
<td><%= t(:chart_type) %>:</td>
<td>
<select class="chart_options<%= index %>" id="type_<%= index %>">
<option>line</option>
<option>bar</option>
<option>column</option>
</select>
</td>
</tr>
<tr>
<td><%= t(:chart_is_dynamic) %>:</td>
<td>
<select class="chart_options<%= index %>" id="dynamic_<%= index %>" >
<option value=""></option>
<option value="true">True</option>
</select>
</td>
<br class="CL" />
</tr>
<iframe id="iframe<%= index %>" width="<%= width %>" height="<%= height %>" style="border: 1px solid #cccccc;" src="" default_src="<%= src %>"></iframe>
<tr>
<td><%= t(:days) %>:</td>
<td><input type="text" class="chart_options<%= index %> shortfield" id="days_<%= index %>" /></td>
</tr>
<tr>
<td><%= t(:results) %>:</td>
<td><input type="text" class="chart_options<%= index %> shortfield" id="results_<%= index %>" /></td>
</tr>
<% if displayconfig %>
<tr>
<td><%= t(:width) %>:</td>
<td><input type="text" class="chart_options<%= index %> shortfield" id="width_<%= index %>" /></td>
</tr>
<tr>
<td><%= t(:height) %>:</td>
<td><input type="text" class="chart_options<%= index %> shortfield" id="height_<%= index %>" /></td>
</tr>
<% end %>
<br /><br />
<%= t(:chart_embed_code) %>:
<br />
<textarea id="embed<%= index %>" rows="5" cols="53">&lt;iframe width="<%= width %>" height="<%= height %>" style="border: 1px solid #cccccc;" src="<%= src %>">&lt;/iframe></textarea>
</div>
</table>
<br /><br /><br />
<table>
<tr>
<td><%= t(:timescale) %>:</td>
<td>
<select class="chart_options<%= index %> mutuallyexclusive<%= index %>" id="timescale_<%= index %>" >
<option value=""></option>
<option value="10">10</option>
<option value="15">15</option>
<option value="20">20</option>
<option value="30">30</option>
<option value="60">60</option>
<option value="240">240</option>
<option value="720">720</option>
<option value="1440">1440</option>
</select>
</td>
</tr>
<tr>
<td><%= t(:average) %>:</td>
<td>
<select class="chart_options<%= index %> mutuallyexclusive<%= index %>" id="average_<%= index %>" >
<option value=""></option>
<option value="10">10</option>
<option value="15">15</option>
<option value="20">20</option>
<option value="30">30</option>
<option value="60">60</option>
<option value="240">240</option>
<option value="720">720</option>
<option value="1440">1440</option>
</select>
</td>
</tr>
<tr>
<td><%= t(:median) %>:</td>
<td>
<select class="chart_options<%= index %> mutuallyexclusive<%= index %>" id="median_<%= index %>" >
<option value=""></option>
<option value="10">10</option>
<option value="15">15</option>
<option value="20">20</option>
<option value="30">30</option>
<option value="60">60</option>
<option value="240">240</option>
<option value="720">720</option>
<option value="1440">1440</option>
</select>
</td>
</tr>
<tr>
<td><%= t(:sum) %>:</td>
<td>
<select class="chart_options<%= index %> mutuallyexclusive<%= index %>" id="sum_<%= index %>" >
<option value=""></option>
<option value="10">10</option>
<option value="15">15</option>
<option value="20">20</option>
<option value="30">30</option>
<option value="60">60</option>
<option value="240">240</option>
<option value="720">720</option>
<option value="1440">1440</option>
</select>
</td>
</tr>
<tr>
<td><%= t(:chart_round) %>:</td>
<td><input type="text" class="chart_options<%= index %> shortfield" id="round_<%= index %>" /></td>
</tr>
<tr>
<td><%= t(:chart_min) %>: </td>
<td><input type="text" class="chart_options<%= index %> shortfield" id="min_<%= index %>" /></td>
</tr>
<tr>
<td><%= t(:chart_max) %>: </td>
<td><input type="text" class="chart_options<%= index %> shortfield" id="max_<%= index %>" /></td>
</tr>
<tr>
<td><input type="button" id="button<%= index %>" value="<%= t(:chart_update) %>" /></td>
<td></td>
</tr>
</table>
<% if displayconfig %>
<%= render :partial => 'charts/display',
:locals => {
:index => index,
:width => @width,
:height => @height,
:src => src,
:options => options
}
%>
<% end %>
<script type="text/javascript">
$(document).ready(function() {
// set initial saved values
$.each(('<%= options.gsub(/'/, "%27") if options %>'.split('&amp;')), function(index, value) {
if (value.length > 0) {
$('#' + value.split('=')[0] + '<%= index %>').val(decodeURIComponent(value.split('=')[1]));
}
});
// draw initial chart with saved options
updateChart(<%= index %>, false);
});
// event to capture unfocus of textbox
$('.chart_options<%= index %>').blur(function() {
// if value exists, update the chart
if ($(this).val().length > 0) {
updateChart(<%= index %>, true);
}
});
var options = '<%= options.gsub(/'/, "%27") if options %>';
// event to capture enter key in textboxes
$('.chart_options<%= index %>').keyup(function(e) {
// if enter key
if (e.keyCode == 13) {
// if value exists, update the chart
if ($(this).val().length > 0) {
updateChart(<%= index %>, true);
}
}
});
$(document).ready(function() {
// set initial saved values
$.each((options.split('&amp;')), setupChartForm(<%= index %> ));
// draw initial chart with saved options
var width = <%= (@width) ? @width : 450 %>;
var height = <%= @height ? @height : 260 %>;
updateChart(<%= index %>, false, width, height, <%= @channel.id %>);
// event to capture update button click
$('#button<%= index %>').click(function() {
updateChart(<%= index %>, true);
});
</script>
});
// event to capture update button click
$('#button<%= index %>').click(function() {
var width = <%= (@width) ? @width : 450 %>;
var height = <%= @height ? @height : 260 %>;
updateChart(<%= index %>, true, width, height, <%= @channel.id %>);
});
$('.mutuallyexclusive<%= index %>').change(function() {
selectedValue = $(this).val();
$('.mutuallyexclusive<%= index %>').each(function () {
$(this).val("");
});
$(this).val(selectedValue);
});
</script>

View File

@@ -0,0 +1,11 @@
<br class="CL" />
<iframe id="iframe<%= index %>" width="<%= width %>" height="<%= height %>" style="border: 1px solid #cccccc;" src="" default_src="<%= src %>"></iframe>
<br /><br />
<%= t(:chart_embed_code) %>:
<br />
<textarea id="embed<%= index %>" rows="5" cols="53">&lt;iframe width="<%= width %>" height="<%= height %>" style="border: 1px solid #cccccc;" src="<%= src %>">&lt;/iframe></textarea>
<br /><br /><br />

View File

@@ -1,104 +1,66 @@
<script type="text/javascript" src="/javascripts/rest.js"></script>
<div id="maincontent">
<h2>
<%= link_to t(:channels), channels_path %> &raquo;
<%= link_to channel_path(@channel.id) do %> <%= t(:channel) %> <%= @channel.id %><% end %> &raquo;
<%= t(:charts) %>
</h2>
<% if !@channel.active? %>
<%= render :partial => 'config',
:locals => {
:displayconfig => true,
:title => t(:chart_example),
:src => "https://api.thingspeak.com/channels/3/charts/1",
:options => '&timescale=60&round=2',
:index => 0,
:width => @width,
:height => @height
}
%>
<h3><%= t(:chart_owned) %></h3>
<% end %>
<% @channel.attribute_names.each do |attr| %>
<% if attr.index('field') and @channel[attr] and !@channel[attr].empty? %>
<%= render :partial => 'config',
:locals => {
:displayconfig => true,
:title => "#{@channel.name} - #{@channel[attr]}",
:src => "#{@domain}channels/#{@channel_id}/charts/#{attr[-1]}",
:options => @channel["options#{attr[-1]}"],
:index => attr[-1],
:width => @width,
:height => @height
}
%>
<% end %>
<% end %>
</div>
<h2>
<%= link_to t(:channels), channels_path %> &raquo;
<%= link_to channel_path(@channel.id) do %> <%= t(:channel) %> <%= @channel.id %><% end %> &raquo;
<%= t(:charts) %>
</h2>
<%= render :partial => 'config',
:locals => {
:title => t(:chart_example),
:src => "https://api.thingspeak.com/channels/3/charts/1",
:options => '&timescale=60&round=2',
:index => 0,
:width => @width,
:height => @height
}
%>
<h3><%= t(:chart_owned) %></h3>
<% @channel.attribute_names.each do |attr| %>
<% if attr.index('field') and @channel[attr] and !@channel[attr].empty? %>
<%= render :partial => 'config',
:locals => {
:title => "#{@channel.name} - #{@channel[attr]}",
:src => "#{@domain}channels/#{@channel_id}/charts/#{attr[-1]}",
:options => @channel["options#{attr[-1]}"],
:index => attr[-1],
:width => @width,
:height => @height
}
%>
<% end %>
<% end %>
<div id="sidebar">
<ul>
<li>
<div class="helplink">(<a href="http://community.thingspeak.com/documentation/api/#charts"><%= t(:help_options) %></a>)</div>
<h2><%= t(:help_charts) %></h2>
<%= t(:help_charts_options) %>
<br /><br />
<%= t(:help_charts_embed) %>
<br /><br />
&bull; <a href="http://community.thingspeak.com/tutorials/wordpress/how-to-embed-a-thingspeak-chart-on-your-wordpress-blog/">WordPress Tutorial</a>
</li>
</ul>
</div>
<script type="text/javascript">
$(document).ready(function() {
// if chrome/safari error occurs, reload page
if ($('#title0').val() == '60' && $('#color0').val() == '10') {
window.location.reload();
}
});
$(document).ready(function() {
// if chrome/safari error occurs, reload page
if ($('#title0').val() == '60' && $('#color0').val() == '10') {
window.location.reload();
}
});
// update the chart with all the textbox values
function updateChart(index, postUpdate) {
// default width and height
var width = <%= @width %>;
var height = <%= @height %>;
// get old src
var src = $('#iframe' + index).attr('default_src').split('?')[0];
// if not a line chart, a timeslice should be present or set timescale=30
if ($('#type' + index).val() != 'line') {
if ($('#timescale' + index).val().length == 0 && $('#average' + index).val().length == 0 && $('#median' + index).val().length == 0 && $('#sum' + index).val().length == 0) {
$('#timescale' + index).val(30);
}
}
// add inputs to array
var inputs = [];
$('.chart_options' + index).each(function() {
var v = $(this).val();
var id = $(this).attr('id');
if (v.length > 0) { inputs.push([id.substring(0, id.length-1), v]); }
});
// create querystring
var qs = '';
while (inputs.length > 0) {
var p = inputs.pop();
if (p[0] == 'width') { width = parseInt(p[1]); }
if (p[0] == 'height') { height = parseInt(p[1]); }
// don't add type=line to querystring, it's the default value
if (!(p[0] == 'type' && p[1] == 'line')) {
qs += '&' + p[0] + '=' + encodeURIComponent(p[1]);
}
}
// if querystring exists, add it to src
if (qs.length > 0) { src += '?' + qs.substring(1); }
// save chart options to database
if (postUpdate && index > 0) {
$.update(
'/channels/<%= @channel_id %>/charts/' + index,
{ options: qs }
);
}
// set embed code
$('#embed' + index).val('<iframe width="' + width + '" height="' + height + '" style="border: 1px solid #cccccc;" src="' + src + '"></iframe>');
// set new src
$('#iframe' + index).attr('src', src);
$('#iframe' + index).attr('width', width);
$('#iframe' + index).attr('height', height);
}
</script>
</script>

View File

@@ -1,89 +1,127 @@
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="/javascripts/jquery-1.6.js"></script>
<script type="text/javascript" src="/javascripts/highcharts<%= '-android' if get_header_value('user_agent').upcase.index('ANDROID') %>.js"></script>
<script type="text/javascript">
// user's timezone offset
var myOffset = new Date().getTimezoneOffset();
// converts date format from JSON
function getChartDate(d) {
// get the data using javascript's date object (year, month, day, hour, minute, second)
// months in javascript start at 0, so remember to subtract 1 when specifying the month
// offset in minutes is converted to milliseconds and subtracted so that chart's x-axis is correct
return Date.UTC(d.substring(0,4), d.substring(5,7)-1, d.substring(8,10), d.substring(11,13), d.substring(14,16), d.substring(17,19)) - (myOffset * 60000);
}
<head>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6/jquery.min.js"></script>
<%= javascript_include_tag 'application' %>
$(document).ready(function() {
// blank array for holding chart data
var chartData = [];
// variable for the local date in milliseconds
var localDate;
// variable for the last date added to the chart
var last_date;
<script type="text/javascript">
// get the data with a webservice call
$.getJSON('<%= "#{@domain}channels/#{params[:channel_id]}/field/#{params[:id]}.json?callback=?&offset=0#{@qs}" %>', function(data) {
// if no access
if (data == '-1') {
$('#chart-container').append('<%= t(:chart_no_access) %>');
// user's timezone offset
var myOffset = new Date().getTimezoneOffset();
// converts date format from JSON
function getChartDate(d) {
// get the data using javascript's date object (year, month, day, hour, minute, second)
// months in javascript start at 0, so remember to subtract 1 when specifying the month
// offset in minutes is converted to milliseconds and subtracted so that chart's x-axis is correct
return Date.UTC(d.substring(0,4), d.substring(5,7)-1, d.substring(8,10), d.substring(11,13), d.substring(14,16), d.substring(17,19)) - (myOffset * 60000);
}
// iterate through each feed
$.each(data.feeds, function() {
var p = new Highcharts.Point();
// set the proper values
var v = this.field<%= params[:id] %>;
p.x = getChartDate(this.created_at);
p.y = parseFloat(v);
// add location if possible
if (this.location) { p.name = this.location; }
// if a numerical value exists add it
if (!isNaN(parseInt(v))<% if params[:max] %> && p.y <= <%= params[:max]%><% end %><% if params[:min] %> && p.y >= <%= params[:min]%><% end %>) { chartData.push(p); }
});
// specify the chart options
var chartOptions = {
$(document).ready(function() {
// blank array for holding chart data
var chartData = [];
// variable for the local date in milliseconds
var localDate;
// variable for the last date added to the chart
var last_date;
// get the data with a webservice call
$.getJSON('<%= "#{@domain}channels/#{params[:channel_id]}/field/#{params[:id]}.json?callback=?&offset=0#{@qs}" %>', function(data) {
// if no access
if (data == '-1') {
$('#chart-container').append('<%= t(:chart_no_access) %>');
}
// iterate through each feed
$.each(data.feeds, function() {
var p = new Highcharts.Point();
// set the proper values
var v = this.field<%= params[:id] %>;
p.x = getChartDate(this.created_at);
p.y = parseFloat(v);
// add location if possible
if (this.location) { p.name = this.location; }
// if a numerical value exists add it
if (!isNaN(parseInt(v))<% if params[:max] %> && p.y <= <%= params[:max]%><% end %><% if params[:min] %> && p.y >= <%= params[:min]%><% end %>) { chartData.push(p); }
});
// specify the chart options
var chartOptions = {
chart: {
renderTo: 'chart-container',
defaultSeriesType: '<%= params[:type] ? "#{params[:type]}" : "line" %>',
backgroundColor: '<%= params[:bgcolor] || "#ffffff" %>',
events: {
load: function() {
if ('true' === '<%= params[:dynamic] %>') {
// push data every 15 seconds
setInterval(function() {
// get the data with a webservice call
$.getJSON('<%= "#{@domain}channels/#{params[:channel_id]}/feed/last.json?callback=?&offset=0&location=true" %>', function(data) {
// if data exists
if (data && data.field<%= params[:id] %>) {
var p = new Highcharts.Point();
// set the proper values
var v = data.field<%= params[:id] %>;
p.x = getChartDate(data.created_at);
p.y = parseFloat(v);
// add location if possible
if (data.location) { p.name = data.location; }
// get the last date if possible
if (dynamicChart.series[0].data.length > 0) { last_date = dynamicChart.series[0].data[dynamicChart.series[0].data.length-1].x; }
// if a numerical value exists and it is a new date, add it
if (!isNaN(parseInt(v)) && (p.x != last_date)<% if params[:max] %> && p.y <= <%= params[:max]%><% end %><% if params[:min] %> && p.y >= <%= params[:min]%><% end %>) {
dynamicChart.series[0].addPoint(p, true, <%= (@push) ? 'true' : 'false' %>);
}
}
});
}, 15000);
renderTo: 'chart-container',
defaultSeriesType: '<%= params[:type] ? "#{params[:type]}" : "line" %>',
backgroundColor: '<%= params[:bgcolor] || "#ffffff" %>',
events: {
load: function() {
//if dynamic and no "timeslice" options are set
// GAK 02/16/2013 Let's try to add the last "average" slice if params[:average]
var url = '<%= "#{@domain}channels/#{params[:channel_id]}/feed/last.json?callback=?&offset=0&location=true#{@qs}" %>' ;
if ("<%= params[:average] %>".length > 0) {
url = '<%= "#{@domain}channels/#{params[:channel_id]}/feed/last_average.json?callback=?&offset=0&location=true&average=#{params[:average]}#{@qs}" %>' ;
}
else if ("<%= params[:median] %>".length > 0) {
url = '<%= "#{@domain}channels/#{params[:channel_id]}/feed/last_median.json?callback=?&offset=0&location=true&median=#{params[:median]}#{@qs}" %>' ;
}
else if ("<%= params[:sum] %>".length > 0) {
url = '<%= "#{@domain}channels/#{params[:channel_id]}/feed/last_sum.json?callback=?&offset=0&location=true&sum=#{params[:sum]}#{@qs}" %>' ;
}
if ('true' === '<%= params[:dynamic] %>' && (
'<%= params[:timescale] %>'.length < 1
)) {
// push data every 15 seconds
setInterval(function() {
// get the data with a webservice call if we're just getting the last channel
$.getJSON(url, function(data) {
// if data exists
if (data && data.field<%= params[:id] %>) {
var p = new Highcharts.Point();
// set the proper values
var v = data.field<%= params[:id] %>;
p.x = getChartDate(data.created_at);
p.y = parseFloat(v);
// add location if possible
if (data.location) { p.name = data.location; }
// get the last date if possible
if (dynamicChart.series[0].data.length > 0) {
last_date = dynamicChart.series[0].data[dynamicChart.series[0].data.length-1].x;
}
var shift = <%= (@push=='true') ? 'true' : 'false' %> ; //default for shift
//if push is requested in parameters
// then if results is and data.length is < results, shift = false
var results = <%= (@results) ? @results : 60 %>;
if ( results && dynamicChart.series[0].data.length+1 >= results ) {
shift = true ;
}
// if a numerical value exists and it is a new date, add it
if (!isNaN(parseInt(v)) && (p.x != last_date)<% if params[:max] %> && p.y <= <%= params[:max]%><% end %><% if params[:min] %> && p.y >= <%= params[:min]%><% end %>) {
dynamicChart.series[0].addPoint(p, true, shift);
}
else {
dynamicChart.series[0].data[dynamicChart.series[0].data.length-1].update(p);
}
}
});
}, 15000);
}
}
}
},
title: {
text: ''
text: ''
},
plotOptions: {
line: {
@@ -101,54 +139,59 @@
},
animation: true,
step: <%= params[:step] || 'false' %>,
borderWidth: 0
borderWidth: 0,
turboThreshold: 0
}
},
tooltip: {
// reformat the tooltips so that local times are displayed
formatter: function() {
var d = new Date(this.x + (myOffset*60000));
var n = (this.point.name === undefined) ? '' : '<br/>' + this.point.name;
return this.series.name + ':<b>' + this.y + '</b>' + n + '<br/>' + d.toDateString() + '<br/>' + d.toTimeString().replace(/\(.*\)/, "");
}
// reformat the tooltips so that local times are displayed
formatter: function() {
var d = new Date(this.x + (myOffset*60000));
var n = (this.point.name === undefined) ? '' : '<br/>' + this.point.name;
return this.series.name + ':<b>' + this.y + '</b>' + n + '<br/>' + d.toDateString() + '<br/>' + d.toTimeString().replace(/\(.*\)/, "");
}
},
xAxis: {
type: 'datetime',
title: {
text: ''
}
type: 'datetime',
title: {
text: 'test'
}
},
yAxis: {
title: {
text: ''
}
title: {
text: ''
}
},
exporting: {
enabled: <%= (params[:export].present? && params[:export] == 'true') ? 'true' : 'false' %>
},
legend: {
enabled: false
enabled: false
},
series: [{
name: data.channel.field<%= params[:id] %>
}]
};
name: data.channel.field<%= params[:id] %>
}]
};
// add the data to the chart
chartOptions.series[0].data = chartData;
// add the data to the chart
chartOptions.series[0].data = chartData;
// set chart labels here so that decoding occurs properly
chartOptions.title.text = <% if params[:title] %>decodeURIComponent('<%= u(params[:title]) %>')<% else %>data.channel.name<% end %>;
chartOptions.xAxis.title.text = <% if params[:xaxis] %>decodeURIComponent('<%= u(params[:xaxis]) %>')<% else %>'Date'<% end %>;
chartOptions.yAxis.title.text = <% if params[:yaxis] %>decodeURIComponent('<%= u(params[:yaxis]) %>')<% else %><%= "data.channel.field#{params[:id]}" %><% end %>;
// set chart labels here so that decoding occurs properly
chartOptions.title.text = <% if params[:title] %>decodeURIComponent('<%= u(params[:title]) %>')<% else %>data.channel.name<% end %>;
chartOptions.xAxis.title.text = <% if params[:xaxis] %>decodeURIComponent('<%= u(params[:xaxis]) %>')<% else %>'Date'<% end %>;
chartOptions.yAxis.title.text = <% if params[:yaxis] %>decodeURIComponent('<%= u(params[:yaxis]) %>')<% else %><%= "data.channel.field#{params[:id]}" %><% end %>;
// draw the chart
var dynamicChart = new Highcharts.Chart(chartOptions);
// draw the chart
var dynamicChart = new Highcharts.Chart(chartOptions);
});
});
});
</script>
</head>
<body style='background-color: <%= params[:bgcolor] ? params[:bgcolor] : 'white' %>;'>
<div id="chart-container" style="width: <%= params[:width] ? params[:width].to_i - 25 : @width.to_i - 25 %>px; height: <%= params[:height] ? params[:height].to_i - 25 : @height.to_i - 25 %>px;"></div>
</body>
</html>

View File

@@ -0,0 +1,45 @@
<div <%= "class=nestedcomment" if !comment.parent_id.nil? %>>
<div class="commentdiv">
<table class="commenttable">
<tr>
<td style="width: 50px; vertical-align: top;">
<%= gravatar_tag User.find(comment.user_id), :default => 'wavatar', :secure => true %>
</td>
<td>
<% if current_user %>
<div class="votediv">
<span id="flaglink<%= comment.id %>" class="voteicon voteflag" onclick="return commentflag(<%= comment.id %>, <%= current_user.id %>);"><span id="commentflag<%= comment.id %>"></span> <%= t(:comment_flag) %></span>
</div>
<% end %>
<span class="username"><%= link_to User.find(comment.user_id).login, list_channels_path(User.find(comment.user_id).login) %></span>
<span class="prettydate"><%= time_ago_in_words(comment.created_at) %> <%= t(:ago) %></span>
<br />
<div>
<%= auto_link_urls(comment.body) %>
</div>
<% if current_user %>
<% if comment.user == current_user %>
<%= link_to t(:delete), comment_path(comment), :method => :delete, :data => { :confirm => t(:confirm_comment_delete) } %>
<% else %>
<span class="spanlink" onclick="$('#commentreply<%= comment.id %>').toggle();"><%= t(:comment_reply) %></span>
<% end %>
<% else %>
<%= link_to t(:comment_reply), channel_comments_path(@channel) %>
<% end %>
<div id="commentreply<%= comment.id %>" style="display: none;">
<%= form_for comment, :as => :comment, :url => "/channels/#{@channel.id}/comments", :html => {:method => :post} do |f| %>
<%= f.error_messages %>
<input name='userlogin' class='userlogin' />
<%= hidden_field_tag :parent_id, comment.id %>
<%= f.text_area :body, :value => '', :class => 'commentarea' %>
<br />
<%= submit_tag %>
<% end %>
</div>
</td>
</tr>
</table>
</div>
<%= render :partial => 'comments/comment', :collection => comment.children %>
</div>

View File

@@ -0,0 +1,5 @@
<div class="response-div pull-right">
Response in:
<span class="response active response-text" data-response_type="text">TEXT</span><span class="response response-json" data-response_type="json">JSON</span><span class="response response-xml" data-response_type="xml">XML</span>
</div>

View File

@@ -0,0 +1,4 @@
<div class="row">
welcome
</div>

View File

@@ -0,0 +1,11 @@
<%= @count %> records processed
<br>
<%= @time_start %> => start controller
<br>
<%= @time_after_db %> => after database operations (<%= @time_after_db - @time_start %> seconds)
<br>
<%= @time_after_sort %> => after sorting (<%= @time_after_sort - @time_after_db %> seconds)
<br>
<%= @time_after_json %> => after to_json is processed (<%= @time_after_json - @time_after_sort %> seconds)
<br>
<%= Time.now %> => after view output (<%= Time.now - @time_after_json %> seconds)

View File

@@ -1,2 +1,2 @@
<% if @success %><%= CSV.generate_line @csv_headers %><% @feed_output.each do |feed| %><% row = [] %><% @csv_headers.each do |attr| %><% row.push(feed.send(attr)) %><% end %><%= CSV.generate_line row %><% end %><% else %>-1<% end %>
<% if @success %><%= CSV.generate_line @csv_headers %><% @feed_output.each do |feed| %><% row = [] %><% @csv_headers.each do |attr| %><% row.push(feed.send(attr)) %><% end %><%= CSV.generate_line(row).html_safe %><% end %><% else %>-1<% end %>

View File

@@ -1 +1 @@
<%= render :partial => 'index.json.erb' %>
<%= render :partial => 'feed/index.json.erb' %>

View File

@@ -0,0 +1,14 @@
<div class="nested-fields">
<div class="row">
<div class="col-sm-12">
<%= t(:thinghttp_header_name) %>
<%= header.text_field :name, :class => 'form-control input-sm' %>
<br>
<%= t(:thinghttp_header_value) %>
<%= header.text_field :value, :class => 'form-control input-sm' %>
<span class="help-block"><%= header.link_to_remove t(:thinghttp_header_remove) %></span>
</div>
</div>
</div>
<br>

View File

@@ -0,0 +1,20 @@
<div id="footer">
<div class="container">
<p class="text-muted">
<span class="pull-left">
<a href="http://www.thingspeak.com/" title="Open Source Internet of Things">ThingSpeak.com</a> |
<a href="http://community.thingspeak.com/" title="The ThingSpeak Blog covering the web of things">Blog</a> |
<a href="http://community.thingspeak.com/forum/" title="Open discussion forum for ThingSpeak">Forum</a> |
<a href="http://community.thingspeak.com/documentation/" title="ThingSpeak Documentation">Documentation</a> |
<a href="http://community.thingspeak.com/tutorials/" title="Tutorials on how to use ThingSpeak web services">Tutorials</a> |
<a href="http://feeds.feedburner.com/internetofthings" title="Internet of Things RSS Feed" target="_blank">RSS Feed</a>
</span>
<span class="hidden-phone pull-right">
&copy;<%= Time.now.year %> <a href="https://thingspeak.com" title="Open Source Internet of Things">ThingSpeak</a> - Powered by <a href="http://www.iobridge.com" target="_blank">ioBridge</a>
</span>
</p>
</div>
</div>

View File

@@ -0,0 +1,12 @@
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-20107670-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>

View File

@@ -1,12 +1,68 @@
<div id="options">
<% if current_user %>
<span class="action"> <%= link_to t(:signout), logout_path, :method => 'delete' %></span>
<% else %>
<span class="action">
<%= link_to t(:signup), new_user_path %>
</span>
<span class="action"> <%= link_to t(:signin), login_path %></span>
<% end %>
<div class="navbar navbar-default navbar-fixed-top" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<%= link_to root_path do %>
<%= image_tag 'thingspeak_logo.png', :size => '190x50', :style => 'padding: 0 8px;' %>
<% end %>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<% if current_user %>
<li class="<%= "active " if @menu == 'channels' %>dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><%=t(:channels)%> <b class="caret"></b></a>
<ul class="dropdown-menu">
<li><%= link_to t(:channels_my), channels_path %></li>
<li><%= link_to t(:watched_channels), watched_channels_path %></li>
<li><%= link_to t(:channels_public), public_channels_path %></li>
</ul>
</li>
<li <%= "class=active" if @menu == 'plugins' %>><%= link_to t(:plugins), plugins_path %></li>
<li class="<%= "active " if @menu == 'account' %>dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><%=t(:account)%> <b class="caret"></b></a>
<ul class="dropdown-menu">
<li><%= link_to t(:myaccount), account_path %></li>
<li><%= link_to t(:account_edit), edit_account_path %></li>
<li><%= link_to t(:public_profile), user_profile_path(current_user.login) %></li>
<li><%= link_to t(:profile_edit), edit_profile_path %></li>
</ul>
</li>
<% else %>
<li <%= "class=active" if @menu == 'channels' %>><%= link_to t(:channels), public_channels_path %></li>
<li <%= "class=active" if @menu == 'features' %>><%= link_to t(:features), features_pages_path %></li>
<% end %>
</ul>
<ul class="nav navbar-nav navbar-right">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><%=t(:support)%> <b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="http://community.thingspeak.com/documentation/"><%= t(:documentation) %></a></li>
<li><a href="http://community.thingspeak.com/tutorials/"><%= t(:tutorials) %></a></li>
<li><a href="http://community.thingspeak.com/forum/"><%= t(:forum) %></a></li>
</ul>
</li>
<li><a href="http://community.thingspeak.com/"><%= t(:blog)%></a></li>
<% if current_user %>
<li><%= link_to t(:signout), logout_path %></li>
<% else %>
<li><%= link_to t(:signin), login_path %></li>
<li><%= link_to t(:signup), new_account_path %></li>
<% end %>
</ul>
</div><!--/.nav-collapse -->
</div>
</div>
<div id="logo"><%= link_to t(:application_name), root_path %></div>

View File

@@ -1,16 +1,34 @@
<!DOCTYPE html>
<html>
<head>
<title><%= @title.nil? ? (@menu.nil? ? t(:application_name) : @menu.capitalize + ' - ' + t(:application_name)) : @title + ' - ' + t(:application_name) %></title>
<%= stylesheet_link_tag "application" %>
<%= javascript_include_tag "application" %>
<%= csrf_meta_tag %>
</head>
<body>
<div id="wrapper">
<div id="header"><div class="fixedwidth"><%= render 'layouts/header' %></div></div>
<div id="menuwrap" class="fixedwidth"><%= render 'layouts/menu' %></div>
<div id="content" class="fixedwidth"><%= yield %></div>
</div>
</body>
<head>
<title><%= @title.nil? ? (@menu.nil? ? 'ThingSpeak' : @menu.capitalize + ' - ThingSpeak') : @title + ' - ThingSpeak' %></title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<%= stylesheet_link_tag 'application' %>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type='text/javascript' src="//netdna.bootstrapcdn.com/bootstrap/3.1.0/js/bootstrap.min.js"></script>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.9.1/jquery-ui.min.js"></script>
<%= javascript_include_tag 'application' %>
<%= csrf_meta_tag %>
<% if Rails.env == 'production' %>
<%= render 'layouts/ga' %>
<% end %>
<%= yield :head %>
</head>
<body>
<div id="wrap">
<%= render 'layouts/header' %>
<div class="container">
<%= yield %>
</div>
</div>
<%= render 'layouts/footer' %>
</body>
</html>

View File

@@ -5,13 +5,13 @@
</head>
<body>
<p>
<%= t(:password_reset_message1) %>
<br />
<%= t(:password_reset_message2) %>
<br />
<%= t(:password_reset_message3) %>
<br /><br />
<a href="<%= @webpage %>"><%= @webpage %></a>
<%= t(:password_reset_message1) %>
<br />
<%= t(:password_reset_message2) %>
<br />
<%= t(:password_reset_message3) %>
<br /><br />
<a href="<%= @webpage %>"><%= @webpage %></a>
</p>
</body>
</html>

View File

@@ -0,0 +1,44 @@
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="http<%= 's' if @ssl %>://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
<script type="text/javascript" src="<%= @map_domain %>/maps/api/js?sensor=false"></script>
<script type="text/javascript">
// when document is ready
$(function() {
// google maps options
var myOptions = {
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
var bounds = new google.maps.LatLngBounds();
var lat, lng, latlng, marker, title;
// get the data with a webservice call
$.getJSON('<%= "#{@domain}channels/#{params[:channel_id]}/feed.json?callback=?&location=true&results=0#{@qs}" %>', function(data) {
// if no access
if (data == '-1') {
$('#chart-container').append('<%= t(:chart_no_access) %>');
}
lat = parseFloat(data.channel.latitude);
lng = parseFloat(data.channel.longitude);
latlng = new google.maps.LatLng(lat, lng);
marker = new google.maps.Marker({
position: latlng,
title: data.channel.name
});
marker.setMap(map);
map.setCenter(latlng);
map.setZoom(4);
});
});
</script>
</head>
<body style="padding: 0; margin: 0;">
<div id="map_canvas" style="width: <%= params[:width] ? params[:width].to_i : @width.to_i %>px; height: <%= params[:height] ? params[:height].to_i : @height.to_i %>px;"></div>
</body>
</html>

View File

@@ -0,0 +1,119 @@
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="<%= @map_domain %>/maps/api/js?sensor=false"></script>
<script type="text/javascript">
// when document is ready
$(function() {
// google maps options
var myOptions = {
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
var bounds = new google.maps.LatLngBounds();
var lat, lng, latlng, marker, title, field1, field2, field3, field4, field5, field6, field7, field8;
// get the data with a webservice call
$.getJSON('<%= "#{@domain}channels/#{params[:channel_id]}/feed.json?callback=?&location=true&offset=0#{@qs}" %>', function(data) {
// if no access
if (data == '-1') {
$('#chart-container').append('<%= t(:chart_no_access) %>');
}
// set channel field names
if (data.channel.field1) { field1 = data.channel.field1; }
if (data.channel.field2) { field2 = data.channel.field2; }
if (data.channel.field3) { field3 = data.channel.field3; }
if (data.channel.field4) { field4 = data.channel.field4; }
if (data.channel.field5) { field5 = data.channel.field5; }
if (data.channel.field6) { field6 = data.channel.field6; }
if (data.channel.field7) { field7 = data.channel.field7; }
if (data.channel.field8) { field8 = data.channel.field8; }
// iterate through each feed
$.each(data.feeds, function() {
lat = parseFloat(this.latitude);
lng = parseFloat(this.longitude);
// if there is data to add
if (lat && lng) {
latlng = new google.maps.LatLng(lat, lng);
title = '';
if (this.field1) { title += field1 + ': ' + this.field1 + '\n'; }
if (this.field2) { title += field2 + ': ' + this.field2 + '\n'; }
if (this.field3) { title += field3 + ': ' + this.field3 + '\n'; }
if (this.field4) { title += field4 + ': ' + this.field4 + '\n'; }
if (this.field5) { title += field5 + ': ' + this.field5 + '\n'; }
if (this.field6) { title += field6 + ': ' + this.field6 + '\n'; }
if (this.field7) { title += field7 + ': ' + this.field7 + '\n'; }
if (this.field8) { title += field8 + ': ' + this.field8 + '\n'; }
if (this.status) { title += this.status; }
marker = new google.maps.Marker({
position: latlng,
title: title
});
marker.setMap(map);
bounds.extend(latlng);
}
});
// if no latlng set, center map
if (latlng === undefined) {
latlng = new google.maps.LatLng(38.5111, -96.8005);
map.setCenter(latlng);
map.setZoom(3);
// if only one data point, set zoom level
} else if (data.feeds.length == 1) {
map.setCenter(latlng);
map.setZoom(8);
} else {
// extend the bounds
map.fitBounds(bounds);
}
// push data every 15 seconds
setInterval(function() {
// get the data with a webservice call
$.getJSON('<%= "#{@domain}channels/#{params[:channel_id]}/feed/last.json?callback=?&location=true&offset=0#{@qs}" %>', function(data) {
// if there is data to add
if (data) {
lat = parseFloat(data.latitude);
lng = parseFloat(data.longitude);
if (lat && lng) {
latlng = new google.maps.LatLng(lat, lng);
title = '';
if (data.field1) { title += field1 + ': ' + data.field1 + '\n'; }
if (data.field2) { title += field2 + ': ' + data.field2 + '\n'; }
if (data.field3) { title += field3 + ': ' + data.field3 + '\n'; }
if (data.field4) { title += field4 + ': ' + data.field4 + '\n'; }
if (data.field5) { title += field5 + ': ' + data.field5 + '\n'; }
if (data.field6) { title += field6 + ': ' + data.field6 + '\n'; }
if (data.field7) { title += field7 + ': ' + data.field7 + '\n'; }
if (data.field8) { title += field8 + ': ' + data.field8 + '\n'; }
if (data.status) { title += data.status; }
marker = new google.maps.Marker({
position: latlng,
title: title
});
marker.setMap(map);
}
}
});
}, 15000);
});
});
</script>
</head>
<body style="padding: 0; margin: 0;">
<div id="map_canvas" style="width: <%= params[:width] ? params[:width].to_i : @width.to_i %>px; height: <%= params[:height] ? params[:height].to_i : @height.to_i %>px;"></div>
</body>
</html>

View File

@@ -0,0 +1 @@
<h3><%= t(:about) %></h3>

View File

@@ -0,0 +1,116 @@
<h2>export test</h2>
<br>
<script type="text/javascript">
// users timezone offset
var myOffset = new Date().getTimezoneOffset();
// converts date format from JSON
function getChartDate(d) {
// get the data using javascript's date object (year, month, day, hour, minute, second)
// months in javascript start at 0, so remember to subtract 1 when specifying the month
// offset in minutes is converted to milliseconds and subtracted so that chart's x-axis is correct
return Date.UTC(d.substring(0,4), d.substring(5,7)-1, d.substring(8,10), d.substring(11,13), d.substring(14,16), d.substring(17,19)) - (myOffset * 60000);
}
$(document).ready(function() {
// blank array for holding chart data
var chartData = [];
// variable for the date string
var d;
// variable for the data point
var p;
// variable for the local date in milliseconds
var localDate;
// get the data with a webservice call
$.getJSON('https://api.thingspeak.com/channels/9/field/1.json?callback=?&amp;results=15&amp;offset=0', function(data) {
// if no access
if (data == '-1') {
$('#chart-container').append('This channel is not public. To embed charts, the channel must be public or a read key must be specified.');
}
// iterate through each feed
$.each(data.feeds, function() {
p = this.field1;
// if a numerical value exists add it
if (!isNaN(parseInt(p))) {
chartData.push([getChartDate(this.created_at), parseFloat(p)]);
}
});
// specify the chart options
var chartOptions = {
chart: {
renderTo: 'chart-container',
defaultSeriesType: 'line',
backgroundColor: '#ffffff'
},
title: {
text: ''
},
plotOptions: {
line: {
color: '#d62020'
},
bar: {
color: '#d62020'
},
column: {
color: '#d62020'
},
series: {
marker: {
radius: 3
},
animation: true
}
},
tooltip: {
// reformat the tooltips so that local times are displayed
formatter: function() {
var d = new Date(this.x + (myOffset*60000));
return this.series.name + ':<b>' + this.y + '</b><br/>' + d.toDateString() + '<br/>' + d.toTimeString().replace(/\(.*\)/, "");
}
},
xAxis: {
type: 'datetime',
title: {
text: ''
}
},
yAxis: {
title: {
text: ''
}
},
legend: {
enabled: false
},
series: [{
name: data.channel.field1
}]
};
// add the data to the chart
chartOptions.series[0].data = chartData;
// set chart labels here so that decoding occurs properly
chartOptions.title.text = 'Dynamic Light Levels';
chartOptions.xAxis.title.text = 'Time';
chartOptions.yAxis.title.text = data.channel.field1;
// draw the chart
var dynamicChart = new Highcharts.Chart(chartOptions);
});
});
</script>
<br />
<div id="chart-container" style="width: 500px; height: 260px; padding-left: 20px; float: left;"></div>

View File

@@ -0,0 +1,22 @@
<h3><%= t(:features) %></h3>
<div class="section_header_reverse">All-purpose Data Storage and Retrieval</div>
<p>You use ThingSpeak to <em>Send</em> and <em>Receive</em> &quot;data&quot; via simple HTTP requests, much like going to a web page and filling out a form. Data can be from anything -- <em>Blood Sugar Levels</em> measured by a glucose meter, <em>Server Usage and Uptime</em> reported by servers, or <em>Location Info</em> from a mobile phone. Once the data is in ThingSpeak, you can build applications that retrieve the data, use the data for process decision making, and reporting.</p>
<p>Data is stored in a ThingSpeak Channel. Each channel allows you to store up to 8 fields of data up to 255 alphanumeric characters; 4 dedicated location fields for <em>Location Description</em>, <em>Latitude</em>, <em>Longitude</em>, and <em>Elevation</em>; Status Update to augment the data; and a Time Date Stamp to time code each piece of incoming data.</p>
<div class="section_header_reverse">Data Importing</div>
<p>Do you already have a bunch of data collected from data acquisition devices, server logs, or sensors? Then you can use the ThingSpeak Importer to bring in your existing data and leverage the ThingSpeak API and Charts to share with and connect to applications instantly.</p>
<div class="section_header_reverse">Dynamic Charting</div>
<p>When you need to visualize your data, ThingSpeak has dynamic charts and an API to make customizations. The charts are perfect for displaying sensor data over time and finding some meaning behind the data. ThingSpeak Charts work on all desktop browsers, iPhones, and Android devices by using JavaScript instead of Flash. The chart types supported are <em>Line</em>, <em>Bar</em>, <em>Column</em>, and <em>Step</em>. You can set colors, sizing, and labels to allow the charts to fit perfectly into your web page or web application.</p>
<div class="section_header_reverse">Data Processing</div>
<p>When pulling data out of ThingSpeak, you can process the data to get it ready for your application. You can also filter the data by setting minimum and maximum value thresholds. Processing options include time scaling, summing, averaging, and median.</p>
<div class="section_header_reverse">Integration with Twitter</div>
<p>Often enough you will find times where you want to share significant data across social networks like Twitter. You can have your garage door Tweet,
&quot;You left your garage door open&quot; or have your house, say &quot;Today's Power Use was 6150 watts.&quot; The ThingSpeak API has Twitter baked in, so you can send status updates to Twitter along with storing your data in a ThingSpeak Channel at the same time. </p>
<div class="section_header_reverse">Fully Localized</div>
<p>ThingSpeak supports over 40 time zones and time offsets for locations that support Day Light Savings. When charts and data are presented to users, we format times and dates using the viewer's time zone. The user interface for ThingSpeak currently supports English and Brazilian Portuguese languages automatically, but the localization <a href="https://github.com/iobridge/thingspeak/blob/master/config/locales/en.yml" title="GitHub Localization file for ThingSpeak.">file</a> is available for translation into other languages. ThingSpeak numerical data supports commas used as decimals, for example, it's getting 38,2 degrees in here, for our friends in Brazil and many other <a href="http://en.wikipedia.org/wiki/Decimal_mark#Countries_using_Arabic_numerals_with_decimal_comma" title="Countries using Arabic numerals with decimal comma" target="_blank">countries</a>.</p>
<div class="section_header_reverse">Privacy Options for Open Data</div>
<p>We respect your privacy. You can choose to make your data public or private. Over 95% of ThingSpeak Channels are private meaning that the data is not publicly accessible without API keys and user authentication. You can control who has access to your data and build applications that are open to those that you choose. We don't sell your data to third-parties. You can even run ThingSpeak on a private network at your facility or home and build tightly secured applications for your organization's needs.</p>
<div class="section_header_reverse">Open Source for Open Source</div>
<p>The ThingSpeak API is available on <a href="https://github.com/iobridge/thingspeak" title="GitHub repo for ThingSpeak source code" target="_blank">GitHub</a> for download and installation on your own servers. You can also take the source code and make changes and contribute new features. ThingSpeak is a modern Ruby on Rails 3.0 application and includes everything to get started including, a full web application, <em>User Management</em>, <em>API Key Management</em>, <em>Channel Management</em>, and <em>Charting</em>. The license for ThingSpeak is under GPLv3 for open source use and can be licensed from <a href="http://www.iobridge.com" title="ioBridge" target="_blank">ioBridge</a> for closed source applications. ThingSpeak has been installed on over 500 servers and licenced commercially since its release on GitHub in March 2011. <a href="mailto:oem@iobridge.com" title="Contact ioBridge for licensing options for ThingSpeak">Contact ioBridge</a> for licensing options for commercial use<a href="mailto:oem@iobridge.com" title="Contact for ThingSpeak Licensing"></a>. ThingSpeak will be powering many new services and products coming to market in 2012.</p>
<p align="center"><a href="https://github.com/iobridge/thingspeak" target="_blank"><%= image_tag 'GitHub_ThingSpeak_API.jpg', :size => '300x288' %></a></p>

View File

@@ -0,0 +1,7 @@
<table border="1">
<% for header in request.env.select {|k,v| k.match("^HTTP.*")} %>
<tr>
<td><%=header[0].split('_',2)[1]%></td><td><%=header[1]%></td>
</tr>
<% end %>
</table>

View File

@@ -1,5 +1,230 @@
<% if current_user %>
<%= t(:homepage_logged_in) %>
<% else %>
<%= t(:homepage) %>
<% end %>
<script type="text/javascript">
// users timezone offset
var myOffset = new Date().getTimezoneOffset();
// converts date format from JSON
function getChartDate(d) {
// get the data using javascript's date object (year, month, day, hour, minute, second)
// months in javascript start at 0, so remember to subtract 1 when specifying the month
// offset in minutes is converted to milliseconds and subtracted so that chart's x-axis is correct
return Date.UTC(d.substring(0,4), d.substring(5,7)-1, d.substring(8,10), d.substring(11,13), d.substring(14,16), d.substring(17,19)) - (myOffset * 60000);
}
$(document).ready(function() {
// blank array for holding chart data
var chartData = [];
// variable for the date string
var d;
// variable for the data point
var p;
// variable for the local date in milliseconds
var localDate;
// get the data with a webservice call
$.getJSON('https://api.thingspeak.com/channels/9/field/1.json?callback=?&amp;results=15&amp;offset=0', function(data) {
// if no access
if (data == '-1') {
$('#chart-container').append('This channel is not public. To embed charts, the channel must be public or a read key must be specified.');
}
// iterate through each feed
$.each(data.feeds, function() {
p = this.field1;
// if a numerical value exists add it
if (!isNaN(parseInt(p))) {
chartData.push([getChartDate(this.created_at), parseFloat(p)]);
}
});
// specify the chart options
var chartOptions = {
chart: {
renderTo: 'chart-container',
defaultSeriesType: 'line',
backgroundColor: '#fff',
events: {
load: function() {
// push data every 15 seconds
setInterval(function() {
// get the data with a webservice call
$.getJSON('https://api.thingspeak.com/channels/9/feed/last.json?callback=?&amp;offset=0', function(data) {
p = data.field1;
d = getChartDate(data.created_at);
last_date = dynamicChart.series[0].data[dynamicChart.series[0].data.length-1].x;
// if a numerical value exists and it is a new date, add it
if (!isNaN(parseInt(p)) && (d != last_date)) {
dynamicChart.series[0].addPoint([d, parseFloat(p)], true, true);
}
});
}, 15000);
}
}
},
title: {
text: ''
},
plotOptions: {
line: {
color: '#d62020'
},
bar: {
color: '#d62020'
},
column: {
color: '#d62020'
},
series: {
marker: {
radius: 3
},
animation: true
}
},
tooltip: {
// reformat the tooltips so that local times are displayed
formatter: function() {
var d = new Date(this.x + (myOffset*60000));
return this.series.name + ':<b>' + this.y + '</b><br/>' + d.toDateString() + '<br/>' + d.toTimeString().replace(/\(.*\)/, "");
}
},
xAxis: {
type: 'datetime',
title: {
text: ''
}
},
yAxis: {
title: {
text: ''
}
},
exporting: {
enabled: false
},
legend: {
enabled: false
},
series: [{
name: data.channel.field1
}]
};
// add the data to the chart
chartOptions.series[0].data = chartData;
// set chart labels here so that decoding occurs properly
chartOptions.title.text = 'Dynamic Light Levels';
chartOptions.xAxis.title.text = 'Time';
chartOptions.yAxis.title.text = data.channel.field1;
// draw the chart
var dynamicChart = new Highcharts.Chart(chartOptions);
});
});
</script>
<div class="row">
<div class="text-center">
<%= image_tag 'front.png', :size => '854x144' %>
</div>
</div>
<br><br><br>
<div class="row">
<div class="col-sm-6">
<div id="chart-container" class="center-block" style="width: 500px; height: 260px; padding-left: 20px;"></div>
</div>
<div class="col-sm-6">
<div style="margin-top: 55px;" class="text-center"><a href="http://community.thingspeak.com/tutorials/netduino/create-your-own-web-of-things-using-the-netduino-plus-and-thingspeak/"><%= image_tag 'my_house_status_update.png' %></a></div>
</div>
</div>
<br><br><br>
<div class="row">
<div class="col-sm-4">
<h4 class="breadcrumb">Features</h4>
<p>
<ul>
<li>Open Source API</li>
<li>Real-time data collection</li>
<li>Data processing</li>
<li>Data visualizations</li>
<li>Location-awareness</li>
<li>Status context</li>
<li>Application infrastructure</li>
<li>Twitter proxy</li>
<li>Apps</li>
<li>Plugins</li>
<li><%= link_to '... more', features_pages_path %></li>
</ul>
</p>
</div>
<div class="col-sm-4">
<h4 class="breadcrumb">Applications</h4>
<p>
<ul>
<li>Sensor monitoring</li>
<li>Energy monitoring</li>
<li>Connecting devices and systems</li>
<li>Geo location tracking</li>
<li>Interfacing with social networks</li>
<li>RFID transactions</li>
</ul>
</p>
<h4 class="breadcrumb">Who Uses ThingSpeak</h4>
<p>
<ul>
<li>Application developers</li>
<li>Product integrators</li>
<li>Web designers</li>
</ul>
</p>
</div>
<div class="col-sm-4">
<h4 class="breadcrumb">Get Started</h4>
<div class="col-pad">
If you are ready to get started, <span id="feature_signup"> <%= link_to t(:signup), new_account_path %></span> for a free user account.
</div>
<h4 class="breadcrumb">Connect</h4>
<p>
<ul>
<li><a href="http://www.twitter.com/thingspeak" title="Follow ThingSpeak on Twitter">Twitter</a></li>
<li><a href="https://github.com/iobridge/ThingSpeak" title="Open Source Internet of Things Project on GitHub">GitHub</a></li>
<li><a href="http://community.thingspeak.com" title="Join the ThingSpeak Community">ThingSpeak Community</a></li>
<li><a href="http://community.thingspeak.com/documentation" title="ThingSpeak API and Apps Documentation">Documentation</a> and <a href="http://community.thingspeak.com/tutorials" title="ThingSpeak Tutorials">Tutorials</a></li>
<li><a href="mailto:support@thingspeak.com" title="Contact ThingSpeak">Questions</a></li>
</ul>
</p>
</div>
</div>
<br><br><br>
<div class="row">
<div class="col-sm-offset-2 col-sm-8 col-xs-12">
<div class="center-block" style="max-width: 600px;">
<h4><a href="http://community.thingspeak.com/" title="ThingSpeak Community, Blog, and Forum">latest news<a> <a href="http://feeds.feedburner.com/internetofthings/" title="ThingSpeak RSS Feed"><%= image_tag 'icon_rss.gif' %></a></h4>
<br>
<% cache("blog-posts-on-homepage", :expires_in => 10.minutes) do %>
<%= raw blog_entries %>
<% end %>
</div>
</div>
</div>

View File

@@ -0,0 +1,145 @@
<!DOCTYPE html>
<html>
<head>
<title>The Social Sensor Network</title>
<style type="text/css">
body {
background-color: #bcd1e4;
}
a {
text-decoration: none;
color: #ffffff;
font: 18px Arial, Sans-Serif;
font-weight: 700;
text-shadow: 0px 1px 2px #535353;
}
h2 {
margin: 10px 0 0 0;
font: 45px Tahoma, Helvetica, Arial, Sans-Serif;
text-align: center;
color: #535353;
text-shadow: 0px 2px 3px #62a09d;
}
h3 {
margin: 0 0 0 0;
font: 14px Tahoma, Helvetica, Arial, Sans-Serif;
text-align: center;
color: #656fad;
text-shadow: 0px 1px 2px #62a09d;
}
input, #submit {
font: 14px Tahoma, Helvetica, Arial, Sans-Serif;
text-align: center;
color: #656fad;
border: 1px solid #535353;
}
#content {
margin: 0 auto;
text-align: center;
width: 800px;
}
#social {
float:left;
}
#demo {
margin: 5px;
border: 1px solid #535353;
padding: 15px;
background: #c46353;
}
#demo_text {
display: block;
margin: 0 0 10px 0;
font: 25px Tahoma, Helvetica, Arial, Sans-Serif;
text-align: center;
color: #535353;
text-shadow: 0px 2px 3px #62a09d;
}
</style>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-22749436-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
</head>
<body>
<div id="content">
<div id="social">
<script src="http://platform.twitter.com/widgets.js" type="text/javascript"></script>
<a href="http://twitter.com/share?via=socialsensors" class="twitter-share-button">Tweet</a>
<iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fwww.socialsensornetwork.com%2F&amp;layout=button_count&amp;show_faces=true&amp;width=450&amp;action=like&amp;font=tahoma&amp;colorscheme=light&amp;height=21" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:450px; height:21px;" allowTransparency="true"></iframe>
</div>
<div style="clear:both;"></div>
<% link_to 'irs-refund/' do %>
<img src='<%= "#{@api_domain}images/social_sensor_network_main.png "%>' width='600' height='415' border='0' />
<% end %>
<h2>the social sensor network is forming.</h2>
<h3>We have one thing in common. At almost all times we are connected to the web.<br />
The Social Sensor Network allows everyone to report and share data in an open and meaningful way.</h3>
<br />
<form method=post action="https://app.icontact.com/icp/signup.php" name="icpsignup" id="icpsignup2312" accept-charset="UTF-8" onsubmit="return verifyRequired2312();" >
<input type=hidden name=redirect value="http://www.socialsensornetwork.com?invite=success" />
<input type=hidden name=errorredirect value="http://www.socialsensornetwork.com" />
<input type=text name="fields_email">
<input type=hidden name="listid" value="26352">
<input type=hidden name="specialid:26352" value="SP8K">
<input type=hidden name=clientid value="874748">
<input type=hidden name=formid value="2312">
<input type=hidden name=reallistid value="1">
<input type=hidden name=doubleopt value="0">
<input type="submit" name="submit" id="submit" value="Sign up for Invite">
</form>
<script type="text/javascript">
// alert user for successful form submission
if (window.location.toString().indexOf('invite=success') > 0) {
alert('Your email address has been submitted, thanks!');
window.location = window.location.toString().replace('?invite=success', '');
}
var icpForm2312 = document.getElementById('icpsignup2312');
if (document.location.protocol === "https:")
icpForm2312.action = "https://app.icontact.com/icp/signup.php";
function verifyRequired2312() {
if (icpForm2312["fields_email"].value == "") {
icpForm2312["fields_email"].focus();
alert("The Email field is required.");
return false;
}
return true;
}
</script>
<br />
<br />
<span id="demo_text">demo channels</span>
<br />
<span id="demo"><a href="http://www.socialsensornetwork.com/irs-refund">IRS Refunds</a></span>
<span id="demo"><a href="http://www.socialsensornetwork.com/online-poker">Frozen Online Poker Money</a></span>
</div>
</body>
</html>

View File

@@ -0,0 +1,19 @@
<h2>Pipes</h2>
<%= link_to 'New Pipe', new_pipe_path %>
<br /><br />
<table class="nicetable">
<tr class="header"><td>ID</td><td>Name</td><td>Slug</td><td>URL</td><td>Date</td></tr>
<% @pipes.each do |m| %>
<tr<%= cycle('', raw(' class="stripe"')) %>>
<td><%= link_to m.id, channel_path(m.id) %></td>
<td><%= link_to m.name, channel_path(m.id) %></td>
<td><%= link_to m.slug, channel_path(m.id) %></td>
<td><%= m.url %></td>
<td><%= raw(m.created_at.strftime("%m/%d/%Y&nbsp;%I:%M%p")) %></td>
</tr>
<% end %>
</table>
<br />
<%= will_paginate @pipes %>

View File

@@ -0,0 +1,30 @@
<h2>Add New Pipe</h2>
<%= form_for @pipe, :url => pipes_path do |f| %>
<table class="table_no_header">
<tr>
<td class="left">Name</td>
<td><%= f.text_field :name %></td>
</tr>
<tr>
<td class="left">Slug</td>
<td><%= f.text_field :slug %></td>
</tr>
<tr>
<td class="left">URL</td>
<td><%= f.text_field :url %></td>
</tr>
<tr>
<td class="left">Parse String</td>
<td><%= f.text_field :parse %></td>
</tr>
<tr>
<td class="left">Minutes to Cache</td>
<td><%= f.text_field :cache %></td>
</tr>
<tr>
<td class="left"></td>
<td><%= f.submit 'Create Pipe' %></td>
</tr>
</table>
<% end %>

View File

@@ -0,0 +1,8 @@
<% if @plugin_windows.blank? %>
<h4>All plugins are attached to a window.</h4>
<% else %>
<h4>Click a rectangle to view that Plugin in a dashboard window.</h4>
<% @plugin_windows.each do |plugin| %>
<div id="plugin-<%=plugin.id%>" class="ioplugin ui-widget-content addportlet"><%= plugin.name %></div>
<% end %>
<% end %>

View File

@@ -0,0 +1,3 @@
<style type="text/css">
body { background-color: #ddd; }
</style>

View File

@@ -0,0 +1,13 @@
<html>
<head>
%%PLUGIN_CSS%%
%%PLUGIN_JAVASCRIPT%%
</head>
<body>
my plugin
</body>
</html>

View File

@@ -0,0 +1,3 @@
<script type="text/javascript">
document.write('<div>javascript active</div>');
</script>

View File

@@ -0,0 +1,109 @@
<div class="col-sm-8 col-xs-8">
<ol class="breadcrumb">
<li><%= link_to t(:plugins), plugins_path %></li>
<li><%= link_to plugin_path(@plugin.id) do %> <%= t(:plugin) %> <%= @plugin.id %><% end %></li>
<li class="active"><%= t(:edit) %></li>
</ol>
<%= form_for @plugin, :html => {:method => 'put', :class => 'form-horizontal'} do |c| %>
<%= error_messages_for 'plugin', :header_message => t(:try_again), :message => t(:plugin_error) %>
<input name='userlogin' class='userlogin' />
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10 col-xs-offset-3 col-xs-6">
<div class="checkbox">
<label>
<%= c.check_box :private_flag %>
<%= t(:plugin_private_flag) %>
</label>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 col-xs-3 control-label"><%= t(:plugin_name) %></label>
<div class="col-sm-10 col-xs-6"><%= c.text_field :name, :class => 'form-control' %></div>
</div>
<div class="form-group">
<label class="col-sm-2 col-xs-3 control-label"><%= t(:plugin_html) %></label>
<div class="col-sm-10 col-xs-6"><%= c.text_area :html, :class => 'form-control', :rows => 14 %></div>
</div>
<div class="form-group">
<label class="col-sm-2 col-xs-3 control-label"><%= t(:plugin_css) %></label>
<div class="col-sm-10 col-xs-6"><%= c.text_area :css, :class => 'form-control', :rows => 14 %></div>
</div>
<div class="form-group">
<label class="col-sm-2 col-xs-3 control-label"><%= t(:plugin_js) %></label>
<div class="col-sm-10 col-xs-6"><%= c.text_area :js, :class => 'form-control', :rows => 14 %></div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label"></label>
<div class="col-sm-10"><p class="form-control-static"><%= c.submit t(:plugin_edit), :class => 'btn btn-primary' %></p></div>
</div>
<% end %>
<br /><br />
<h3><%= t(:plugin_delete_message) %></h3>
<%= button_to t(:plugin_delete), plugin_path(@plugin.id), :method => 'delete', :data => { :confirm => t(:confirm_plugin_delete) }, :class => 'btn btn-danger' %>
</div>
<script type="text/javascript">
// when document is ready
$(function() {
// allow tabs to work in textareas
$("textarea").tabby();
// clears status message
function clearStatus() {
setTimeout(function() {
$('#status').html('');
}, 2500);
}
// event to capture update button click
$('#plugin_submit').click(
function() {
$.update(
// url to post to
'/plugins/ajax_update/<%= @plugin.id %>',
// data to send
{
plugin:
{
name: $('#plugin_name').val(),
private_flag: $('#plugin_private_flag').is(':checked'),
html: $('#plugin_html').val(),
css: $('#plugin_css').val(),
js: $('#plugin_js').val()
}
},
// if post was successful
function (response) {
var status = (response == '1') ? '<%= t(:saved) %>' : '<%= t(:saved_error) %>';
$('#status').html(status);
clearStatus();
},
// if post failed
function (response) {
$('#status').html('<%= t(:saved_error) %>');
clearStatus();
}
);
return false;
});
});
</script>

View File

@@ -0,0 +1,43 @@
<div class="row">
<div class="col-xs-12 col-sm-6">
<h4 class='breadcrumb'><%= t(:plugins) %></h4>
<% if @plugins.length > 0 %>
<table class="table table-striped table-bordered">
<tr>
<th><%= t(:plugin_name) %></th>
<th><%= t(:action) %></th>
</tr>
<% @plugins.each do |p| %>
<tr>
<td><%= link_to p.name, plugin_path(p.id) %></td>
<td><%= link_to t(:edit), edit_plugin_path(p.id) %></td>
</tr>
<% end %>
</table>
<br /><br />
<% end %>
<%= form_for :plugin do |p| %>
<input name='userlogin' class='userlogin' />
<%= p.submit t(:plugin_create), :class => 'btn btn-primary' %>
<% end %>
</div>
<div id="sidebar" class="col-xs-12 col-sm-6">
<h4 class="breadcrumb"><%= t(:help) %></h4>
<div class="col-pad">
<%= t(:help_plugins) %>
<ul>
<li><a href="http://community.thingspeak.com/tutorials/google/display-a-google-gauge-visualization-using-thingspeak-plugins/" target="_blank">Google Gauge Tutorial</a></li>
</ul>
</div>
</div>
</div>

View File

@@ -0,0 +1 @@
<%= raw(@output) %>

View File

@@ -0,0 +1,46 @@
<html>
<head>
<%= stylesheet_link_tag 'application' %>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6/jquery.min.js"></script>
<%= javascript_include_tag 'application' %>
</head>
<body>
<div class="recent_status">
<% @statuses.each do |r| %>
<div ><span class="status_messages" id="<%= r.entry_id %>"><%= r.status %><br /><abbr class="timeago" title="<%= r.created_at %>"><%= r.created_at %></abbr></div>
<br />
<% end %>
<div>
<script>
$(function () {
$(".timeago").timeago();
var refreshInterval = setInterval(refreshStatus, 1 * 60 * 1000);
});
function refreshStatus() {
$.getJSON("/channels/<%= @channel_id %>/status/recent", function(data){
//look for most recent status and only append if the new status has a greater entry_id
var firstId = $(".status_messages").first().attr('id');
for(var i in data) {
if (data[i].entry_id > firstId) {
$(".recent_status").prepend("<div><span class=\"status_messages\" id=\"" +
data[i].entry_id + "\">"+
data[i].status +
"</span><br /><abbr class=\"timeago\" title=\"" +
data[i].created_at + "\">" +
data[i].created_at + "</abbr></div></br>");
}
}
$(".timeago").timeago();
});
}
</script>
</body>
</html>

View File

@@ -0,0 +1,24 @@
<%= form_for :tag, :url => tags_path do |t| %>
<input name='userlogin' class='userlogin' />
<table>
<tr>
<td><%= t(:tags_search) %>:</td>
<td><%= t.text_field :name %><%= t.submit t(:submit) %></td>
</tr>
</table>
<br />
<% if @tag_name %>
<% if @results %>
<% @results.each do |channel| %>
<%= link_to channel.name, channel_path(channel.id) %>
<br />
<% end %>
<% else %>
<%= t(:search_empty) %>
<% end %>
<% end %>
<% end %>

View File

@@ -1,13 +1,57 @@
<div class="FL"><%= render :partial => 'users/login' %></div>
<div class="DT PL30">
<% if @failed %>
<h2 class="rubyred"><%= t(:signin_failure) %></h2>
<%= t(:signin_try_again) %>
<% else %>
<div class="large">
<%= t(:signin_please) %>
</div>
<br />
<%= @mail_message %>
<% end %>
<div class="col-sm-6 col-xs-12">
<h4 class="breadcrumb">
<% if @failed %>
<%= t(:signin_failure) %>
<% else %>
<%= t(:signin_please) %>
<% end %>
</h4>
<% if @failed %><%= t(:signin_try_again) %><br><br><% end %>
<% if @mail_message.present? %><%= @mail_message %><br><br><% end %>
<%= form_for @user_session, :url => user_session_path, :html => { :id => 'loginform', :class => 'form-horizontal' } do |f| %>
<input name='userlogin' class='userlogin' />
<%= f.hidden_field :remember_me, :value => false %>
<div class="form-group">
<label class="col-sm-4 col-xs-3 control-label"><%= t(:userid) %></label>
<div class="col-sm-8 col-xs-9"><%= f.text_field :login, :value => cookies['user_id'], :class => 'form-control' %></div>
</div>
<div class="form-group">
<label class="col-sm-4 col-xs-3 control-label"><%= t(:password) %></label>
<div class="col-sm-8 col-xs-9">
<%= f.password_field :password, :class => 'form-control' %>
<%= link_to t(:forgot), forgot_password_path, :id => 'forgot_password' %>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-4 col-sm-8 col-xs-offset-3 col-xs-9">
<div class="checkbox">
<label>
<%= f.check_box :remember_id, :checked => true %>
<%= t(:remember_me) %>
</label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-4 col-sm-8 col-xs-offset-3 col-xs-9"><p class="form-control-static"><%= f.submit t(:signin), :class => 'btn btn-primary' %></p></div>
</div>
<% end %>
</div>
<script type="text/javascript">
var login = document.getElementById('user_session_login');
if (login.value.length == 0)
login.focus();
else
document.getElementById('user_session_password').focus();
</script>

View File

@@ -1,62 +1,54 @@
<h2>
<%= link_to t(:myaccount), account_path %> &raquo;
<%= t(:account_edit) %>
</h2>
<div class="col-sm-8 col-xs-7">
<%= form_for @user, :url => account_path do |f| %>
<%= error_messages_for 'user', :header_message => t(:try_again), :message => t(:account_error_edit) %>
<ol class="breadcrumb">
<li><%= link_to t(:myaccount), account_path %></li>
<li class="active"><%= t(:account_edit) %></li>
</ol>
<%= form_for @user, :url => account_path, :html => {:class => 'form-horizontal'} do |f| %>
<%= error_messages_for 'user', :header_message => t(:try_again), :message => t(:account_error_edit) %>
<input name='userlogin' class='userlogin' />
<table class="table_no_header">
<tr>
<td class="left">
<div class="vcenter"><%= f.label :login, t(:userid) %></div>
</td>
<td class="right">
<%= f.text_field :login %>
</td>
</tr>
<tr>
<td class="left">
<div class="vcenter"><%= f.label t(:email) %></div>
</td>
<td class="right">
<%= f.text_field :email %>
</td>
</tr>
<tr>
<td class="left"><%= t(:time_zone) %></td>
<td><%= time_zone_select 'user', 'time_zone', nil, :default => 'Eastern Time (US & Canada)' %></td>
<div class="form-group">
<label class="col-sm-4 col-xs-4 control-label"><%= t(:userid) %></label>
<div class="col-sm-8 col-xs-8"><%= f.text_field :login, :class => 'form-control' %></div>
</div>
</tr>
<tr>
<td class="left">
<div class="vcenter"><%= f.label :password, raw(t(:password_change_raw)) %></div>
</td>
<td class="right">
<%= f.password_field :password %>
</td>
<tr>
<td class="left">
<%= f.label :password_confirmation, raw(t(:password_confirmation_raw)) %>
</td>
<td class="right">
<%= f.password_field :password_confirmation %>
<div class="form-group">
<label class="col-sm-4 col-xs-4 control-label"><%= t(:email) %></label>
<div class="col-sm-8 col-xs-8"><%= f.text_field :email, :class => 'form-control' %></div>
</div>
<div class="form-group">
<label class="col-sm-4 col-xs-4 control-label"><%= t(:time_zone) %></label>
<div class="col-sm-8 col-xs-8">
<p class="form-control-static">
<%= time_zone_select 'user', 'time_zone', nil, {:default => 'Eastern Time (US & Canada)'}, {:class => 'form-control'} %>
</p>
</div>
</div>
<div class="form-group">
<label class="col-sm-4 col-xs-4 control-label"><%= t(:password_change) %></label>
<div class="col-sm-8 col-xs-8"><%= f.password_field :password, :class => 'form-control' %></div>
</div>
<div class="form-group">
<label class="col-sm-4 col-xs-4 control-label"><%= t(:password_confirmation) %></label>
<div class="col-sm-8 col-xs-8"><%= f.password_field :password_confirmation, :class => 'form-control' %></div>
</div>
<div class="form-group">
<label class="col-sm-4 col-xs-4 control-label"><%= t(:password_current) %></label>
<div class="col-sm-8 col-xs-8"><%= f.password_field :password_current, :class => 'form-control' %></div>
</div>
<div class="form-group">
<div class="col-sm-offset-4 col-sm-8 col-xs-offset-4 col-xs-8"><p class="form-control-static"><%= f.submit t(:account_update), :class => 'btn btn-primary' %></p></div>
</div>
<% end %>
</div>
</td>
</tr>
<tr>
<td class="left">
<%= raw(t(:password_current_raw)) %>
</td>
<td class="right">
<input name="password_current" type="password" />
</td>
</tr>
<tr>
<td class="left"></td>
<td class="right"><%= f.submit t(:account_update) %></td>
</tr>
</table>
<% end %>

View File

@@ -0,0 +1,43 @@
<div class="col-sm-8 col-xs-7">
<ol class="breadcrumb">
<li><%= link_to t(:myaccount), account_path %></li>
<li class="active"><%= t(:profile_edit) %></li>
</ol>
<%= form_for @user, :url => update_profile_path, :html => {:class => 'form-horizontal'} do |f| %>
<input name='userlogin' class='userlogin' />
<div class="form-group">
<div class="col-sm-offset-4 col-sm-8 col-xs-offset-3 col-xs-6">
<div class="checkbox">
<label>
<%= f.check_box :public_flag %>
<%= t(:public) %>
</label>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-4 col-xs-3 control-label"><%= t(:profile_website) %></label>
<div class="col-sm-8 col-xs-6"><%= f.text_field :website, :class => 'form-control' %></div>
</div>
<div class="form-group">
<label class="col-sm-4 col-xs-3 control-label"><%= t(:profile_bio) %></label>
<div class="col-sm-8 col-xs-6"><%= f.text_area :bio, :class => 'form-control', :rows => 4 %></div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label"></label>
<div class="col-sm-8"><p class="form-control-static"><%= f.submit t(:profile_update), :class => 'btn btn-primary' %></p></div>
</div>
<% end %>
</div>

View File

@@ -1,11 +1,30 @@
<h2><%= t(:password_forgot) %></h2>
<%= t(:password_forgot_message) %>
<br /><br />
<%= form_for :user, :url => resetpassword_path do |f| %>
<input name='userlogin' class='userlogin' />
<%= f.text_field :login %>
<%= f.submit t(:submit) %>
<% end %>
<div class="col-sm-7 col-xs-12">
<h4 class="breadcrumb"><%= t(:password_forgot) %></h4>
<%= t(:password_forgot_message) %>
<br><br>
<%= form_for @user, :url => { :controller => 'mailer', :action => 'resetpassword' }, :html => {:class => 'form-horizontal' } do |f| %>
<input name='userlogin' class='userlogin' />
<div class="form-group">
<label class="col-sm-3 col-xs-3 control-label"><%= t(:email) %></label>
<div class="col-sm-9 col-xs-9"><%= f.text_field :login, :class => 'form-control' %></div>
</div>
<div class="form-group">
<div class="col-sm-offset-3 col-sm-9 col-xs-offset-3 col-xs-9"><p class="form-control-static"><%= f.submit t(:submit), :class => 'btn btn-primary' %></p></div>
</div>
<% end %>
</div>
<script type="text/javascript">
document.getElementById('user_login').focus();
</script>
document.getElementById('user_login').focus();
</script>

View File

@@ -0,0 +1,19 @@
<h3><%= t(:user_public_channels) %> <%= @user.login %></h3>
<% if @channels.present? && @channels.count > 0 %>
<table class="table table-striped table-bordered">
<tr><th><%= t(:channel_name) %></th><th><%= t(:channel_description) %></th><th><%= t(:tags) %></th></tr>
<% @channels.each do |m| %>
<tr<%= cycle('', raw(' class="stripe"')) %>>
<td><%= link_to m.name, channel_path(m.id) %></td>
<td><%= m.description %></td>
<td><%= m.list_tags %></td>
</tr>
<% end %>
</table>
<br />
<%= will_paginate @channels %>
<% else %>
<%= t(:user_no_public_channels) %>
<% end %>

View File

@@ -1,51 +1,49 @@
<h2><%= t(:signup_header) %></h2>
<br />
<%= form_for @user, :url => account_path do |f| %>
<%= error_messages_for 'user', :header_message => t(:try_again), :message => t(:account_error) %>
<input name='userlogin' class='userlogin' />
<table class="bigtable">
<tr>
<td class="left">
<div class="vcenter"><%= f.label :login, t(:userid) %></div>
</td>
<td class="right">
<%= f.text_field :login %>
</td>
</tr>
<tr>
<td class="left">
<div class="vcenter"><%= f.label t(:email) %></div>
</td>
<td class="right">
<%= f.text_field :email %>
</td>
</tr>
<tr>
<td><%= t(:time_zone) %></td>
<td><%= time_zone_select 'user', 'time_zone', nil, :default => 'Eastern Time (US & Canada)' %></td>
</tr>
<tr>
<td class="left">
<div class="vcenter"><%= f.label t(:password) %></div>
</td>
<td class="right">
<%= f.password_field :password %>
</td>
<tr>
<td class="left">
<%= f.label :password_confirmation, raw(t(:password_confirmation_raw)) %>
</td>
<td class="right">
<%= f.password_field :password_confirmation %>
</td>
</tr>
<tr>
<td class="left"></td>
<td class="right"><%= f.submit t(:create_account) %></td>
</tr>
</table>
<% end %>
<div class="col-sm-8 col-xs-7">
<h4 class="breadcrumb"><%= t(:signup_header) %></h4>
<%= form_for @user, :url => account_path, :html => {:class => 'form-horizontal'} do |f| %>
<%= error_messages_for 'user', :header_message => t(:try_again), :message => t(:account_error) %>
<input name='userlogin' class='userlogin' />
<div class="form-group">
<label class="col-sm-4 col-xs-3 control-label"><%= t(:userid) %></label>
<div class="col-sm-8 col-xs-6"><%= f.text_field :login, :class => 'form-control' %></div>
</div>
<div class="form-group">
<label class="col-sm-4 col-xs-3 control-label"><%= t(:email) %></label>
<div class="col-sm-8 col-xs-6"><%= f.text_field :email, :class => 'form-control' %></div>
</div>
<div class="form-group">
<label class="col-sm-4 col-xs-3 control-label"><%= t(:time_zone) %></label>
<div class="col-sm-8 col-xs-8">
<p class="form-control-static">
<%= time_zone_select 'user', 'time_zone', nil, {:default => 'Eastern Time (US & Canada)'}, {:class => 'form-control'} %>
</p>
</div>
</div>
<div class="form-group">
<label class="col-sm-4 col-xs-3 control-label"><%= t(:password) %></label>
<div class="col-sm-8 col-xs-6"><%= f.password_field :password, :class => 'form-control' %></div>
</div>
<div class="form-group">
<label class="col-sm-4 col-xs-3 control-label"><%= t(:password_confirmation) %></label>
<div class="col-sm-8 col-xs-6"><%= f.password_field :password_confirmation, :class => 'form-control' %></div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label"></label>
<div class="col-sm-8"><p class="form-control-static"><%= f.submit t(:create_account), :id => "user_submit", :class => 'btn btn-primary' %></p></div>
</div>
<% end %>
</div>
<script type="text/javascript">
document.getElementById('user_login').focus();
</script>
document.getElementById('user_login').focus();
</script>

View File

@@ -0,0 +1,19 @@
<% if @user.public_flag == true %>
<div class="FR">
<br /><br />
<%= gravatar_tag @user, :default => 'wavatar', :secure => true %>
</div>
<h2><%= t(:profile_for) %> <%= @user.login %></h2>
<%= link_to t(:channels_public_view), list_channels_path(@user.login) %>
<br /><br />
<%= t(:member_since) %> <%= @user.created_at.strftime('%B %-d, %Y') %>
<br /><br />
<%= t(:profile_website) %>: <%= link_to @user.website, @user.website %>
<br /><br />
<%= t(:profile_bio) %>: <%= @user.bio %>
<% else %>
<%= t(:profile_not_public) %>
<% end %>

View File

@@ -1,34 +1,35 @@
<% if @valid_link %>
<h2><%= t(:password_new) %></h2>
<%= form_for @user, :url => change_password_user_path(@user) do |f| %>
<%= error_messages_for 'user', :header_message => t(:try_again), :message => t(:password_new_error) %>
<input name='userlogin' class='userlogin' />
<table class="bigtable">
<tr>
<td class="left">
<div class="vcenter"><%= f.label :password %></div>
</td>
<td class="right">
<%= f.password_field :password %>
<br />
<%= t(:password_new_choose) %>
</td>
<tr>
<td class="left">
<%= f.label :password_confirmation, raw(t(:password_confirmation_raw)) %>
</td>
<td class="right">
<%= f.password_field :password_confirmation %>
<br />
<%= t(:password_new_confirmation) %>
</td>
</tr>
<tr>
<td class="left"></td>
<td class="right"><%= f.submit t(:submit) %></td>
</tr>
</table>
<% end %>
<h2><%= t(:password_new) %></h2>
<%= form_for @user, :url => { :controller => 'users', :action => 'change_password', :id => @user.id } do |f| %>
<%= error_messages_for 'user', :header_message => t(:try_again), :message => t(:password_new_error) %>
<input name='userlogin' class='userlogin' />
<table class="bigtable">
<tr>
<td class="left">
<div class="vcenter"><%= f.label :password %></div>
</td>
<td class="right">
<%= f.password_field :password %>
<br />
<%= t(:password_new_choose) %>
</td>
<tr>
<td class="left">
<%= f.label :password_confirmation, raw(t(:password_confirmation)) %>
</td>
<td class="right">
<%= f.password_field :password_confirmation %>
<br />
<%= t(:password_new_confirmation) %>
</td>
</tr>
<tr>
<td class="left"></td>
<td class="right"><%= f.submit t(:submit) %></td>
</tr>
</table>
<% end %>
<% else %>
<%= t(:password_link_expired) %>
<% end %>
<%= t(:password_link_expired) %>
<% end %>

View File

@@ -1,20 +1,56 @@
<h2><%= t(:account_info) %></h2>
<div class="col-sm-5 col-xs-12">
<%= link_to t(:account_edit), edit_account_path %>
<h4 class="breadcrumb"><%= t(:myaccount) %></h4>
<br /><br />
<div class="col-pad">
<%= link_to t(:account_edit), edit_account_path, :class => 'btn btn-primary btn-sm' %>
<br /><br />
<table class="table">
<tr>
<td><%= t(:userid) %></td>
<td><%= @user.login %></td>
</tr>
<tr>
<td><%= t(:email) %></td>
<td><%= @user.email %></td>
</tr>
<tr>
<td><%= t(:time_zone) %></td>
<td><%= @user.time_zone %></td>
</tr>
<tr>
<td><%= t(:api_key) %></td>
<td>
<%= @user.api_key %><br>
<%= button_to t(:api_key_new), user_new_api_key_path, :data => { :confirm => t(:confirm_new_user_api_key) }, :class => 'btn btn-primary btn-sm' %>
</td>
</tr>
</table>
</div>
<br /><br />
<h4 class="breadcrumb"><%= t(:public_profile) %></h4>
<div class="col-pad">
<%= link_to t(:profile_edit), edit_profile_path, :class => 'btn btn-primary btn-sm' %>
<br /><br />
<%= link_to t(:profile_view), user_profile_path(@user.login) %>
<br /><br />
<% if @user.public_flag %>
<table class="table">
<tr>
<td><%= t(:profile_website) %></td>
<td><%= @user.website %></td>
</tr>
<tr>
<td><%= t(:profile_bio) %></td>
<td><%= @user.bio %></td>
</tr>
</table>
<% else %>
<%= t(:profile_not_public_me) %>
<% end %>
</div>
</div>
<table class="table_no_header">
<tr>
<td class="left"><%= t(:userid) %></td>
<td><%= @user.login %></td>
</tr>
<tr>
<td class="left"><%= t(:email) %></td>
<td><%= @user.email %></td>
</tr>
<tr>
<td class="left"><%= t(:time_zone) %></td>
<td><%= @user.time_zone %></td>
</tr>
</table>

View File

@@ -0,0 +1,104 @@
<script>
$(function() {
$("#tabs").tabs({
ajaxOptions: {
error: function( xhr, status, index, anchor ) {
$( anchor.hash ).html(
"Couldn't load this tab. We'll try to fix this as soon as possible. " +
"If this wouldn't be a demo." );
}
}
});
//Need to turn this into an ID so it doesn't run on more than one object
$(".ioplugin").off();
$("body").on("click", ".ioplugin", function() {
var plugins = $(".plugin");
var addPlugin = $(this);
var ids = addPlugin.attr('id').split("-");
var channelId = <%= params[:channel_id] %>;
var windowId =ids[1];
//Need to add data to this request to identify it as a plugin request
var data = {plugin:true, visibility_flag:"<%= @visibility %>"};
$.update("/channels/" + channelId + "/windows/"+ windowId + "/display" , data,
function(response) {
var window = response.plugin_window;
var colId = window.col;
var colName = (window.private_flag == true) ? "private" : "public";
addPlugin.hide();
for (var type in response) {
var wtype = type;
}
var portlet = addWindow(colName,colId, window.id, wtype, window.title, window.html );
//for each portlet
portlet.each ( decoratePortlet("true") );
portlet.find( ".ui-toggle" ).click( uiToggleClick );
portlet.find( ".ui-view" ).click( uiViewClick (channelId) );
portlet.find( ".ui-edit" ).click( uiEditClick (channelId) );
portlet.find( ".ui-close" ).click( uiCloseClick (channelId) );
}) ;
});
$(".ioportlet").click(
function() {
var addPortlet = $(this);
var ids = addPortlet.attr('id').split("-");
var channelId = ids[1];
var windowId =ids[2];
$.update("/channels/" + channelId +"/windows/"+ windowId + "/display" ,
function(response) {
var window = (response.portlet_window) ? response.portlet_window : response.chart_window;
var colId = window.col;
var colName = (window.private_flag == true) ? "private" : "public";
addPortlet.hide();
for (var type in response) {
var wtype = type;
}
var portlet = addWindow(colName,colId, window.id, wtype, window.title, window.html );
//for each portlet
portlet.each ( decoratePortlet("true") );
portlet.find( ".ui-toggle" ).click( uiToggleClick );
portlet.find( ".ui-view" ).click( uiViewClick (channelId) );
portlet.find( ".ui-edit" ).click( uiEditClick (channelId) );
portlet.find( ".ui-close" ).click( uiCloseClick (channelId) );
}) ;
});
});
</script>
<div id="tabs">
<ul>
<li><a href="#tabs-1">Windows</a></li>
<% if @visibility =="private" %>
<li><a href="/plugins/private_plugins?channel_id=<%= params[:channel_id] %>">Plugins</a></li>
<% else %>
<li><a href="/plugins/public_plugins?channel_id=<%= params[:channel_id] %>">Plugins</a></li>
<% end %>
</ul>
<div id="tabs-1">
<% if @windows.blank? %>
<h4><%= t("portlets_all_displayed") %></h4>
<% else %>
<h4><%= t("portlets_add") %></h4>
<% @windows.each do |window| %>
<div id="addPortlet-<%= window.channel_id %>-<%=window.id%>" class="ioportlet ui-widget-content addportlet" >
<%= window.title %>
</div>
<% end %>
<% end %>
</div>
</div>