diff --git a/app/controllers/channels_controller.rb b/app/controllers/channels_controller.rb index 902c416..ae62a20 100644 --- a/app/controllers/channels_controller.rb +++ b/app/controllers/channels_controller.rb @@ -39,6 +39,9 @@ class ChannelsController < ApplicationController # list public channels def public + # error if page 0 + respond_with_error(:error_resource_not_found) and return if params[:page] == '0' + @domain = domain # default blank response @channels = Channel.where(:id => 0).paginate :page => params[:page] @@ -63,7 +66,6 @@ class ChannelsController < ApplicationController # normal channel list else @header = t(:featured_channels) - respond_with_error(:error_resource_not_found) and return if params[:page] == '0' @channels = Channel.public_viewable.active.order('ranking desc, updated_at DESC').paginate :page => params[:page] end diff --git a/app/controllers/plugins_controller.rb b/app/controllers/plugins_controller.rb index 9951f76..f28e45f 100644 --- a/app/controllers/plugins_controller.rb +++ b/app/controllers/plugins_controller.rb @@ -1,5 +1,6 @@ class PluginsController < ApplicationController - before_filter :require_user, :except => [:show_public, :show] + before_filter :authenticate_via_api_key!, :only => [:index] + before_filter :require_user, :except => [:show_public, :show, :public] before_filter :set_plugins_menu before_filter :check_permission, :only => ['edit', 'update', 'ajax_update', 'destroy'] @@ -11,8 +12,31 @@ class PluginsController < ApplicationController def new; ; end def edit; ; end + # get list of public plugins + def public + # error if page 0 + respond_with_error(:error_resource_not_found) and return if params[:page] == '0' + + # default blank response + @plugins = Plugin.where(:id => 0).paginate :page => params[:page] + + # get plugins + @plugins = Plugin.where("public_flag = true").order('updated_at DESC').paginate :page => params[:page] + + respond_to do |format| + format.html + format.json { render :json => Plugin.paginated_hash(@plugins).to_json } + format.xml { render :xml => Plugin.paginated_hash(@plugins).to_xml(:root => 'response') } + end + end + def index @plugins = current_user.plugins + respond_to do |format| + format.html + format.json { render :json => @plugins.to_json(Plugin.public_options) } + format.xml { render :xml => @plugins.to_xml(Plugin.public_options) } + end end def public_plugins diff --git a/app/models/plugin.rb b/app/models/plugin.rb index 88da6a2..5447b6b 100644 --- a/app/models/plugin.rb +++ b/app/models/plugin.rb @@ -18,6 +18,44 @@ class Plugin < ActiveRecord::Base has_many :windows, -> { where window_type: 'plugin' }, :foreign_key => :content_id, :source => :window before_destroy { |record| record.windows.each { |window| window.delete } } + # pagination variables + cattr_reader :per_page + @@per_page = 15 + + # paginated hash for json and xml output + # plugins input must be paginated + def self.paginated_hash(plugins) + { + pagination: + { + current_page: plugins.current_page, + per_page: plugins.per_page, + total_entries: plugins.total_entries, + }, + plugins: plugins.as_json(Plugin.public_options) + } + end + + # for to_json or to_xml, return only the public attributes + def self.public_options + { + :root => false, + :only => [:id, :name, :created_at, :public_flag], + :methods => [:username, :url] + } + end + + # login name of the user who created the plugin + def username; self.user.try(:login); end + + # url for the plugin + def url + domain = 'https://thingspeak.com' + domain = 'http://staging.thingspeak.com' if Rails.env.staging? + domain = 'http://127.0.0.1:3000' if Rails.env.development? + return "#{domain}/plugins/#{self.id}" + end + def destroy_window window_id = Window.where(content_id: self.id, window_type: 'plugin').first.id Window.delete(window_id) diff --git a/app/views/channels/_list.html.erb b/app/views/channels/_list.html.erb index 3b3338d..f749def 100644 --- a/app/views/channels/_list.html.erb +++ b/app/views/channels/_list.html.erb @@ -4,10 +4,10 @@
- <%= link_to channel_path(channel.id), :id => "showsite_#{channel.id}", class: 'link-no-hover' do %> + <%= link_to channel_path(channel.id), class: 'link-no-hover' do %> <% end %> - <%= link_to channel_path(channel.id), :id => "showsite_#{channel.id}" do %> + <%= link_to channel_path(channel.id) do %> <%= truncate(channel.name, length: 23) %> <% end %>
diff --git a/app/views/docs/_sidebar.html.erb b/app/views/docs/_sidebar.html.erb index ddcf96f..20354e4 100644 --- a/app/views/docs/_sidebar.html.erb +++ b/app/views/docs/_sidebar.html.erb @@ -46,7 +46,14 @@
  • Users
  • <% end %> -
  • Plugins
  • + <% if params[:action] == 'plugins' %> +
  • Plugins
  • +
  • Example
  • +
  • List Plugins
  • + <% else %> +
  • Plugins
  • + <% end %> +
  • Tutorials
  • Error Codes
  • diff --git a/app/views/docs/plugins.html.erb b/app/views/docs/plugins.html.erb index 44c876b..f52c0ed 100644 --- a/app/views/docs/plugins.html.erb +++ b/app/views/docs/plugins.html.erb @@ -12,14 +12,16 @@


    -

    Example Plugin

    +

    Example Plugin

    Display a Google Gauge Visualization using ThingSpeak Plugins [Source Code]

    +

    -











    +
    + <%= render 'docs/plugins/index' %>
    diff --git a/app/views/docs/plugins/_index.html.erb b/app/views/docs/plugins/_index.html.erb new file mode 100644 index 0000000..9a29fbd --- /dev/null +++ b/app/views/docs/plugins/_index.html.erb @@ -0,0 +1,182 @@ +
    + <%= render 'response' %> +

    List Public Plugins

    +
    + +
    +To view a list of public plugins, send an HTTP GET to +
    +<%= @ssl_api_domain %>plugins/public.json.xml . + +

    +Valid parameters: + + +
    +Example GET: + +
    GET <%= @ssl_api_domain %>plugins/public.json.xml
    + +
    + +
    + The response will be a webpage with a list of public plugins. +
    + +
    + The response will be a JSON object of public plugins, for example: + +
    +{
    +  "pagination":
    +  {
    +    "current_page": 1,
    +    "per_page":15,
    +    "total_entries": 2
    +  },
    +  "plugins":
    +  [
    +    {
    +      "id": 8,
    +      "name": "google gauge",
    +      "created_at": "2014-01-05T16:35:26-05:00",
    +      "public_flag": true,
    +      "username": "hans",
    +      "url": "https://thingspeak.com/plugins/8"
    +    },
    +    {
    +      "id": 13,
    +      "name": "Plugin 13",
    +      "created_at": "2014-10-09T14:45:31-04:00",
    +      "public_flag": true,
    +      "username": "hans",
    +      "url": "https://thingspeak.com/plugins/13"
    +    }
    +  ]
    +}
    +
    + +
    + +
    + The response will be an XML object of public plugins, for example: + +
    +<response>
    +  <pagination>
    +    <current-page type="WillPaginate::PageNumber">1</current-page>
    +    <per-page type="integer">15</per-page>
    +    <total-entries type="integer">2</total-entries>
    +  </pagination>
    +  <plugins type="array">
    +    <plugin>
    +      <id type="integer">8</id>
    +      <name>google gauge</name>
    +      <created-at type="dateTime">2014-01-05T16:35:26-05:00</created-at>
    +      <public-flag type="boolean">true</public-flag>
    +      <username>hans</username>
    +      <url>https://thingspeak.com/plugins/8</url>
    +    </plugin>
    +    <plugin>
    +      <id type="integer">13</id>
    +      <name>Plugin 13</name>
    +      <created-at type="dateTime">2014-10-09T14:45:31-04:00</created-at>
    +      <public-flag type="boolean">true</public-flag>
    +      <username>hans</username>
    +      <url>https://thingspeak.com/plugins/13</url>
    +    </plugin>
    +  </plugins>
    +</response>
    +
    + +
    + +
    + <%= render 'response' %> +

    List My Plugins

    +
    + +
    +To view a list of your plugins, send an HTTP GET to +
    +<%= @ssl_api_domain %>plugins.json.xml . + +

    +Valid parameters: + + + +
    +Example GET: + +
    GET <%= @ssl_api_domain %>plugins.json.xml
    + +
    + +
    + The response will be a webpage with a list of your plugins. +
    + +
    + The response will be a JSON object of your plugins, for example: + +
    +[
    +    {
    +      "id": 8,
    +      "name": "google gauge",
    +      "created_at": "2014-01-05T16:35:26-05:00",
    +      "public_flag": false,
    +      "username": "hans",
    +      "url": "https://thingspeak.com/plugins/8"
    +    },
    +    {
    +      "id": 13,
    +      "name": "Plugin 13",
    +      "created_at": "2014-10-09T14:45:31-04:00",
    +      "public_flag": false,
    +      "username": "hans",
    +      "url": "https://thingspeak.com/plugins/13"
    +    }
    +  ]
    +
    + +
    + +
    + The response will be an XML object of your plugins, for example: + +
    +<response>
    +  <pagination>
    +    <current-page type="WillPaginate::PageNumber">1</current-page>
    +    <per-page type="integer">15</per-page>
    +    <total-entries type="integer">2</total-entries>
    +  </pagination>
    +  <plugins type="array">
    +    <plugin>
    +      <id type="integer">8</id>
    +      <name>google gauge</name>
    +      <created-at type="dateTime">2014-01-05T16:35:26-05:00</created-at>
    +      <public-flag type="boolean">false</public-flag>
    +      <username>hans</username>
    +      <url>https://thingspeak.com/plugins/8</url>
    +    </plugin>
    +    <plugin>
    +      <id type="integer">13</id>
    +      <name>Plugin 13</name>
    +      <created-at type="dateTime">2014-10-09T14:45:31-04:00</created-at>
    +      <public-flag type="boolean">false</public-flag>
    +      <username>hans</username>
    +      <url>https://thingspeak.com/plugins/13</url>
    +    </plugin>
    +  </plugins>
    +</response>
    +
    + +
    + diff --git a/app/views/plugins/public.html.erb b/app/views/plugins/public.html.erb new file mode 100644 index 0000000..1eec268 --- /dev/null +++ b/app/views/plugins/public.html.erb @@ -0,0 +1,34 @@ +
    + +
    + + + <% @plugins.each do |plugin| %> +
    + +
    +
    + <%= link_to plugin_path(plugin.id), class: 'link-no-hover' do %> + + <% end %> + <%= link_to plugin_path(plugin.id) do %> + <%= truncate(plugin.name, length: 23) %> + <% end %> +
    + +
    +

    by <%= link_to(plugin.user.login, user_profile_path(plugin.user.login)) if plugin.user.present? %>

    +
    +
    + +
    + <% end %> + +
    +
    + <%= will_paginate @plugins, renderer: BootstrapPagination::Rails %> +
    +
    + +
    + diff --git a/config/routes.rb b/config/routes.rb index 768b15d..9cb1490 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -127,6 +127,7 @@ Thingspeak::Application.routes.draw do collection do get 'private_plugins' get 'public_plugins' + get 'public' end end diff --git a/spec/controllers/plugins_controller_spec.rb b/spec/controllers/plugins_controller_spec.rb index 9b4c8b2..b993af9 100644 --- a/spec/controllers/plugins_controller_spec.rb +++ b/spec/controllers/plugins_controller_spec.rb @@ -3,18 +3,54 @@ require 'spec_helper' describe PluginsController do before :each do @user = FactoryGirl.create(:user) - controller.stub(:current_user).and_return(@user) - controller.stub(:current_user_session).and_return(true) - @plugin = FactoryGirl.create(:plugin, :user => @user) @channel = FactoryGirl.create(:channel, :user => @user) end describe "GET 'private_plugins' for plugin" do + before :each do + controller.stub(:current_user).and_return(@user) + controller.stub(:current_user_session).and_return(true) + end + it "should return plugin windows" do get 'private_plugins', :channel_id => @channel.id response.should be_successful end end + describe "Not Logged In" do + it "should display public plugins" do + get :public + response.should render_template('public') + end + + it "should show paginated list of public plugins as json" do + @plugin.update_column(:public_flag, true) + get :public, :format => :json + JSON.parse(response.body).keys.include?('pagination').should be_true + JSON.parse(response.body)['plugins'].length.should eq(1) + end + + it "should not show private plugins" do + @plugin.update_column(:public_flag, false) + get :public, :format => :json + JSON.parse(response.body)['plugins'].length.should eq(0) + end + end + + describe "API" do + describe "list plugins" do + it "should not list my plugins" do + get :index, {:api_key => 'INVALID', :format => 'json'} + response.status.should eq(401) + end + + it "lists my plugins" do + get :index, {:api_key => @user.api_key, :format => 'json'} + response.should be_successful + end + end + end end +