shopify_app 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. data/.gitignore +7 -0
  2. data/CHANGELOG +2 -0
  3. data/Gemfile +4 -0
  4. data/README.rdoc +58 -0
  5. data/Rakefile +2 -0
  6. data/install.rb +25 -0
  7. data/lib/generators/shopify_app/README +23 -0
  8. data/lib/generators/shopify_app/USAGE +22 -0
  9. data/lib/generators/shopify_app/shopify_app_generator.rb +50 -0
  10. data/lib/generators/shopify_app/templates/app/controllers/home_controller.rb +18 -0
  11. data/lib/generators/shopify_app/templates/app/controllers/login_controller.rb +50 -0
  12. data/lib/generators/shopify_app/templates/app/helpers/home_helper.rb +3 -0
  13. data/lib/generators/shopify_app/templates/app/helpers/login_helper.rb +3 -0
  14. data/lib/generators/shopify_app/templates/app/helpers/tabs_helper.rb +10 -0
  15. data/lib/generators/shopify_app/templates/app/views/home/design.html.erb +164 -0
  16. data/lib/generators/shopify_app/templates/app/views/home/index.html.erb +103 -0
  17. data/lib/generators/shopify_app/templates/app/views/home/welcome.html.erb +110 -0
  18. data/lib/generators/shopify_app/templates/app/views/layouts/application.html.erb +39 -0
  19. data/lib/generators/shopify_app/templates/app/views/login/index.html.erb +15 -0
  20. data/lib/generators/shopify_app/templates/public/images/box-bg2.gif +0 -0
  21. data/lib/generators/shopify_app/templates/public/images/info-bg.gif +0 -0
  22. data/lib/generators/shopify_app/templates/public/images/info.gif +0 -0
  23. data/lib/generators/shopify_app/templates/public/images/shopify-logo.png +0 -0
  24. data/lib/generators/shopify_app/templates/public/stylesheets/application.css +285 -0
  25. data/lib/shopify_app.rb +17 -0
  26. data/lib/shopify_app/configuration.rb +6 -0
  27. data/lib/shopify_app/login_protection.rb +21 -0
  28. data/lib/shopify_app/railtie.rb +17 -0
  29. data/lib/shopify_app/version.rb +3 -0
  30. data/shopify_app.gemspec +26 -0
  31. metadata +134 -0
