├── log └── .gitkeep ├── lib ├── tasks │ └── .gitkeep └── assets │ └── .gitkeep ├── test ├── unit │ └── .gitkeep ├── fixtures │ └── .gitkeep ├── functional │ └── .gitkeep ├── integration │ └── .gitkeep ├── performance │ └── browsing_test.rb └── test_helper.rb ├── app ├── mailers │ └── .gitkeep ├── models │ ├── .gitkeep │ ├── user.rb │ └── lead.rb ├── helpers │ ├── leads_helper.rb │ ├── tasks_helper.rb │ ├── sessions_helper.rb │ └── application_helper.rb ├── assets │ ├── images │ │ └── rails.png │ ├── stylesheets │ │ ├── leads.css.scss │ │ ├── tasks.css.scss │ │ ├── sessions.css.scss │ │ └── application.css │ └── javascripts │ │ ├── leads.js.coffee │ │ ├── sessions.js.coffee │ │ ├── tasks.js.coffee │ │ └── application.js ├── views │ ├── leads │ │ ├── new.html.erb │ │ ├── edit.html.erb │ │ ├── _form.html.erb │ │ └── index.html.erb │ ├── layouts │ │ └── application.html.erb │ ├── tasks │ │ ├── show.html.erb │ │ └── index.html.erb │ └── sessions │ │ └── new.html.erb └── controllers │ ├── tasks_controller.rb │ ├── application_controller.rb │ ├── leads_controller.rb │ └── sessions_controller.rb ├── vendor ├── plugins │ └── .gitkeep └── assets │ └── stylesheets │ └── .gitkeep ├── config ├── initializers │ ├── podio.rb │ ├── mime_types.rb │ ├── inflections.rb │ ├── backtrace_silencers.rb │ ├── session_store.rb │ ├── secret_token.rb │ └── wrap_parameters.rb ├── environment.rb ├── boot.rb ├── locales │ └── en.yml ├── database.yml ├── environments │ ├── development.rb │ ├── test.rb │ └── production.rb ├── routes.rb └── application.rb ├── config.ru ├── doc └── README_FOR_APP ├── public ├── robots.txt ├── 422.html ├── 404.html └── 500.html ├── db ├── migrate │ └── 20120112160232_create_users.rb ├── seeds.rb └── schema.rb ├── Rakefile ├── script └── rails ├── .gitignore ├── Gemfile ├── README.md └── Gemfile.lock /log/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /lib/tasks/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/unit/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/mailers/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/models/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /lib/assets/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/fixtures/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vendor/plugins/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/functional/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/integration/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vendor/assets/stylesheets/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/helpers/leads_helper.rb: -------------------------------------------------------------------------------- 1 | module LeadsHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/helpers/tasks_helper.rb: -------------------------------------------------------------------------------- 1 | module TasksHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/helpers/sessions_helper.rb: -------------------------------------------------------------------------------- 1 | module SessionsHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/helpers/application_helper.rb: -------------------------------------------------------------------------------- 1 | module ApplicationHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/assets/images/rails.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/podio/podio_rails_sample/master/app/assets/images/rails.png -------------------------------------------------------------------------------- /config/initializers/podio.rb: -------------------------------------------------------------------------------- 1 | Rails.application.config.middleware.use OmniAuth::Builder do 2 | provider :podio, ENV['PODIO_CLIENT_ID'], ENV['PODIO_CLIENT_SECRET'] 3 | end -------------------------------------------------------------------------------- /app/views/leads/new.html.erb: -------------------------------------------------------------------------------- 1 | <%= form_for :lead, :url => leads_path do |form| %> 2 | <%= render 'form', :form => form %> 3 | <%= form.submit 'Create Lead' %> 4 | <% end %> 5 | -------------------------------------------------------------------------------- /config.ru: -------------------------------------------------------------------------------- 1 | # This file is used by Rack-based servers to start the application. 2 | 3 | require ::File.expand_path('../config/environment', __FILE__) 4 | run PodioRailsSample::Application 5 | -------------------------------------------------------------------------------- /config/environment.rb: -------------------------------------------------------------------------------- 1 | # Load the rails application 2 | require File.expand_path('../application', __FILE__) 3 | 4 | # Initialize the rails application 5 | PodioRailsSample::Application.initialize! 6 | -------------------------------------------------------------------------------- /app/views/leads/edit.html.erb: -------------------------------------------------------------------------------- 1 | <%= form_for :lead, :url => lead_path(@lead.id), :method => :put do |form| %> 2 | <%= render 'form', :form => form %> 3 | <%= form.submit 'Update Lead' %> 4 | <% end %> 5 | -------------------------------------------------------------------------------- /app/assets/stylesheets/leads.css.scss: -------------------------------------------------------------------------------- 1 | // Place all the styles related to the leads controller here. 2 | // They will automatically be included in application.css. 3 | // You can use Sass (SCSS) here: http://sass-lang.com/ 4 | -------------------------------------------------------------------------------- /app/assets/stylesheets/tasks.css.scss: -------------------------------------------------------------------------------- 1 | // Place all the styles related to the tasks controller here. 2 | // They will automatically be included in application.css. 3 | // You can use Sass (SCSS) here: http://sass-lang.com/ 4 | -------------------------------------------------------------------------------- /app/assets/stylesheets/sessions.css.scss: -------------------------------------------------------------------------------- 1 | // Place all the styles related to the sessions controller here. 2 | // They will automatically be included in application.css. 3 | // You can use Sass (SCSS) here: http://sass-lang.com/ 4 | -------------------------------------------------------------------------------- /config/boot.rb: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | 3 | # Set up gems listed in the Gemfile. 4 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) 5 | 6 | require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE']) 7 | -------------------------------------------------------------------------------- /doc/README_FOR_APP: -------------------------------------------------------------------------------- 1 | Use this README file to introduce your application and point to useful places in the API for learning more. 2 | Run "rake doc:app" to generate API documentation for your models, controllers, helpers, and libraries. 3 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file 2 | # 3 | # To ban all spiders from the entire site uncomment the next two lines: 4 | # User-Agent: * 5 | # Disallow: / 6 | -------------------------------------------------------------------------------- /config/initializers/mime_types.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new mime types for use in respond_to blocks: 4 | # Mime::Type.register "text/richtext", :rtf 5 | # Mime::Type.register_alias "text/html", :iphone 6 | -------------------------------------------------------------------------------- /config/locales/en.yml: -------------------------------------------------------------------------------- 1 | # Sample localization file for English. Add more files in this directory for other locales. 2 | # See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points. 3 | 4 | en: 5 | hello: "Hello world" 6 | -------------------------------------------------------------------------------- /app/assets/javascripts/leads.js.coffee: -------------------------------------------------------------------------------- 1 | # Place all the behaviors and hooks related to the matching controller here. 2 | # All this logic will automatically be available in application.js. 3 | # You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/ 4 | -------------------------------------------------------------------------------- /app/assets/javascripts/sessions.js.coffee: -------------------------------------------------------------------------------- 1 | # Place all the behaviors and hooks related to the matching controller here. 2 | # All this logic will automatically be available in application.js. 3 | # You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/ 4 | -------------------------------------------------------------------------------- /app/assets/javascripts/tasks.js.coffee: -------------------------------------------------------------------------------- 1 | # Place all the behaviors and hooks related to the matching controller here. 2 | # All this logic will automatically be available in application.js. 3 | # You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/ 4 | -------------------------------------------------------------------------------- /db/migrate/20120112160232_create_users.rb: -------------------------------------------------------------------------------- 1 | class CreateUsers < ActiveRecord::Migration 2 | def change 3 | create_table :users do |t| 4 | t.string :provider 5 | t.string :uid 6 | t.string :email 7 | 8 | t.timestamps 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /app/models/user.rb: -------------------------------------------------------------------------------- 1 | class User < ActiveRecord::Base 2 | 3 | def self.create_with_omniauth(auth) 4 | create! do |user| 5 | user.provider = auth["provider"] 6 | user.uid = auth["info"]["user_id"] 7 | user.email = auth["info"]["email"] 8 | end 9 | end 10 | 11 | end 12 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env rake 2 | # Add your own tasks in files placed in lib/tasks ending in .rake, 3 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 4 | 5 | require File.expand_path('../config/application', __FILE__) 6 | 7 | PodioRailsSample::Application.load_tasks 8 | -------------------------------------------------------------------------------- /app/controllers/tasks_controller.rb: -------------------------------------------------------------------------------- 1 | class TasksController < ApplicationController 2 | 3 | def index 4 | @tasks = Podio::Task.find_all(:responsible => 0, :completed => false) # 0 is a shortcut for current user 5 | end 6 | 7 | def show 8 | @task = Podio::Task.find(params[:id]) 9 | end 10 | 11 | end 12 | -------------------------------------------------------------------------------- /script/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application. 3 | 4 | APP_PATH = File.expand_path('../../config/application', __FILE__) 5 | require File.expand_path('../../config/boot', __FILE__) 6 | require 'rails/commands' 7 | -------------------------------------------------------------------------------- /app/views/layouts/application.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |4 | Status: 5 | <%= @task.status %> 6 |
7 | 8 |9 | Group: 10 | <%= @task.group %> 11 |
12 | 13 |14 | Decscription: 15 | <%= @task.description %> 16 |
17 | 18 |19 | Due on: 20 | <%= @task.due_on %> 21 |
22 | 23 |<%= link_to 'Show tasks', tasks_path %>
24 | -------------------------------------------------------------------------------- /test/performance/browsing_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | require 'rails/performance_test_help' 3 | 4 | class BrowsingTest < ActionDispatch::PerformanceTest 5 | # Refer to the documentation for all available options 6 | # self.profile_options = { :runs => 5, :metrics => [:wall_time, :memory] 7 | # :output => 'tmp/performance', :formats => [:flat] } 8 | 9 | def test_homepage 10 | get '/' 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /config/initializers/backtrace_silencers.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. 4 | # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } 5 | 6 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. 7 | # Rails.backtrace_cleaner.remove_silencers! 8 | -------------------------------------------------------------------------------- /config/initializers/session_store.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | PodioRailsSample::Application.config.session_store :cookie_store, :key => '_podio_rails_sample_session' 4 | 5 | # Use the database for sessions instead of the cookie-based default, 6 | # which shouldn't be used to store highly confidential information 7 | # (create the session table with "rails generate session_migration") 8 | # PodioRailsSample::Application.config.session_store :active_record_store 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | # 3 | # If you find yourself ignoring temporary files generated by your text editor 4 | # or operating system, you probably want to add a global ignore instead: 5 | # git config --global core.excludesfile ~/.gitignore_global 6 | 7 | # Ignore bundler config 8 | /.bundle 9 | 10 | # Ignore the default SQLite database. 11 | /db/*.sqlite3 12 | 13 | # Ignore all logfiles and tempfiles. 14 | /log/*.log 15 | /tmp 16 | -------------------------------------------------------------------------------- /app/views/sessions/new.html.erb: -------------------------------------------------------------------------------- 1 |7 | <%= label_tag :app_id, 'App id' %> 8 | <%= text_field_tag :app_id %> 9 |
10 |11 | <%= label_tag :app_token, 'App token' %> 12 | <%= text_field_tag :app_token %> 13 |
14 |<%= submit_tag('Authenticate as app') %>
15 | <% end %> 16 | -------------------------------------------------------------------------------- /test/test_helper.rb: -------------------------------------------------------------------------------- 1 | ENV["RAILS_ENV"] = "test" 2 | require File.expand_path('../../config/environment', __FILE__) 3 | require 'rails/test_help' 4 | 5 | class ActiveSupport::TestCase 6 | # Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order. 7 | # 8 | # Note: You'll currently still have to declare fixtures explicitly in integration tests 9 | # -- they do not yet inherit this setting 10 | fixtures :all 11 | 12 | # Add more helper methods to be used by all tests here... 13 | end 14 | -------------------------------------------------------------------------------- /app/assets/javascripts/application.js: -------------------------------------------------------------------------------- 1 | // This is a manifest file that'll be compiled into including all the files listed below. 2 | // Add new JavaScript/Coffee code in separate files in this directory and they'll automatically 3 | // be included in the compiled file accessible from http://example.com/assets/application.js 4 | // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the 5 | // the compiled file. 6 | // 7 | //= require jquery 8 | //= require jquery_ujs 9 | //= require_tree . 10 | -------------------------------------------------------------------------------- /config/initializers/secret_token.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Your secret key for verifying the integrity of signed cookies. 4 | # If you change this key, all old signed cookies will become invalid! 5 | # Make sure the secret is at least 30 characters and all random, 6 | # no regular words or you'll be exposed to dictionary attacks. 7 | PodioRailsSample::Application.config.secret_token = 'a06ae4e09fee7309e3b93e77ea1e72ab2363f6d7477439095919c82a1fe32e9f90867deead423ea3d80118fb5f49764a7006f2741e5e9a6dd07255486025e118' 8 | -------------------------------------------------------------------------------- /config/initializers/wrap_parameters.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | # 3 | # This file contains settings for ActionController::ParamsWrapper which 4 | # is enabled by default. 5 | 6 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. 7 | ActiveSupport.on_load(:action_controller) do 8 | wrap_parameters :format => [:json] 9 | end 10 | 11 | # Disable root element in JSON by default. 12 | ActiveSupport.on_load(:active_record) do 13 | self.include_root_in_json = false 14 | end 15 | -------------------------------------------------------------------------------- /app/views/tasks/index.html.erb: -------------------------------------------------------------------------------- 1 || Task ID | 4 |Status | 5 |Group | 6 |Text | 7 |8 | |
|---|---|---|---|---|
| <%= task.id %> | 12 |<%= task.status %> | 13 |<%= task.group %> | 14 |<%= task.text %> | 15 |<%= link_to 'Details', task_path(task.id) %> | 16 |
<%= link_to 'Show leads', leads_path %> | <%= link_to 'Logout', sessions_path, :method => :delete %>
21 | -------------------------------------------------------------------------------- /config/database.yml: -------------------------------------------------------------------------------- 1 | # SQLite version 3.x 2 | # gem install sqlite3 3 | # 4 | # Ensure the SQLite 3 gem is defined in your Gemfile 5 | # gem 'sqlite3' 6 | development: 7 | adapter: sqlite3 8 | database: db/development.sqlite3 9 | pool: 5 10 | timeout: 5000 11 | 12 | # Warning: The database defined as "test" will be erased and 13 | # re-generated from your development database when you run "rake". 14 | # Do not set this db to the same as development or production. 15 | test: 16 | adapter: sqlite3 17 | database: db/test.sqlite3 18 | pool: 5 19 | timeout: 5000 20 | 21 | production: 22 | adapter: sqlite3 23 | database: db/production.sqlite3 24 | pool: 5 25 | timeout: 5000 26 | -------------------------------------------------------------------------------- /app/controllers/application_controller.rb: -------------------------------------------------------------------------------- 1 | class ApplicationController < ActionController::Base 2 | protect_from_forgery 3 | 4 | before_filter :ensure_login 5 | 6 | protected 7 | 8 | def ensure_login 9 | if session[:podio_access_token] 10 | init_podio_client 11 | else 12 | redirect_to new_session_path 13 | end 14 | end 15 | 16 | def init_podio_client 17 | Podio.setup( 18 | :api_url => 'https://api.podio.com', 19 | :api_key => ENV['PODIO_CLIENT_ID'], 20 | :api_secret => ENV['PODIO_CLIENT_SECRET'], 21 | :oauth_token => Podio::OAuthToken.new('access_token' => session[:podio_access_token], 'refresh_token' => session[:podio_refresh_token]) 22 | ) 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /public/422.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |Maybe you tried to change something you didn't have access to.
24 |You may have mistyped the address or the page may have moved.
24 |We've been notified about this issue and we'll take a look at it shortly.
24 |2 | <%= form.label :organization %> 3 | <%= form.text_field :organization %> 4 |
5 |6 | <%= form.label :lead_contact %> 7 | <%= form.select :lead_contact, @lead_contacts.collect { |lc| [lc.name, lc.profile_id] } %> 8 |
9 |10 | <%= form.label :sales_contact %> 11 | <%= form.select :sales_contact, @sales_contacts.collect { |lc| [lc.name, lc.profile_id] } %> 12 |
13 |14 | <%= form.label :potential_revenue %> 15 | <%= form.text_field :potential_revenue_value %> 16 | <%= form.select :potential_revenue_currency, ['USD', 'EUR'] %> 17 |
18 |19 | <%= form.label :probability %> 20 | <%= form.text_field :probability %> 21 |
22 |23 | <%= form.label :status_id, 'Status' %> 24 | <%= form.select :status_id, @statuses %> 25 |
26 |27 | <%= form.label :followup_at %> 28 | <%= form.date_select :followup_at %> 29 |
30 | -------------------------------------------------------------------------------- /app/controllers/leads_controller.rb: -------------------------------------------------------------------------------- 1 | class LeadsController < ApplicationController 2 | before_filter :load_collections, :only => [:new, :edit] 3 | 4 | def index 5 | @leads = Lead.all 6 | end 7 | 8 | def new 9 | @lead = Lead.new 10 | end 11 | 12 | def create 13 | Lead.create_from_params(params['lead']) 14 | redirect_to leads_path, :notice => 'Lead created' 15 | end 16 | 17 | def edit 18 | @lead = Lead.find_basic(params[:id]) 19 | end 20 | 21 | def update 22 | Lead.update_from_params(params[:id], params['lead']) 23 | redirect_to leads_path, :notice => 'Lead updated' 24 | end 25 | 26 | def destroy 27 | Lead.delete(params[:id]) 28 | redirect_to leads_path, :notice => 'Lead deleted' 29 | end 30 | 31 | protected 32 | 33 | def load_collections 34 | @lead_contacts = Lead.space_contacts 35 | @sales_contacts = Lead.users 36 | @statuses = Lead.statuses 37 | end 38 | 39 | end 40 | -------------------------------------------------------------------------------- /db/schema.rb: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | # This file is auto-generated from the current state of the database. Instead 3 | # of editing this file, please use the migrations feature of Active Record to 4 | # incrementally modify your database, and then regenerate this schema definition. 5 | # 6 | # Note that this schema.rb definition is the authoritative source for your 7 | # database schema. If you need to create the application database on another 8 | # system, you should be using db:schema:load, not running all the migrations 9 | # from scratch. The latter is a flawed and unsustainable approach (the more migrations 10 | # you'll amass, the slower it'll run and the greater likelihood for issues). 11 | # 12 | # It's strongly recommended to check this file into your version control system. 13 | 14 | ActiveRecord::Schema.define(:version => 20120112160232) do 15 | 16 | create_table "users", :force => true do |t| 17 | t.string "provider" 18 | t.string "uid" 19 | t.string "email" 20 | t.datetime "created_at", :null => false 21 | t.datetime "updated_at", :null => false 22 | end 23 | 24 | end 25 | -------------------------------------------------------------------------------- /app/views/leads/index.html.erb: -------------------------------------------------------------------------------- 1 || Organization | 4 |Lead Contact | 5 |Sales Contact | 6 |Potential Revenue | 7 |Probability | 8 |Status | 9 |Next follow up at | 10 |11 | |
|---|---|---|---|---|---|---|---|
| <%= lead.organization %> | 15 |<%= lead.lead_contact %> | 16 |<%= lead.sales_contact %> | 17 |<%= number_to_currency(lead.potential_revenue_value, :unit => lead.potential_revenue_currency) %> | 18 |<%= number_to_percentage(lead.probability.to_i) %> | 19 |<%= lead.status_text %> | 20 |<%= l(lead.followup_at.to_date) %> | 21 |<%= link_to 'Edit', edit_lead_path(lead.id) %> | <%= link_to 'Delete', lead_path(lead.id), :method => :delete, :confirm => 'Are you sure?' %> | 22 |
27 | <%= link_to 'Create a new lead', new_lead_path %> | 28 | <%= link_to 'Show tasks', tasks_path %> | 29 | <%= link_to 'Logout', sessions_path, :method => :delete %> 30 |
31 | -------------------------------------------------------------------------------- /config/environments/development.rb: -------------------------------------------------------------------------------- 1 | PodioRailsSample::Application.configure do 2 | # Settings specified here will take precedence over those in config/application.rb 3 | 4 | # In the development environment your application's code is reloaded on 5 | # every request. This slows down response time but is perfect for development 6 | # since you don't have to restart the web server when you make code changes. 7 | config.cache_classes = false 8 | 9 | # Log error messages when you accidentally call methods on nil. 10 | config.whiny_nils = true 11 | 12 | # Show full error reports and disable caching 13 | config.consider_all_requests_local = true 14 | config.action_controller.perform_caching = false 15 | 16 | # Don't care if the mailer can't send 17 | # config.action_mailer.raise_delivery_errors = false 18 | 19 | # Print deprecation notices to the Rails logger 20 | config.active_support.deprecation = :log 21 | 22 | # Only use best-standards-support built into browsers 23 | config.action_dispatch.best_standards_support = :builtin 24 | 25 | # Do not compress assets 26 | config.assets.compress = false 27 | 28 | # Expands the lines which load the assets 29 | config.assets.debug = true 30 | end 31 | -------------------------------------------------------------------------------- /app/controllers/sessions_controller.rb: -------------------------------------------------------------------------------- 1 | class SessionsController < ApplicationController 2 | skip_before_filter :ensure_login 3 | 4 | def new 5 | end 6 | 7 | def create 8 | auth = request.env["omniauth.auth"] 9 | user = User.find_by_provider_and_uid(auth["provider"], auth["info"]["user_id"]) || User.create_with_omniauth(auth) 10 | session[:user_id] = user.id 11 | session[:podio_access_token] = auth["credentials"]["token"] 12 | session[:podio_refresh_token] = auth["credentials"]["refresh_token"] 13 | redirect_to root_url, :notice => "Signed in!" 14 | end 15 | 16 | def create_from_app_auth 17 | Podio.setup( 18 | :api_url => 'https://api.podio.com', 19 | :api_key => ENV['PODIO_CLIENT_ID'], 20 | :api_secret => ENV['PODIO_CLIENT_SECRET'] 21 | ) 22 | 23 | Podio.client.authenticate_with_app(params[:app_id], params[:app_token]) 24 | 25 | session[:podio_access_token] = Podio.client.oauth_token.access_token 26 | session[:podio_refresh_token] = Podio.client.oauth_token.refresh_token 27 | 28 | redirect_to root_url, :notice => "Signed in!" 29 | end 30 | 31 | def destroy 32 | session.clear 33 | redirect_to root_url, :notice => "Logged out!" 34 | end 35 | 36 | end 37 | -------------------------------------------------------------------------------- /config/environments/test.rb: -------------------------------------------------------------------------------- 1 | PodioRailsSample::Application.configure do 2 | # Settings specified here will take precedence over those in config/application.rb 3 | 4 | # The test environment is used exclusively to run your application's 5 | # test suite. You never need to work with it otherwise. Remember that 6 | # your test database is "scratch space" for the test suite and is wiped 7 | # and recreated between test runs. Don't rely on the data there! 8 | config.cache_classes = true 9 | 10 | # Configure static asset server for tests with Cache-Control for performance 11 | config.serve_static_assets = true 12 | config.static_cache_control = "public, max-age=3600" 13 | 14 | # Log error messages when you accidentally call methods on nil 15 | config.whiny_nils = true 16 | 17 | # Show full error reports and disable caching 18 | config.consider_all_requests_local = true 19 | config.action_controller.perform_caching = false 20 | 21 | # Raise exceptions instead of rendering exception templates 22 | config.action_dispatch.show_exceptions = false 23 | 24 | # Disable request forgery protection in test environment 25 | config.action_controller.allow_forgery_protection = false 26 | 27 | # Tell Action Mailer not to deliver emails to the real world. 28 | # The :test delivery method accumulates sent emails in the 29 | # ActionMailer::Base.deliveries array. 30 | config.action_mailer.delivery_method = :test 31 | 32 | # Use SQL instead of Active Record's schema dumper when creating the test database. 33 | # This is necessary if your schema can't be completely dumped by the schema dumper, 34 | # like if you have constraints or database-specific column types 35 | # config.active_record.schema_format = :sql 36 | 37 | # Print deprecation notices to the stderr 38 | config.active_support.deprecation = :stderr 39 | end 40 | -------------------------------------------------------------------------------- /config/routes.rb: -------------------------------------------------------------------------------- 1 | PodioRailsSample::Application.routes.draw do 2 | 3 | root :to => 'leads#index' 4 | resources :sessions, :only => [:new, :create] do 5 | collection do 6 | delete :destroy 7 | post :create_from_app_auth 8 | end 9 | end 10 | match "/auth/:provider/callback" => "sessions#create" 11 | resources :leads 12 | resources :tasks 13 | 14 | # The priority is based upon order of creation: 15 | # first created -> highest priority. 16 | 17 | # Sample of regular route: 18 | # match 'products/:id' => 'catalog#view' 19 | # Keep in mind you can assign values other than :controller and :action 20 | 21 | # Sample of named route: 22 | # match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase 23 | # This route can be invoked with purchase_url(:id => product.id) 24 | 25 | # Sample resource route (maps HTTP verbs to controller actions automatically): 26 | # resources :products 27 | 28 | # Sample resource route with options: 29 | # resources :products do 30 | # member do 31 | # get 'short' 32 | # post 'toggle' 33 | # end 34 | # 35 | # collection do 36 | # get 'sold' 37 | # end 38 | # end 39 | 40 | # Sample resource route with sub-resources: 41 | # resources :products do 42 | # resources :comments, :sales 43 | # resource :seller 44 | # end 45 | 46 | # Sample resource route with more complex sub-resources 47 | # resources :products do 48 | # resources :comments 49 | # resources :sales do 50 | # get 'recent', :on => :collection 51 | # end 52 | # end 53 | 54 | # Sample resource route within a namespace: 55 | # namespace :admin do 56 | # # Directs /admin/products/* to Admin::ProductsController 57 | # # (app/controllers/admin/products_controller.rb) 58 | # resources :products 59 | # end 60 | 61 | # You can have the root of your site routed with "root" 62 | # just remember to delete public/index.html. 63 | # root :to => 'welcome#index' 64 | 65 | # See how all your routes lay out with "rake routes" 66 | 67 | # This is a legacy wild controller route that's not recommended for RESTful applications. 68 | # Note: This route will make all actions in every controller accessible via GET requests. 69 | # match ':controller(/:action(/:id(.:format)))' 70 | end 71 | -------------------------------------------------------------------------------- /config/environments/production.rb: -------------------------------------------------------------------------------- 1 | PodioRailsSample::Application.configure do 2 | # Settings specified here will take precedence over those in config/application.rb 3 | 4 | # Code is not reloaded between requests 5 | config.cache_classes = true 6 | 7 | # Full error reports are disabled and caching is turned on 8 | config.consider_all_requests_local = false 9 | config.action_controller.perform_caching = true 10 | 11 | # Disable Rails's static asset server (Apache or nginx will already do this) 12 | config.serve_static_assets = false 13 | 14 | # Compress JavaScripts and CSS 15 | config.assets.compress = true 16 | 17 | # Don't fallback to assets pipeline if a precompiled asset is missed 18 | config.assets.compile = false 19 | 20 | # Generate digests for assets URLs 21 | config.assets.digest = true 22 | 23 | # Defaults to Rails.root.join("public/assets") 24 | # config.assets.manifest = YOUR_PATH 25 | 26 | # Specifies the header that your server uses for sending files 27 | # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache 28 | # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx 29 | 30 | # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. 31 | # config.force_ssl = true 32 | 33 | # See everything in the log (default is :info) 34 | # config.log_level = :debug 35 | 36 | # Use a different logger for distributed setups 37 | # config.logger = SyslogLogger.new 38 | 39 | # Use a different cache store in production 40 | # config.cache_store = :mem_cache_store 41 | 42 | # Enable serving of images, stylesheets, and JavaScripts from an asset server 43 | # config.action_controller.asset_host = "http://assets.example.com" 44 | 45 | # Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added) 46 | # config.assets.precompile += %w( search.js ) 47 | 48 | # Disable delivery errors, bad email addresses will be ignored 49 | # config.action_mailer.raise_delivery_errors = false 50 | 51 | # Enable threaded mode 52 | # config.threadsafe! 53 | 54 | # Enable locale fallbacks for I18n (makes lookups for any locale fall back to 55 | # the I18n.default_locale when a translation can not be found) 56 | config.i18n.fallbacks = true 57 | 58 | # Send deprecation notices to registered listeners 59 | config.active_support.deprecation = :notify 60 | end 61 | -------------------------------------------------------------------------------- /config/application.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../boot', __FILE__) 2 | 3 | # Pick the frameworks you want: 4 | require "active_record/railtie" 5 | require "action_controller/railtie" 6 | # require "action_mailer/railtie" 7 | # require "active_resource/railtie" 8 | # require "sprockets/railtie" 9 | # require "rails/test_unit/railtie" 10 | 11 | if defined?(Bundler) 12 | # If you precompile assets before deploying to production, use this line 13 | Bundler.require(*Rails.groups(:assets => %w(development test))) 14 | # If you want your assets lazily compiled in production, use this line 15 | # Bundler.require(:default, :assets, Rails.env) 16 | end 17 | 18 | module PodioRailsSample 19 | class Application < Rails::Application 20 | # Settings in config/environments/* take precedence over those specified here. 21 | # Application configuration should go into files in config/initializers 22 | # -- all .rb files in that directory are automatically loaded. 23 | 24 | # Custom directories with classes and modules you want to be autoloadable. 25 | # config.autoload_paths += %W(#{config.root}/extras) 26 | 27 | # Only load the plugins named here, in the order given (default is alphabetical). 28 | # :all can be used as a placeholder for all plugins not explicitly named. 29 | # config.plugins = [ :exception_notification, :ssl_requirement, :all ] 30 | 31 | # Activate observers that should always be running. 32 | # config.active_record.observers = :cacher, :garbage_collector, :forum_observer 33 | 34 | # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. 35 | # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. 36 | # config.time_zone = 'Central Time (US & Canada)' 37 | 38 | # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. 39 | # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] 40 | # config.i18n.default_locale = :de 41 | 42 | # Configure the default encoding used in templates for Ruby 1.9. 43 | config.encoding = "utf-8" 44 | 45 | # Configure sensitive parameters which will be filtered from the log file. 46 | config.filter_parameters += [:password] 47 | 48 | # Enable the asset pipeline 49 | config.assets.enabled = true 50 | 51 | # Version of your assets, change this if you want to expire all your assets 52 | config.assets.version = '1.0' 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Podio sample Rails application 2 | 3 | This app demonstrates how to authenticate against Podio, and how to read and write items. 4 | 5 | ## Preparations on Podio 6 | 7 | Create an API key by logging into Podio and go to Account Settings in the My Account dropdown. Then go to the API Keys tab and write a name and a domain for this app. While you are developing, you probably want to set the domain to `localhost:3000 or similar. 8 | 9 | To be able to run this sample you must also have the Leads app installed on Podio. It can be installed [from the App Store](https://podio.com/store/app/11236-leads). You can also use another app, but then this example won't work "out of the box". 10 | 11 | ## Installation 12 | 13 | Clone this repository: 14 | 15 | git clone https://github.com/podio/podio_rails_sample.git 16 | 17 | Install gem dependencies: 18 | 19 | bundle install 20 | 21 | Setup the database: 22 | 23 | rake db:migrate 24 | 25 | ## Configuration 26 | 27 | You must put your API key and secret in the environment variables PODIO_CLIENT_ID and PODIO_CLIENT_SECRET. Alternatively you can hardcode them in config/initializers/podio.rb. 28 | 29 | You must also update the hardcoded APP_ID and SPACE_ID constants in app/models/lead.rb to the corresponding ids for your instance of the Leads app. You find the app id by going to your installed Leads app on Podio, click the wrench icon and select "Developers". One way to get the space id is to go to the [API reference page for the Get app operation](https://developers.podio.com/doc/applications/get-app-22349), scroll to the bottom, login to the sandbox, paste in the app id, submit the form and find the "space_id" in the result. 30 | 31 | ## Running 32 | 33 | To start the web server locally, run: 34 | 35 | rails server 36 | 37 | Then go to [localhost:3000](http://localhost:3000) to login and use the app. 38 | 39 | ## App authentication 40 | 41 | When you run this app, you will notice that you get the opportunity to paste in an app id and an app token on the login page. This demonstrates how you can authenticate as an app, rather than as a user. You get the app id and token from the app's "Developer" page. The different ways of authenticating are explained here: https://developers.podio.com/authentication. 42 | 43 | ## Tips 44 | 45 | You probably want to work with Podio apps that has a completely different structure than the Leads app used in this example. The easiest way to the see the structure and the all-important external ids of you app is to go to the aforementioned "Developers" page for your app.You can also go to https://developers.podio.com/doc/applications/get-app-22349 and enter the app id with "full" as type in the in the sandbox. 46 | 47 | Further, you can see exactly what fields and values you get from a Get Items call by using the sandbox here: https://developers.podio.com/doc/items/get-items-27803 48 | 49 | The authentication in this app is based on Omniauth and a strategy for using Omnioauth with Podio - https://github.com/lucasallan/omniauth-podio. On top of that it pretty much follows the steps outlined in the RailsCast about simple Omniauth usage - http://railscasts.com/episodes/241-simple-omniauth?view=asciicast. 50 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: http://rubygems.org/ 3 | specs: 4 | actionmailer (3.2.8) 5 | actionpack (= 3.2.8) 6 | mail (~> 2.4.4) 7 | actionpack (3.2.8) 8 | activemodel (= 3.2.8) 9 | activesupport (= 3.2.8) 10 | builder (~> 3.0.0) 11 | erubis (~> 2.7.0) 12 | journey (~> 1.0.4) 13 | rack (~> 1.4.0) 14 | rack-cache (~> 1.2) 15 | rack-test (~> 0.6.1) 16 | sprockets (~> 2.1.3) 17 | activemodel (3.2.8) 18 | activesupport (= 3.2.8) 19 | builder (~> 3.0.0) 20 | activerecord (3.2.8) 21 | activemodel (= 3.2.8) 22 | activesupport (= 3.2.8) 23 | arel (~> 3.0.2) 24 | tzinfo (~> 0.3.29) 25 | activeresource (3.2.8) 26 | activemodel (= 3.2.8) 27 | activesupport (= 3.2.8) 28 | activesupport (3.2.8) 29 | i18n (~> 0.6) 30 | multi_json (~> 1.0) 31 | addressable (2.3.2) 32 | ansi (1.4.3) 33 | arel (3.0.2) 34 | builder (3.0.0) 35 | coffee-rails (3.2.2) 36 | coffee-script (>= 2.2.0) 37 | railties (~> 3.2.0) 38 | coffee-script (2.2.0) 39 | coffee-script-source 40 | execjs 41 | coffee-script-source (1.3.3) 42 | erubis (2.7.0) 43 | execjs (1.4.0) 44 | multi_json (~> 1.0) 45 | faraday (0.7.6) 46 | addressable (~> 2.2) 47 | multipart-post (~> 1.1) 48 | rack (~> 1.1) 49 | hashie (1.2.0) 50 | hike (1.2.1) 51 | httpauth (0.1) 52 | i18n (0.6.1) 53 | journey (1.0.4) 54 | jquery-rails (2.1.1) 55 | railties (>= 3.1.0, < 5.0) 56 | thor (~> 0.14) 57 | json (1.7.5) 58 | mail (2.4.4) 59 | i18n (>= 0.4.0) 60 | mime-types (~> 1.16) 61 | treetop (~> 1.4.8) 62 | mime-types (1.19) 63 | multi_json (1.3.6) 64 | multipart-post (1.1.5) 65 | oauth2 (0.6.1) 66 | faraday (~> 0.7) 67 | httpauth (~> 0.1) 68 | multi_json (~> 1.3) 69 | omniauth (1.1.1) 70 | hashie (~> 1.2) 71 | rack 72 | omniauth-oauth2 (1.0.2) 73 | oauth2 (~> 0.6.0) 74 | omniauth (~> 1.0) 75 | omniauth-podio (0.0.1) 76 | omniauth (~> 1.0) 77 | omniauth-oauth2 (~> 1.0) 78 | podio (0.8) 79 | activemodel (~> 3.0) 80 | activesupport (~> 3.0) 81 | faraday (~> 0.7.0) 82 | multi_json 83 | polyglot (0.3.3) 84 | rack (1.4.1) 85 | rack-cache (1.2) 86 | rack (>= 0.4) 87 | rack-ssl (1.3.2) 88 | rack 89 | rack-test (0.6.1) 90 | rack (>= 1.0) 91 | rails (3.2.8) 92 | actionmailer (= 3.2.8) 93 | actionpack (= 3.2.8) 94 | activerecord (= 3.2.8) 95 | activeresource (= 3.2.8) 96 | activesupport (= 3.2.8) 97 | bundler (~> 1.0) 98 | railties (= 3.2.8) 99 | railties (3.2.8) 100 | actionpack (= 3.2.8) 101 | activesupport (= 3.2.8) 102 | rack-ssl (~> 1.3.2) 103 | rake (>= 0.8.7) 104 | rdoc (~> 3.4) 105 | thor (>= 0.14.6, < 2.0) 106 | rake (0.9.2.2) 107 | rdoc (3.12) 108 | json (~> 1.4) 109 | sass (3.2.1) 110 | sass-rails (3.2.5) 111 | railties (~> 3.2.0) 112 | sass (>= 3.1.10) 113 | tilt (~> 1.3) 114 | sprockets (2.1.3) 115 | hike (~> 1.2) 116 | rack (~> 1.0) 117 | tilt (~> 1.1, != 1.3.0) 118 | sqlite3 (1.3.6) 119 | thor (0.16.0) 120 | tilt (1.3.3) 121 | treetop (1.4.10) 122 | polyglot 123 | polyglot (>= 0.3.1) 124 | turn (0.9.6) 125 | ansi 126 | tzinfo (0.3.33) 127 | uglifier (1.3.0) 128 | execjs (>= 0.3.0) 129 | multi_json (~> 1.0, >= 1.0.2) 130 | 131 | PLATFORMS 132 | ruby 133 | 134 | DEPENDENCIES 135 | coffee-rails 136 | jquery-rails 137 | omniauth-podio 138 | podio 139 | rails 140 | sass-rails 141 | sqlite3 142 | turn 143 | uglifier 144 | -------------------------------------------------------------------------------- /app/models/lead.rb: -------------------------------------------------------------------------------- 1 | class Lead < Podio::Item 2 | APP_ID = 12695955 3 | SPACE_ID = 3631649 4 | 5 | # Find all items in the Leads app 6 | def self.all 7 | collection = self.find_all(APP_ID) 8 | collection[:all] 9 | end 10 | 11 | # Find valid lead contacts in the space 12 | def self.space_contacts 13 | Podio::Contact.find_all_for_space(SPACE_ID, :order => 'contact', :limit => 12, :contact_type => 'space,connection', :exclude_self => false) rescue [] 14 | end 15 | 16 | # Find valid sales contacts in the space 17 | def self.users 18 | Podio::Contact.find_all_for_space(SPACE_ID, :order => 'contact', :limit => 12, :contact_type => 'user', :exclude_self => false) rescue [] 19 | end 20 | 21 | # Find valid statuses 22 | def self.statuses 23 | app = Podio::Application.find(APP_ID) 24 | field = app.fields.find { |field| field['external_id'] == 'status2' } 25 | field['config']['settings']['options'].map { |option| [option['text'], option['id']] } 26 | end 27 | 28 | def self.create_from_params(params) 29 | # raise fields.inspect 30 | self.create(APP_ID, { :fields => fields_from_params(params) }) 31 | end 32 | 33 | def self.update_from_params(id, params) 34 | self.update(id, { :fields => fields_from_params(params) }) 35 | end 36 | 37 | # 38 | # Map the field values return by the Podio API to simple getters 39 | # 40 | 41 | def organization 42 | field_values_by_external_id('company-or-organisation', :simple => true) 43 | end 44 | 45 | def lead_contact 46 | field_values_by_external_id('contacts', :simple => true).try(:[], 'name') 47 | end 48 | 49 | def sales_contact 50 | field_values_by_external_id('sales-contact', :simple => true).try(:[], 'name') 51 | end 52 | 53 | def potential_revenue_value 54 | field_values_by_external_id('potential-revenue').try(:first).try(:[], 'value').to_i 55 | end 56 | 57 | def potential_revenue_currency 58 | field_values_by_external_id('potential-revenue').try(:first).try(:[], 'currency') 59 | end 60 | 61 | def probability 62 | field_values_by_external_id('probability-of-sale', :simple => true) 63 | end 64 | 65 | def status_id 66 | field_values_by_external_id('status2', :simple => true).try(:[], 'id') 67 | end 68 | 69 | def status_text 70 | field_values_by_external_id('status2', :simple => true).try(:[], 'text') 71 | end 72 | 73 | def followup_at 74 | field_values_by_external_id('next-follow-up').try(:first).try(:[], 'start').try(:to_datetime) 75 | end 76 | 77 | protected 78 | 79 | def field_values_by_external_id(external_id, options = {}) 80 | if self.fields.present? 81 | field = self.fields.find { |field| field['external_id'] == external_id } 82 | if field 83 | values = field['values'] 84 | if options[:simple] 85 | values.first['value'] 86 | else 87 | values 88 | end 89 | else 90 | nil 91 | end 92 | else 93 | nil 94 | end 95 | end 96 | 97 | def self.fields_from_params(params) 98 | { 99 | 'company-or-organisation' => params[:organization], 100 | 'contacts' => (params[:lead_contact].present? ? params[:lead_contact].to_i : nil), 101 | 'sales-contact' => (params[:sales_contact].present? ? params[:sales_contact].to_i : nil), 102 | 'potential-revenue' => { :value => params['potential_revenue_value'], :currency => params['potential_revenue_currency'] }, 103 | 'probability-of-sale' => params[:probability].to_i, 104 | 'status2' => params[:status_id].to_i, 105 | 'next-follow-up' => DateTime.new(params['followup_at(1i)'].to_i, params['followup_at(2i)'].to_i, params['followup_at(3i)'].to_i).to_s(:db) 106 | }.delete_if { |k, v| v.nil? } 107 | end 108 | 109 | end 110 | --------------------------------------------------------------------------------