@@ -0,0 +1,7 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ .DS_Store
6
+ .yardoc
7
+ doc/
@@ -0,0 +1,2 @@
1
+ * Require shopify_api gem
2
+ * Don't require shopify.yml when using environment variables [cody]
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in shopify_app.gemspec
4
+ gemspec
@@ -0,0 +1,58 @@
1
+ = Shopify application generator for Rails 3
2
+
3
+ == Description
4
+
5
+ This plugin makes it easy to get a Rails 3 app up and running with the
6
+ Shopify API.
7
+
8
+ The generator creates a basic login controller for authenticating with your
9
+ shop and a controller called "home" which displays basic information about
10
+ your products, orders and articles.
11
+
12
+ <i>Note: It's recommended to use this on a new Rails project, so that the
13
+ generator won't overwrite/delete some of your files.</i>
14
+
15
+ == Installation
16
+
17
+ # Add the gem shopify_app to your Gemfile
18
+ $ echo "gem 'shopify_app'" >> Gemfile
19
+ $ bundle install
20
+
21
+ == Usage
22
+
23
+ $ rails generate shopify_app your_app_api_key your_app_secret
24
+
25
+ If you don't have an API key yet, create a Shopify Partner account at
26
+ http://shopify.com/partners and create an app. You can also create test shops
27
+ once you're logged in as a partner.
28
+
29
+ When you create your app in the Shopify Partner Account, set the return URL to
30
+ <tt>http://localhost:3000/login/finalize</tt>
31
+
32
+ You can also create a private application that only works for your shop by
33
+ visiting https://YOUR-SHOP.myshopify.com/admin/api
34
+
35
+ === Example
36
+
37
+ $ rails generate shopify_app edffbb1bb793e2750686e6f4647a384a fed5bb18hde3e2750686e6f4647a781a
38
+
39
+ This will create a LoginController and a HomeController with their own views.
40
+
41
+ == After running the generator
42
+
43
+ First, start your application:
44
+
45
+ $ rails server
46
+
47
+ Now visit http://localhost:3000 and install your application in a Shopify store.
48
+
49
+ After your application has been given read or read/write API permission by the
50
+ shop, you're ready to start experimenting with the Shopify API.
51
+
52
+ == Questions or problems?
53
+
54
+ http://api.shopify.com <= Read up on the possible API calls!
55
+
56
+ http://forums.shopify.com/categories/9 <= Talk to new friends!
57
+
58
+ http://wiki.shopify.com/Shopify_App_Development <= Edit the docs!
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,25 @@
1
+ puts
2
+ puts "Shopify App Generator"
3
+ puts "---------------------"
4
+ puts
5
+ puts "To get started, first register your app as a Shopify Partner:"
6
+ puts
7
+ puts " * Go to http://www.shopify.com/partners and create or login to your Partner account."
8
+ puts
9
+ puts " * Jump over to the Apps tab and hit the 'Create a new app' button"
10
+ puts " (Make sure to set the Return URL to http://localhost:3000/login/finalize during development)"
11
+ puts
12
+ puts " * Install the Shopify API gem:
13
+
14
+ $ gem install shopify_api"
15
+ puts
16
+ puts " * Run
17
+
18
+ $ rails generate shopify_app your_app_api_key your_app_secret"
19
+ puts
20
+ puts " * Set up a test shop to install your app in (do this on the Partner site)"
21
+ puts
22
+ puts " * Run $ rails server"
23
+ puts
24
+ puts " * Visit http://localhost:3000 and use the test shop's URL to install this app"
25
+ puts
@@ -0,0 +1,23 @@
1
+
2
+
3
+ What's next?
4
+ ------------
5
+
6
+ Make sure to set the return URL of the application your Shopify partner account
7
+ to <tt>http://localhost:3000/login/finalize</tt>.
8
+
9
+ Then, start your application with:
10
+
11
+ $ rails server
12
+
13
+ Now visit http://localhost:3000 and install your application in a Shopify store.
14
+
15
+ After your application has been given read or read/write API permission by the
16
+ shop, you're ready to start experimenting with the Shopify API.
17
+
18
+ Questions or problems?
19
+ ----------------------
20
+
21
+ API Reference http://api.shopify.com
22
+ Developer Forums http://forums.shopify.com/categories/9
23
+ Developer Wiki http://wiki.shopify.com/Shopify_App_Development
@@ -0,0 +1,22 @@
1
+ Description:
2
+ This is a generator for creating a basic Shopify application to quickly get
3
+ you started. You can see some examples on how to use the Shopify API.
4
+
5
+ The generator creates a basic login controller for authenticating with your
6
+ Shop and a controller called "home" which displays basic information
7
+ about your products, orders and articles.
8
+
9
+ Note: It's recommended to use this on a new Rails project, so that the
10
+ generator won't overwrite/delete some of your files.
11
+
12
+ Usage:
13
+ Pass your API key and then your Secret, which the login controller
14
+ will need to authenticate with your shop.
15
+ If you don't have an API key yet, register your application in our
16
+ partner system at http://www.shopify.com/partners
17
+
18
+
19
+ Examples:
20
+ script/generate shopify_app edffbb1bb793e2750686e6f4647a384a abbcee050...
21
+
22
+ This will create a login controller and a home controller and views.
@@ -0,0 +1,50 @@
1
+ require 'rails/generators'
2
+
3
+ class ShopifyAppGenerator < Rails::Generators::Base
4
+ argument :api_key, :type => :string, :required => false
5
+ argument :secret, :type => :string, :required => false
6
+
7
+ class_option :skip_routes, :type => :boolean, :default => false, :desc => 'pass true to skip route generation'
8
+
9
+ def self.source_root
10
+ File.join(File.dirname(__FILE__), 'templates')
11
+ end
12
+
13
+ def copy_files
14
+ directory 'app'
15
+ directory 'public'
16
+ end
17
+
18
+ def remove_static_index
19
+ remove_file 'public/index.html'
20
+ end
21
+
22
+ def add_config_variables
23
+
24
+ api_key_str = api_key.nil? ? "ENV['SHOPIFY_API_KEY']" : api_key.inspect
25
+ api_secret_str = secret.nil? ? "ENV['SHOPIFY_API_SECRET']" : secret.inspect
26
+
27
+ inject_into_file 'config/application.rb', <<-DATA, :after => "class Application < Rails::Application\n"
28
+
29
+ # Shopify API connection credentials:
30
+ config.shopify.api_key = #{api_key_str}
31
+ config.shopify.secret = #{api_secret_str}
32
+ DATA
33
+ end
34
+
35
+ def add_routes
36
+ unless options[:skip_routes]
37
+ route "match 'login/logout' => 'login#logout'"
38
+ route "match 'login/finalize' => 'login#finalize'"
39
+ route "match 'login/authenticate' => 'login#authenticate'"
40
+ route "match 'login' => 'login#index'"
41
+ route "match 'design' => 'home#design'"
42
+ route "match 'welcome' => 'home#welcome'"
43
+ route "root :to => 'home#index'"
44
+ end
45
+ end
46
+
47
+ def display_readme
48
+ readme '../README'
49
+ end
50
+ end
@@ -0,0 +1,18 @@
1
+ class HomeController < ApplicationController
2
+
3
+ around_filter :shopify_session, :except => 'welcome'
4
+
5
+ def welcome
6
+ current_host = "#{request.host}#{':' + request.port.to_s if request.port != 80}"
7
+ @callback_url = "http://#{current_host}/login/finalize"
8
+ end
9
+
10
+ def index
11
+ # get 3 products
12
+ @products = ShopifyAPI::Product.find(:all, :params => {:limit => 3})
13
+
14
+ # get latest 3 orders
15
+ @orders = ShopifyAPI::Order.find(:all, :params => {:limit => 3, :order => "created_at DESC" })
16
+ end
17
+
18
+ end
@@ -0,0 +1,50 @@
1
+ class LoginController < ApplicationController
2
+ def index
3
+ # Ask user for their #{shop}.myshopify.com address
4
+
5
+ # If the #{shop}.myshopify.com address is already provided in the URL, just skip to #authenticate
6
+ if params[:shop].present?
7
+ redirect_to :controller => 'login', :action => "authenticate", :shop => params[:shop]
8
+ end
9
+ end
10
+
11
+ def authenticate
12
+ if params[:shop].present?
13
+ redirect_to ShopifyAPI::Session.new(params[:shop].to_s).create_permission_url
14
+ else
15
+ redirect_to return_address
16
+ end
17
+ end
18
+
19
+ # Shopify redirects the logged-in user back to this action along with
20
+ # the authorization token t.
21
+ #
22
+ # This token is later combined with the developer's shared secret to form
23
+ # the password used to call API methods.
24
+ def finalize
25
+ shopify_session = ShopifyAPI::Session.new(params[:shop], params[:t], params)
26
+ if shopify_session.valid?
27
+ session[:shopify] = shopify_session
28
+ flash[:notice] = "Logged in to shopify store."
29
+
30
+ redirect_to return_address
31
+ session[:return_to] = nil
32
+ else
33
+ flash[:error] = "Could not log in to Shopify store."
34
+ redirect_to :action => 'index'
35
+ end
36
+ end
37
+
38
+ def logout
39
+ session[:shopify] = nil
40
+ flash[:notice] = "Successfully logged out."
41
+
42
+ redirect_to :action => 'index'
43
+ end
44
+
45
+ protected
46
+
47
+ def return_address
48
+ session[:return_to] || root_url
49
+ end
50
+ end
@@ -0,0 +1,10 @@
1
+ module TabsHelper
2
+ # Create a tab as <li> and give it the id "current" if the current action matches that tab
3
+ def tab(name, url, options = {})
4
+ if controller.action_name =~ (options[:highlight] = /#{name}/i)
5
+ content_tag :li, link_to(options[:label] || name.to_s.capitalize, url, {:id => "current"})
6
+ else
7
+ content_tag :li, link_to(options[:label] || name.to_s.capitalize, url)
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,164 @@
1
+ <h1 class="blue">Overview of the styles used</h1>
2
+
3
+ <div class="info">
4
+ <%= image_tag '/images/info.gif', :style => "float:left" %>
5
+ <p>You are free to use this demo application as a base to create new applications that use the Shopify API.</p>
6
+ </div>
7
+
8
+ <table id="style-table">
9
+ <tr>
10
+ <td style="width: 33%">
11
+ <pre><code>&lt;h1&gt;Lorem ipsum&lt;/h1&gt;</code></pre>
12
+ </td>
13
+
14
+ <td style="width: 66%">
15
+ <h1>Lorem ipsum</h1>
16
+ </td>
17
+ </tr>
18
+ <tr>
19
+ <td>
20
+ <pre><code>&lt;h2&gt;Lorem ipsum&lt;/h2&gt;</code></pre>
21
+ </td>
22
+
23
+ <td>
24
+ <h2>Lorem ipsum</h2>
25
+ </td>
26
+ </tr>
27
+ <tr>
28
+ <td>
29
+ <pre><code>&lt;h3&gt;Lorem ipsum&lt;/h3&gt;</code></pre>
30
+ </td>
31
+
32
+ <td>
33
+ <h3>Lorem ipsum</h3>
34
+ </td>
35
+ </tr>
36
+ <tr>
37
+ <td>
38
+ <pre><code>&lt;h4&gt;Lorem ipsum&lt;/h4&gt;</code></pre>
39
+ </td>
40
+
41
+ <td>
42
+ <h4>Lorem ipsum</h4>
43
+ </td>
44
+ </tr>
45
+
46
+ <tr>
47
+ <td>
48
+ <pre><code>&lt;p&gt;&hellip;&lt;/p&gt;</code></pre>
49
+ </td>
50
+
51
+ <td>
52
+ <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
53
+ </td>
54
+ </tr>
55
+
56
+ <tr>
57
+ <td>
58
+ <pre><code>&lt;p class="note"&gt;&hellip;&lt;/p&gt;</code></pre>
59
+ </td>
60
+
61
+ <td>
62
+ <p class="note">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
63
+ </td>
64
+ </tr>
65
+
66
+ <tr>
67
+ <td>
68
+ <pre><code>&lt;span class="highlight"&gt;&hellip;&lt;/span&gt;</code></pre>
69
+ </td>
70
+
71
+ <td>
72
+ <span class="highlight">Lorem ipsum dolor sit amet</p>
73
+ </td>
74
+ </tr>
75
+
76
+ <tr>
77
+ <td>
78
+ <pre><code>&lt;h3 class="blue"&gt;&hellip;&lt;/h3&gt;</code></pre>
79
+ </td>
80
+
81
+ <td>
82
+ <h3 class="blue">Lorem ipsum</h3>
83
+ </td>
84
+ </tr>
85
+ <tr>
86
+ <td>
87
+ <pre><code>&lt;h3 class="green"&gt;&hellip;&lt;/h3&gt;</code></pre>
88
+ </td>
89
+
90
+ <td>
91
+ <h3 class="green">Lorem ipsum</h3>
92
+ </td>
93
+ </tr>
94
+ <tr>
95
+ <td>
96
+ <pre><code>&lt;h3 class="orange"&gt;&hellip;&lt;/h3&gt;</code></pre>
97
+ </td>
98
+
99
+ <td>
100
+ <h3 class="orange">Lorem ipsum</h3>
101
+ </td>
102
+ </tr>
103
+
104
+ <tr>
105
+ <td>
106
+ <pre><code>&lt;p class="blue"&gt;&hellip;&lt;/p&gt;</code></pre>
107
+ </td>
108
+
109
+ <td>
110
+ <p class="blue">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
111
+ </td>
112
+ </tr>
113
+ <tr>
114
+ <td>
115
+ <pre><code>&lt;p class="green"&gt;&hellip;&lt;/p&gt;</code></pre>
116
+ </td>
117
+
118
+ <td>
119
+ <p class="green">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
120
+ </td>
121
+ </tr>
122
+ <tr>
123
+ <td>
124
+ <pre><code>&lt;p class="orange"&gt;&hellip;&lt;/p&gt;</code></pre>
125
+ </td>
126
+
127
+ <td>
128
+ <p class="orange">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
129
+ </td>
130
+ </tr>
131
+
132
+ <tr>
133
+ <td>
134
+ <pre><code>&lt;div class="box"&gt;<br />&nbsp;&nbsp;&lt;div class="wrapper"&gt;&hellip;&lt;/div&gt;<br />&lt;/div&gt;</code></pre>
135
+ </td>
136
+
137
+ <td>
138
+ <div class="box"><div class="wrapper">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</div></div>
139
+ </td>
140
+ </tr>
141
+
142
+ <tr>
143
+ <td>
144
+ <pre><code>&lt;p class="dark"&gt;&hellip;&lt;/p&gt;</code></pre>
145
+ </td>
146
+
147
+ <td>
148
+ <p class="dark">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
149
+ </td>
150
+ </tr>
151
+
152
+ <tr>
153
+ <td>
154
+ <pre><code>&lt;p class="light"&gt;&hellip;&lt;/p&gt;</code></pre>
155
+ </td>
156
+
157
+ <td>
158
+ <p class="light">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
159
+ </td>
160
+ </tr>
161
+
162
+
163
+
164
+ </table>
@@ -0,0 +1,103 @@
1
+ <div id="sidebar">
2
+ <h3>Where to start</h3>
3
+ <h4>Check out the <code style="font-size: 140%">home_controller</code></h4>
4
+
5
+ <p class="description">
6
+ The controller in this demo application fetches the latest 3 orders and products and makes them available as instance variables <code style="color: #218BCE">@orders</code> and <code style="color: #218BCE">@products</code>.
7
+ </p>
8
+
9
+ <h4>Check out the <code>index</code> template</h4>
10
+
11
+ <p class="description">
12
+ This is the Ruby template you are currently looking at. It is located at:<br />
13
+ </p>
14
+
15
+ <p style="background: #fff; margin-left: 4px"><code>views/home/index.html.erb</code></p>
16
+
17
+ <p class="description">
18
+ Have a look at the markup and Ruby code to see how the Shopify API is being used.
19
+ </p>
20
+
21
+ <h3>Additional documentation</h3>
22
+
23
+ <p class="description">
24
+ Become an expert:
25
+ </p>
26
+
27
+ <ul>
28
+ <li>
29
+ <%= link_to 'API documentation', 'http://www.shopify.com/developers/api/' %>
30
+ <span class="note">The reference: what you can do with the Shopify API.</span>
31
+ </li>
32
+ <li>
33
+ <%= link_to 'Wiki', 'http://wiki.shopify.com/' %>
34
+ <span class="note">Get more information and share your knowledge.</span>
35
+ </li>
36
+ <li>
37
+ <%= link_to 'Forum', 'http://forums.shopify.com/community' %>
38
+ <span class="note">Ask questions and see what others already wanted to know.</span>
39
+ </li>
40
+ </ul>
41
+
42
+ <h3>Once you're ready</h3>
43
+
44
+ <p class="description">
45
+ We'd love to see what you create using the Shopify API.
46
+ Find out how to share your application with the world and read the latest information on the <%= link_to 'API Publishing Page', 'http://www.shopify.com/developers/publishing/' %>.
47
+ </p>
48
+ </div>
49
+
50
+
51
+ <div id="orders">
52
+ <h2>Your recent orders</h2>
53
+
54
+ <% if @orders.blank? %>
55
+
56
+ <em class="note">There are no orders in your store.</em>
57
+
58
+ <% else %>
59
+
60
+ <ul>
61
+ <% @orders.each do |order| %>
62
+ <li>
63
+ <div class="order box">
64
+ <div class="wrapper">
65
+ <strong><%= link_to order.name, "http://#{current_shop.url}/admin/orders/#{order.id}" %></strong>
66
+ <span class="price"><%= order.total_price %> <%= order.currency %></span>
67
+ <span class="highlight"><%= order.financial_status %></span>
68
+ by <span class="note"><%= order.billing_address.name %></span>
69
+ </div>
70
+ </div>
71
+ </li>
72
+ <% end %>
73
+ </ul>
74
+
75
+ <% end %>
76
+ </div>
77
+
78
+
79
+ <h2>Some of your products</h2>
80
+
81
+ <% if @products.blank? %>
82
+
83
+ <em class="note">There are no products in your store.</em>
84
+
85
+ <% else %>
86
+
87
+ <% @products.each do |product| %>
88
+ <div class="product box">
89
+ <div class="wrapper">
90
+ <%= image_tag product.images.first.small rescue '' %>
91
+
92
+ <h4><%= link_to product.title, "http://#{current_shop.url}/admin/products/#{product.id}" %></h4>
93
+
94
+ <p class="price"><%= product.price_range %> <%= current_shop.shop.currency %></p>
95
+ <p style="margin-bottom: 0"><%= product.product_type %> <span class="note">type</span></p>
96
+ <p style="margin: 0"><%= product.vendor %> <span class="note">vendor</span></p>
97
+
98
+ <div style="clear:left"></div>
99
+ </div>
100
+ </div>
101
+ <% end %>
102
+
103
+ <% end %>
@@ -0,0 +1,110 @@
1
+ <h1 class="green">Welcome</h1>
2
+
3
+ <p>
4
+ This is an example Shopify application that shows what you can do with the Shopify API.
5
+ </p>
6
+
7
+ <div class="info" style="clear: both">
8
+ This will send the <strong>API-Key</strong> and <strong>Secret</strong> to a shop, and make sure that you have the rights to
9
+ access its private admin data.<br/>
10
+ After authenticating, you will be redirected to the <code>finalize</code> action of your <code>LoginController</code>, which stores the session, and then redirects you to your example dashboard.<br/>
11
+ Your <code>HomeController</code> will get your recent <code>Orders</code> and <code>Articles</code> through the
12
+ Shopify <%= link_to 'REST', 'http://www.xfront.com/REST-Web-Services.html', :title => "Get more information about REST web services in general" %> API and list them with all of your <code>Products</code>.
13
+ You can click on a link of one of your objects and will then be taken to the corresponding admin area of your shop.<br/>
14
+
15
+ <p><strong>Note:</strong> There are no examples for <em>creating or editing</em> objects, but you are also able to do that with the Shopify API!</p>
16
+ </div>
17
+
18
+ <h3>1. Make sure you've entered a valid <em>API-Key</em> and <em>Secret</em></h3>
19
+
20
+ <ul style="list-style-type: lower-alpha;">
21
+ <li>
22
+ <p>
23
+ If you haven't registered your application yet, then enter your shop's <strong>URL</strong> or <strong>subdomain</strong> here:<br/>
24
+ </p>
25
+
26
+ <div class="box grey" style="width: 500px;text-align: center">
27
+ <script type="text/javascript" charset="utf-8">
28
+ function getApiUrl() {
29
+ var name = $('shop').value;
30
+ if (name.indexOf('.') == -1) {
31
+ var api_url = name + '.myshopify.com';
32
+ } else {
33
+ var api_url = name.replace(/^https?:\/\//, ''); // Remove the "http://"
34
+ }
35
+ api_url = api_url.replace(/\/$/, ''); // Trim trailing slashes
36
+ $('api-form').action = 'http://' + api_url + '/admin/api_clients/new';
37
+ }
38
+ </script>
39
+
40
+ <% form_tag '', :method => 'get', :id => 'api-form', :onsubmit => "getApiUrl(); return true;", :style => 'margin-left: 16px;' do %>
41
+ <%= text_field_tag 'shop', '', :size => 40 %>
42
+ <%= hidden_field_tag 'api_client[return_url]', @callback_url %>
43
+ <%= submit_tag 'Get API key' %>
44
+ <% end %>
45
+ </div>
46
+
47
+ <p>
48
+ After registering your application with Shopify, you need to edit the <code>config/shopify.yml</code> file,
49
+ and insert your <em>API-Key</em> and <em>Secret</em> there. Then restart this application.
50
+ </p>
51
+ </li>
52
+ <li>
53
+ <p><strong>If you've already supplied those to the generator</strong>, then move on to <%= link_to 'Step #2', '#callback-step' %>.</p>
54
+ </li>
55
+ </ul>
56
+
57
+ <h3 id="callback-step">2. Make sure your <em>callback URL</em> is correct</h3>
58
+
59
+ The URL should be <code><%= @callback_url %></code>,
60
+ with the host portion of the URL pointing to whichever domain is currently hosting this application. <br/>
61
+ The callback URL of your app can be changed in the API screen of your Shopify admin interface.
62
+
63
+ <h3>3. <%= link_to 'Login', '/login' %> to your shop</h3>
64
+
65
+ <div class="border-wrap">
66
+ <div class="info">
67
+ This will send the <strong>API-Key</strong> and <strong>Secret</strong> to a shop, and make sure that you have the rights to
68
+ access its private admin data.<br/>
69
+ After authenticating, you will be redirected to the <code>finalize</code> action of your <code>LoginController</code>, which stores the session, and then redirects you to your example dashboard.<br/>
70
+ Your <code>HomeController</code> will get your recent <code>Orders</code> and <code>Articles</code> through the
71
+ Shopify <%= link_to 'REST', 'http://www.xfront.com/REST-Web-Services.html', :title => "Get more information about REST web services in general" %> API and list them with all of your <code>Products</code>.
72
+ You can click on a link of one of your objects and will then be taken to the corresponding admin area of your shop.<br/>
73
+
74
+ <p><strong>Note:</strong> There are no examples for <em>creating or editing</em> objects, but you are also able to do that with the Shopify API!</p>
75
+ </div>
76
+ </div>
77
+
78
+ <h3>4. Check out the source code of the <code>home_controller</code> and its <code>index</code> template</h3>
79
+
80
+ <p class="description">
81
+ You can analyze those files to see how the ShopifyAPI is used and get a glimpse of what's possible.
82
+ </p>
83
+
84
+ <h3>5. Read additional documentation</h3>
85
+
86
+ <p class="description">
87
+ Become an expert.
88
+ </p>
89
+
90
+ <ul>
91
+ <li>
92
+ <%= link_to 'API documentation', 'http://www.shopify.com/developers/api' %>
93
+ <span class="hint">(An overview of what you can do with the Shopify API.)
94
+ </li>
95
+ <li>
96
+ <%= link_to 'Wiki (needs its own API section)', 'http://wiki.shopify.com/' %>
97
+ <span class="hint">(Get more information and share your knowledge.)
98
+ </li>
99
+ <li>
100
+ <%= link_to 'Forum (needs its own API section)', 'http://forums.shopify.com/community' %>
101
+ <span class="hint">(Ask questions and see what others already wanted to know.)
102
+ </li>
103
+ </ul>
104
+
105
+ <h3>6. Publish your application</h3>
106
+
107
+ <p class="description">
108
+ This feature is not implemented yet, but it in the future it will allow you to register your application,
109
+ so that will be shown in a public directory with a description, so that more users will take notice of it.
110
+ </p>
@@ -0,0 +1,39 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Shopify Application</title>
5
+ <%= stylesheet_link_tag :all %>
6
+ <%= javascript_include_tag :defaults %>
7
+ <%= csrf_meta_tag %>
8
+ </head>
9
+
10
+ <body>
11
+ <div id="header">
12
+ <h1><%= link_to 'Shopify Demo Application', '/' %></h1>
13
+
14
+ <p id="login-link">
15
+ <% if current_shop %>
16
+ <span class="note">current shop</span> <%= link_to current_shop.url, "http://#{current_shop.url}", :class => 'shop_name' %> <span class="note">|</span>
17
+ <%= link_to 'logout', :controller => "login", :action => 'logout' %>
18
+ <% end %>
19
+ </p>
20
+ </div>
21
+
22
+ <div id="container" class="clearfix">
23
+ <ul id="tabs">
24
+ <%= tab :index, {:controller => 'home'}, :label => 'Home' %>
25
+ <%= tab :design, {:controller => 'home', :action => 'design'}, :label => 'Design Help' %>
26
+ </ul>
27
+
28
+ <!-- Flash error & notice-->
29
+ <% if flash[:error] %> <div id="flasherrors"><%= flash[:error] %></div><% end %>
30
+ <% if flash[:notice] %><div id="flashnotices"><%= flash[:notice] %></div><% end %>
31
+
32
+ <!-- begin div.main-->
33
+ <div id="main">
34
+ <%= yield %>
35
+ </div>
36
+ <!-- end div.main -->
37
+ </div>
38
+ </body>
39
+ </html>
@@ -0,0 +1,15 @@
1
+ <h1>Install</h1>
2
+
3
+ <p>Install this app in a shop to get access to its private admin data.</p>
4
+
5
+ <p style="padding-bottom: 1em"><span class="hint">Don&rsquo;t have a shop to install your app in handy? <a href="https://app.shopify.com/services/partners/api_clients/test_shops">Create a test shop.</a></span></p>
6
+
7
+ <%= form_tag '/login/authenticate' do %>
8
+ <label for='shop'><strong>The URL of the Shop</strong>
9
+ <span class="hint">(or just the subdomain if it&rsquo;s at myshopify.com)</span>
10
+ </label>
11
+ <p>
12
+ <%= text_field_tag 'shop', nil, {:size => 45} %>
13
+ <%= submit_tag 'Install' %>
14
+ </p>
15
+ <% end %>
@@ -0,0 +1,285 @@
1
+ body {
2
+ margin: 0;
3
+ font: 0.8em/1.3em "Lucida Grande", Arial, Arial, sans-serif;
4
+ background: #ededed;
5
+ }
6
+
7
+ h1 { font-weight: normal; font-size: 24px; }
8
+ h1 a { color: #FFFAD5; text-decoration: none; }
9
+ h2 { font-weight: normal; margin-top: 24px; }
10
+ h3 { margin-top: 24px; }
11
+
12
+ #header {
13
+ background: #2d3337 url('../images/shopify-logo.png') 20px 50% no-repeat;
14
+ padding: 25px 25px 25px 70px;
15
+ border-top: 5px solid #1f2326;
16
+ border-bottom: 1px solid #252a2e;
17
+ }
18
+
19
+ #header h1 { color: #fffad5; }
20
+
21
+ #login-link {
22
+ float: right;
23
+ position: relative;
24
+ bottom: 43px;
25
+ right: 15px;
26
+ color: #ededed;
27
+ }
28
+
29
+ #login-link a { color: #ebff7c; }
30
+ #login-link a:hover { text-decoration: underline; }
31
+ #login-link a.shop_name { color: inherit; text-decoration: none; }
32
+ #login-link a.shop_name:hover { text-decoration: underline; }
33
+
34
+ #container {
35
+ width: 90%;
36
+ min-width: 800px;
37
+ margin: 40px auto;
38
+ background: #fff;
39
+ border-right: 1px solid #e5e5e5;
40
+ border-bottom: 1px solid #e5e5e5;
41
+ }
42
+
43
+ #container h1 { margin: 18px 0 27px 0; }
44
+
45
+ #main { padding: 18px; }
46
+
47
+ #tabs {
48
+ margin: 0;
49
+ padding: 0;
50
+ height: 20px;
51
+ position: absolute;
52
+ top: 123px;
53
+ }
54
+
55
+ #tabs li {
56
+ margin: 0;
57
+ padding: 0;
58
+ display: inline;
59
+ list-style-type: none;
60
+ }
61
+
62
+ #tabs a:link, #tabs a:visited {
63
+ float: left;
64
+ padding: 3px 8px ;
65
+ margin: 0 10px 4px 0px;
66
+ text-decoration: none;
67
+ color: #888;
68
+ background: #ddd;
69
+ }
70
+
71
+ #tabs a:link#current, #tabs a:visited#current, #tabs a:hover { color: #000 !important; }
72
+ #tabs a:link#current, #tabs a:visited#current { font-weight: bold; background: #fff; }
73
+
74
+ a { color: #22658b; }
75
+ a:hover { color: #359cd7; }
76
+
77
+ dl { margin: 10px 15px; }
78
+ dt { margin: 10px 0; }
79
+ dd { margin: 5px 0 15px 0; }
80
+ dl input { margin: 0 !important; }
81
+
82
+ code { font-size: 140%; }
83
+
84
+ /* UTILITY CLASSES */
85
+
86
+ .clearfix:after {
87
+ content: ".";
88
+ display: block;
89
+ height: 0;
90
+ clear: both;
91
+ visibility: hidden;
92
+ }
93
+
94
+ .clearfix {display: inline-table;}
95
+
96
+ /* Hides from IE-mac \*/
97
+ * html .clearfix {height: 1%;}
98
+ .clearfix {display: block;}
99
+ /* End hide from IE-mac */
100
+
101
+ .ta-left { text-align: left; }
102
+ .ta-right { text-align: right; }
103
+ .ta-center { text-align: center; }
104
+ .pl { padding-left: 10px !important; }
105
+ .note { color: #777; font-size: 85%; }
106
+ .highlight { background: #ffc; }
107
+
108
+ /*
109
+ * LOGIN / WELCOME
110
+ */
111
+
112
+ #left, #right {
113
+ width: 40%;
114
+ float: left;
115
+ margin: 0 2% 30px 2%;
116
+ }
117
+
118
+ #left { min-width: 390px; }
119
+
120
+ #logout { float: right; margin: 10px; }
121
+ #logout a { color: #330; }
122
+
123
+ /*
124
+ * DASHBOARD
125
+ */
126
+
127
+ .order, .product { width: 55%; }
128
+ .product { margin: 10px; }
129
+
130
+ .product img {
131
+ margin: 0 10px 0 0;
132
+ float: left;
133
+ }
134
+
135
+ .product h4 {
136
+ margin: 0 0 12px 0;
137
+ font-size: 14px;
138
+ }
139
+
140
+ .price {
141
+ color: #666;
142
+ font-size: 15px;
143
+ font-family: Times, "Times New Roman";
144
+ font-style: italic;
145
+ }
146
+
147
+ #orders ul {
148
+ list-style-type: none;
149
+ padding: 0 0 0 7px;
150
+ }
151
+
152
+ #orders li { padding: 3px; }
153
+
154
+ #sidebar {
155
+ float: right;
156
+ width: 280px;
157
+ background: #f5fbfe;
158
+ border-left: 1px solid #D7E4EA;
159
+ color: #003366;
160
+ padding: 0 20px 20px 20px;
161
+ margin-bottom: 18px;
162
+ }
163
+
164
+ #sidebar ul {
165
+ padding-left: 20px;
166
+ list-style-type: square;
167
+ }
168
+
169
+ #sidebar li { margin: 8px 0; }
170
+
171
+ /* STYLE OVERVIEW */
172
+
173
+ #style-table { margin: 20px 0; }
174
+ #style-table td * { margin: 0; }
175
+ #style-table td { padding: 10px; border-bottom: 1px dotted #e5e5e5; }
176
+ #style-table td:first-child {
177
+ background:#Fefefe url('../images/box-bg2.gif') repeat-x scroll left bottom;
178
+ }
179
+ /* Flash */
180
+
181
+ #flasherrors, #flashnotices {
182
+ background: #faf7ea;
183
+ border-bottom: 1px solid #e8e6d9;
184
+ padding: 10px;
185
+ font-weight: bold;
186
+ text-align:center;
187
+ }
188
+
189
+ #flasherrors { color: #6e290b; }
190
+ #flashnotices { color: #549d19; }
191
+
192
+ /* CLASSES */
193
+
194
+ .description {
195
+ margin: 0px 0px 0px 4px;
196
+ font-weight: normal;
197
+ }
198
+
199
+ .box {
200
+ padding: 0;
201
+ background:#FAFAFA url('../images/box-bg2.gif') repeat-x scroll left top;
202
+ border:1px solid #CCCCCC;
203
+ }
204
+
205
+ .wrapper {
206
+ border:1px solid #FFFFFF;
207
+ padding: 10px;
208
+ }
209
+
210
+ .info {
211
+ padding: 0;
212
+ margin: 8px auto;
213
+ background: #009ad6 url('../images/info-bg.gif') top left repeat-x;
214
+ border: 1px solid #61abda;
215
+ font: 1.2em/1.7em "Comic Sans MS";
216
+ color: #fff;
217
+ height: 85px;
218
+ }
219
+
220
+ .info code {
221
+ font-size: 14px;
222
+ background: none;
223
+ }
224
+
225
+ .info a { color: #fff; }
226
+ .info a:hover { color: #dcfaff; }
227
+
228
+ .grey {
229
+ background: #eee;
230
+ border: 1px solid #ccc;
231
+ }
232
+
233
+ .green, .orange, .blue { padding: 10px; }
234
+ h1.green, h2.green, h3.green, h1.orange, h2.orange, h3.orange, h1.blue, h2.blue, h3.blue { padding: 0; }
235
+
236
+ .green {
237
+ background: #61b41e;
238
+ border: 1px solid #60b31d;
239
+ color: #ddecd0;
240
+ }
241
+
242
+ h1.green, h2.green, h3.green {
243
+ color: #6ece21;
244
+ background: none;
245
+ border: none;
246
+ }
247
+
248
+ .orange {
249
+ background: #ce6e21;
250
+ border: 1px solid #bc641e;
251
+ color: #fce0ca;
252
+ padding: 10px;
253
+ }
254
+
255
+ h1.orange, h2.orange, h3.orange {
256
+ color: #ce6e21;
257
+ background: none;
258
+ border: none;
259
+ }
260
+
261
+ .blue {
262
+ background: #218bce;
263
+ border: 1px solid #1e80be;
264
+ color: #d9ecf8;
265
+ padding: 10px;
266
+ }
267
+
268
+ h1.blue, h2.blue, h3.blue {
269
+ color: #218bce;
270
+ background: none;
271
+ border: none;
272
+ }
273
+
274
+ .light {
275
+ background: #faf7ea;
276
+ border: 1px solid #e8e6d9;
277
+ padding: 18px;
278
+ }
279
+
280
+ .dark {
281
+ background: #333;
282
+ border: 1px solid #000;
283
+ color: #fff;
284
+ padding: 10px;
285
+ }
@@ -0,0 +1,17 @@
1
+ require 'shopify_api'
2
+
3
+ module ShopifyApp
4
+
5
+ def self.configuration
6
+ @configuration ||= ShopifyApp::Configuration.new
7
+ end
8
+
9
+ def self.setup_session
10
+ ShopifyAPI::Session.setup(:api_key => ShopifyApp.configuration.api_key, :secret => ShopifyApp.configuration.secret)
11
+ end
12
+ end
13
+
14
+ require 'shopify_app/login_protection'
15
+ require 'shopify_app/configuration'
16
+ require 'shopify_app/railtie'
17
+ require 'shopify_app/version'
@@ -0,0 +1,6 @@
1
+ class ShopifyApp::Configuration
2
+
3
+ attr_accessor :api_key
4
+
5
+ attr_accessor :secret
6
+ end
@@ -0,0 +1,21 @@
1
+ module ShopifyApp::LoginProtection
2
+
3
+ def shopify_session
4
+ if session[:shopify]
5
+ begin
6
+ # session[:shopify] set in LoginController#finalize
7
+ ShopifyAPI::Base.site = session[:shopify].site
8
+ yield
9
+ ensure
10
+ ShopifyAPI::Base.site = nil
11
+ end
12
+ else
13
+ session[:return_to] = request.fullpath
14
+ redirect_to :controller => 'login'
15
+ end
16
+ end
17
+
18
+ def current_shop
19
+ session[:shopify]
20
+ end
21
+ end
@@ -0,0 +1,17 @@
1
+ require 'rails'
2
+
3
+ class ShopifyApp::Railtie < ::Rails::Railtie
4
+
5
+ config.before_configuration do
6
+ config.shopify = ShopifyApp.configuration
7
+ end
8
+
9
+ initializer "shopify_app.action_controller_integration" do
10
+ ActionController::Base.send :include, ShopifyApp::LoginProtection
11
+ ActionController::Base.send :helper_method, :current_shop
12
+ end
13
+
14
+ initializer "shopify_app.setup_session" do
15
+ ShopifyApp.setup_session
16
+ end
17
+ end
@@ -0,0 +1,3 @@
1
+ module ShopifyApp
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "shopify_app/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "shopify_app"
7
+ s.version = ShopifyApp::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.author = "Shopify"
10
+ s.email = ["edward@shopify.com", "jonathan@shopify.com", "willem@shopify.com"]
11
+ s.homepage = "http://www.shopify.com/developers"
12
+ s.summary = %q{This gem is used to get quickly started with the Shopify API}
13
+ s.description = %q{Creates a basic login controller for authenticating with your Shop and also a product controller which lets your edit your products easily.}
14
+
15
+ s.rubyforge_project = "shopify-api"
16
+
17
+ s.add_runtime_dependency('rails', '~> 3')
18
+ s.add_runtime_dependency('shopify_api')
19
+
20
+ s.add_development_dependency('rake')
21
+
22
+ s.files = `git ls-files`.split("\n")
23
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
24
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
25
+ s.require_paths = ["lib"]
26
+ end
metadata ADDED
@@ -0,0 +1,134 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: shopify_app
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - Shopify
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-02-26 00:00:00 -05:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: rails
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ~>
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 3
30
+ version: "3"
31
+ type: :runtime
32
+ version_requirements: *id001
33
+ - !ruby/object:Gem::Dependency
34
+ name: shopify_api
35
+ prerelease: false
36
+ requirement: &id002 !ruby/object:Gem::Requirement
37
+ none: false
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ segments:
42
+ - 0
43
+ version: "0"
44
+ type: :runtime
45
+ version_requirements: *id002
46
+ - !ruby/object:Gem::Dependency
47
+ name: rake
48
+ prerelease: false
49
+ requirement: &id003 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ segments:
55
+ - 0
56
+ version: "0"
57
+ type: :development
58
+ version_requirements: *id003
59
+ description: Creates a basic login controller for authenticating with your Shop and also a product controller which lets your edit your products easily.
60
+ email:
61
+ - edward@shopify.com
62
+ - jonathan@shopify.com
63
+ - willem@shopify.com
64
+ executables: []
65
+
66
+ extensions: []
67
+
68
+ extra_rdoc_files: []
69
+
70
+ files:
71
+ - .gitignore
72
+ - CHANGELOG
73
+ - Gemfile
74
+ - README.rdoc
75
+ - Rakefile
76
+ - install.rb
77
+ - lib/generators/shopify_app/README
78
+ - lib/generators/shopify_app/USAGE
79
+ - lib/generators/shopify_app/shopify_app_generator.rb
80
+ - lib/generators/shopify_app/templates/app/controllers/home_controller.rb
81
+ - lib/generators/shopify_app/templates/app/controllers/login_controller.rb
82
+ - lib/generators/shopify_app/templates/app/helpers/home_helper.rb
83
+ - lib/generators/shopify_app/templates/app/helpers/login_helper.rb
84
+ - lib/generators/shopify_app/templates/app/helpers/tabs_helper.rb
85
+ - lib/generators/shopify_app/templates/app/views/home/design.html.erb
86
+ - lib/generators/shopify_app/templates/app/views/home/index.html.erb
87
+ - lib/generators/shopify_app/templates/app/views/home/welcome.html.erb
88
+ - lib/generators/shopify_app/templates/app/views/layouts/application.html.erb
89
+ - lib/generators/shopify_app/templates/app/views/login/index.html.erb
90
+ - lib/generators/shopify_app/templates/public/images/box-bg2.gif
91
+ - lib/generators/shopify_app/templates/public/images/info-bg.gif
92
+ - lib/generators/shopify_app/templates/public/images/info.gif
93
+ - lib/generators/shopify_app/templates/public/images/shopify-logo.png
94
+ - lib/generators/shopify_app/templates/public/stylesheets/application.css
95
+ - lib/shopify_app.rb
96
+ - lib/shopify_app/configuration.rb
97
+ - lib/shopify_app/login_protection.rb
98
+ - lib/shopify_app/railtie.rb
99
+ - lib/shopify_app/version.rb
100
+ - shopify_app.gemspec
101
+ has_rdoc: true
102
+ homepage: http://www.shopify.com/developers
103
+ licenses: []
104
+
105
+ post_install_message:
106
+ rdoc_options: []
107
+
108
+ require_paths:
109
+ - lib
110
+ required_ruby_version: !ruby/object:Gem::Requirement
111
+ none: false
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ segments:
116
+ - 0
117
+ version: "0"
118
+ required_rubygems_version: !ruby/object:Gem::Requirement
119
+ none: false
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ segments:
124
+ - 0
125
+ version: "0"
126
+ requirements: []
127
+
128
+ rubyforge_project: shopify-api
129
+ rubygems_version: 1.3.7
130
+ signing_key:
131
+ specification_version: 3
132
+ summary: This gem is used to get quickly started with the Shopify API
133
+ test_files: []
134
+