Initial Commit

This commit is contained in:
Jarred Sumner
2012-10-11 12:30:08 -07:00
parent 275e4d8352
commit 4b169b02fb
114 changed files with 2274 additions and 18 deletions

31
.gitignore vendored
View File

@@ -1,16 +1,19 @@
*.rbc
*.sassc
.sass-cache
capybara-*.html
.rspec
# See http://help.github.com/ignore-files/ for more about ignoring files.
#
# If you find yourself ignoring temporary files generated by your text editor
# or operating system, you probably want to add a global ignore instead:
# git config --global core.excludesfile ~/.gitignore_global
# Ignore bundler config
/.bundle
/vendor/bundle
/log/*
/tmp/*
# Ignore the default SQLite database.
/db/*.sqlite3
/public/system/*
/coverage/
/spec/tmp/*
**.orig
rerun.txt
pickle-email-*.html
# Ignore all logfiles and tempfiles.
/log/*.log
/tmp
config/settings.local.yml
config/settings/*.local.yml
config/environments/*.local.yml

30
Gemfile Normal file
View File

@@ -0,0 +1,30 @@
source 'https://rubygems.org'
gem 'rails', '3.2.8'
group :development do
gem 'sqlite3'
end
group :production do
gem 'thin'
gem 'pg'
end
# Gems used only for assets and not required
# in production environments by default.
group :assets do
gem 'sass-rails', '~> 3.2.3'
gem 'coffee-rails', '~> 3.2.1'
gem 'therubyracer', :platforms => :ruby
gem 'uglifier', '>= 1.0.3'
end
# jQuery
gem 'jquery-rails'
# Kickstarter's awesome Amazon Flexible Payments gem
gem 'amazon_flex_pay'
# Configuration File
gem 'rails_config'

138
Gemfile.lock Normal file
View File

@@ -0,0 +1,138 @@
GEM
remote: https://rubygems.org/
specs:
actionmailer (3.2.8)
actionpack (= 3.2.8)
mail (~> 2.4.4)
actionpack (3.2.8)
activemodel (= 3.2.8)
activesupport (= 3.2.8)
builder (~> 3.0.0)
erubis (~> 2.7.0)
journey (~> 1.0.4)
rack (~> 1.4.0)
rack-cache (~> 1.2)
rack-test (~> 0.6.1)
sprockets (~> 2.1.3)
activemodel (3.2.8)
activesupport (= 3.2.8)
builder (~> 3.0.0)
activerecord (3.2.8)
activemodel (= 3.2.8)
activesupport (= 3.2.8)
arel (~> 3.0.2)
tzinfo (~> 0.3.29)
activeresource (3.2.8)
activemodel (= 3.2.8)
activesupport (= 3.2.8)
activesupport (3.2.8)
i18n (~> 0.6)
multi_json (~> 1.0)
amazon_flex_pay (0.9.13)
activesupport (>= 3.0.14)
multi_xml (~> 0.2.0)
rest-client (~> 1.6.1)
arel (3.0.2)
builder (3.0.3)
coffee-rails (3.2.2)
coffee-script (>= 2.2.0)
railties (~> 3.2.0)
coffee-script (2.2.0)
coffee-script-source
execjs
coffee-script-source (1.3.3)
daemons (1.1.9)
erubis (2.7.0)
eventmachine (1.0.0)
execjs (1.4.0)
multi_json (~> 1.0)
foreman (0.60.2)
thor (>= 0.13.6)
hike (1.2.1)
i18n (0.6.1)
journey (1.0.4)
jquery-rails (2.1.3)
railties (>= 3.1.0, < 5.0)
thor (~> 0.14)
json (1.7.5)
libv8 (3.3.10.4)
mail (2.4.4)
i18n (>= 0.4.0)
mime-types (~> 1.16)
treetop (~> 1.4.8)
mime-types (1.19)
multi_json (1.3.6)
multi_xml (0.2.2)
pg (0.14.1)
polyglot (0.3.3)
rack (1.4.1)
rack-cache (1.2)
rack (>= 0.4)
rack-ssl (1.3.2)
rack
rack-test (0.6.2)
rack (>= 1.0)
rails (3.2.8)
actionmailer (= 3.2.8)
actionpack (= 3.2.8)
activerecord (= 3.2.8)
activeresource (= 3.2.8)
activesupport (= 3.2.8)
bundler (~> 1.0)
railties (= 3.2.8)
rails_config (0.3.1)
activesupport (>= 3.0)
railties (3.2.8)
actionpack (= 3.2.8)
activesupport (= 3.2.8)
rack-ssl (~> 1.3.2)
rake (>= 0.8.7)
rdoc (~> 3.4)
thor (>= 0.14.6, < 2.0)
rake (0.9.2.2)
rdoc (3.12)
json (~> 1.4)
rest-client (1.6.7)
mime-types (>= 1.16)
sass (3.2.1)
sass-rails (3.2.5)
railties (~> 3.2.0)
sass (>= 3.1.10)
tilt (~> 1.3)
sprockets (2.1.3)
hike (~> 1.2)
rack (~> 1.0)
tilt (~> 1.1, != 1.3.0)
sqlite3 (1.3.6)
therubyracer (0.10.2)
libv8 (~> 3.3.10)
thin (1.5.0)
daemons (>= 1.0.9)
eventmachine (>= 0.12.6)
rack (>= 1.0.0)
thor (0.16.0)
tilt (1.3.3)
treetop (1.4.10)
polyglot
polyglot (>= 0.3.1)
tzinfo (0.3.33)
uglifier (1.3.0)
execjs (>= 0.3.0)
multi_json (~> 1.0, >= 1.0.2)
PLATFORMS
ruby
DEPENDENCIES
amazon_flex_pay
coffee-rails (~> 3.2.1)
foreman
jquery-rails
pg
rails (= 3.2.8)
rails_config
sass-rails (~> 3.2.3)
sqlite3
therubyracer
thin
uglifier (>= 1.0.3)

1
Procfile Normal file
View File

@@ -0,0 +1 @@
web: bundle exec rails server thin -p $PORT -e $RACK_ENV

View File

@@ -1,4 +0,0 @@
selfstarter
===========
Roll your own crowdfunding

66
README.rdoc Normal file
View File

@@ -0,0 +1,66 @@
# Selfstarter
Selfstarter makes it easy to roll your own crowdfunding site. To get started, fork this repository and change around ```config/settings.yml``` to suit your needs.
## Background
[Kickstarter rejected us](http://techcrunch.com/2012/10/07/the-story-of-lockitron-crowdfunding-without-kickstarter/), so we made our own crowdfunding for [Lockitron](https://lockitron.com). Feel free to [give us feedback](mailto:hello@lockitron.com)!
Over the past week, a lot of people asked us for help with building their own crowdfunding app. This is it.
Selfstarter is starting point. We made some specific choices with Selfstarter for Lockitron and we recommend you tailor it for your project:
* We use Amazon Payments for payments. You can use Stripe or WePay. We used Kickstarter's awesome ```amazon_flex_pay``` gem.
* We collect multi-use tokens from customers with Amazon Payments - this let's us collect payment information without charging the customer until we are ready to ship
* Selfstarter doesn't come with any authentication, administration, mailers or analytics tools. We recommend adding a basic set of these so that you can message backers and manage orders.
## Getting Started
First you'll need to fork and clone this repo
Let's get all our dependencies setup:
```bash
bundle install --without production
```
Now let's create the database:
```bash
rake db:migrate
```
Let's get it running:
```bash
rails s
```
### Customizing
While it is *just* a skeleton, we did make it a little quicker to change around things like your product name, the colors, pricing, etc.
To change around the product name, tweet text, and more, open this file:
```
config/settings.yml
```
To change around the colors and fonts, open this file:
```
app/assets/stylesheets/variables.css.scss
```
To dive into the code, open this file:
```
app/controllers/preorder_controller.rb
```
### Deploying to Production
We recommend using Heroku, and we even include a ```Procfile``` for you. All you need to do is run:
```bash
gem install heroku
heroku create
git push heroku master
heroku run rake db:migrate
```

7
Rakefile Normal file
View File

@@ -0,0 +1,7 @@
#!/usr/bin/env rake
# Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
require File.expand_path('../config/application', __FILE__)
Selfstarter::Application.load_tasks

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 B

BIN
app/assets/images/rails.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

View File

@@ -0,0 +1,19 @@
// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// the compiled file.
//
// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
// GO AFTER THE REQUIRES BELOW.
//
//= require jquery
//= require jquery_ujs
//= require jquery-ui
//= require jquery.details
//= require jquery.textchange
//= require preorder
//= require_tree .

View File

@@ -0,0 +1,6 @@
(function(b){var d="open"in document.createElement("details"),e;b.fn.details=function(a){"open"===a&&(d?this.prop("open",!0):this.trigger("open"));"close"===a&&(d?this.prop("open",!1):this.trigger("close"));"init"===a&&e(b(this));if(!a){if(!d)return this.hasClass("open");var c=!1;this.each(function(){if(this.open)return c=!0,!1});return c}};e=function(a){a=a.not(".details-inited").addClass("details-inited");a.filter(".animated").each(function(){var a=b(this),d=a.children("summary").remove(),e=b("<div>").addClass("details-wrapper").append(a.children());
a.append(e).prepend(d)});d||(a.each(function(){var a=b(this);a.children("summary").length||a.prepend("<summary>Details</summary>")}).children("summary").filter(":not(tabindex)").attr("tabindex",0).end().end().contents(":not(summary)").filter(function(){return 3===this.nodeType&&/[^\t\n\r ]/.test(this.data)}).wrap("<span>").end().end().filter(":not([open])").prop("open",!1).end().filter("[open]").addClass("open").prop("open",!0).end(),b.browser.msie&&9>b.browser.msie&&a.filter(":not(.open)").children().not("summary").hide())};
b(function(){b("body").on("open.details","details.animated",function(){var a=b(this),c=a.children(".details-wrapper");c.hide();setTimeout(function(){c.slideDown(a.data("animation-speed"))},0)}).on("close.details","details.animated",function(){var a=b(this),c=a.children(".details-wrapper");setTimeout(function(){a.prop("open",!0).addClass("open");c.slideUp(a.data("animation-speed"),function(){a.prop("open",!1).removeClass("open")})},0)});if(d)b("body").on("click","summary",function(){var a=b(this).parent();
a.prop("open")?a.trigger("close"):a.trigger("open")});else if(b("html").addClass("no-details"),b("head").prepend('<style>details{display:block}summary{cursor:pointer}details>summary::before{content:"\u25ba"}details.open>summary::before{content:"\u25bc"}details:not(.open)>:not(summary){display:none}</style>'),b("body").on("open.details","details",function(a){b(this).addClass("open").trigger("change.details");a.stopPropagation()}).on("close.details","details",function(a){b(this).removeClass("open").trigger("change.details");
a.stopPropagation()}).on("toggle.details","details",function(a){var c=b(this);c.hasClass("open")?c.trigger("close"):c.trigger("open");a.stopPropagation()}).on("click","summary",function(){b(this).parent().trigger("toggle")}).on("keyup","summary",function(a){(32===a.keyCode||13===a.keyCode&&!b.browser.opera)&&b(this).parent().trigger("toggle")}),b.browser.msie&&9>b.browser.msie)b("body").on("open.details","details",function(){b(this).children().not("summary").show()}).on("close.details","details",
function(){b(this).children().not("summary").hide()});e(b("details"))})})(jQuery);

View File

@@ -0,0 +1,10 @@
/*!
* jQuery TextChange Plugin
* http://www.zurb.com/playground/jquery-text-change-custom-event
*
* Copyright 2010, ZURB
* Released under the MIT License
*/
(function(a){a.event.special.textchange={setup:function(){a(this).data("lastValue",this.contentEditable==="true"?a(this).html():a(this).val());a(this).bind("keyup.textchange",a.event.special.textchange.handler);a(this).bind("cut.textchange paste.textchange input.textchange",a.event.special.textchange.delayedHandler)},teardown:function(){a(this).unbind(".textchange")},handler:function(){a.event.special.textchange.triggerIfChanged(a(this))},delayedHandler:function(){var c=a(this);setTimeout(function(){a.event.special.textchange.triggerIfChanged(c)},
25)},triggerIfChanged:function(a){var b=a[0].contentEditable==="true"?a.html():a.val();b!==a.data("lastValue")&&(a.trigger("textchange",[a.data("lastValue")]),a.data("lastValue",b))}};a.event.special.hastext={setup:function(){a(this).bind("textchange",a.event.special.hastext.handler)},teardown:function(){a(this).unbind("textchange",a.event.special.hastext.handler)},handler:function(c,b){b===""&&b!==a(this).val()&&a(this).trigger("hastext")}};a.event.special.notext={setup:function(){a(this).bind("textchange",
a.event.special.notext.handler)},teardown:function(){a(this).unbind("textchange",a.event.special.notext.handler)},handler:function(c,b){a(this).val()===""&&a(this).val()!==b&&a(this).trigger("notext")}}})(jQuery);

View File

@@ -0,0 +1,28 @@
Selfstarter =
firstTime: true
validateEmail: ->
# The regex we use for validating email
# It probably should be a parser, but there isn't enough time for that (Maybe in the future though!)
if /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/.test($("#email").val())
$("#email").removeClass("highlight")
$("#amazon_button").removeClass("disabled")
else
$("#email").addClass("highlight") unless Selfstarter.firstTime
$("#amazon_button").addClass("disabled") unless $("#amazon_button").hasClass("disabled")
init: ->
$("#email").bind "textchange", ->
Selfstarter.validateEmail()
$("#email").bind "hastext", ->
Selfstarter.validateEmail()
# The first time they type in their email, we don't want it to throw a validation error
$("#email").change ->
Selfstarter.firstTime = false
$ ->
Selfstarter.init()
$("#email").focus()

View File

@@ -0,0 +1,14 @@
/*
* This is a manifest file that'll be compiled into application.css, which will include all the files
* listed below.
*
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
* or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
*
* You're free to add application-wide styles to this file and they'll appear at the top of the
* compiled file, but it's generally better to create a new file per style scope.
*
*= require_self
*= require reset
*= require main
*/

View File

@@ -0,0 +1,48 @@
.main_content
{
width: 560px;
float: left;
h3
{
margin-bottom: 30px;
color: #4b4b4b;
line-height: 1;
}
p
{
line-height: 1.5;
}
#checkout
{
#email
{
padding: 15px;
border-radius: 10px;
border: 1px solid #CCC;
width: 350px;
outline: none;
}
.invalid
{
border: 1px solid orange;
}
#amazon_button
{
margin-top: 5px;
padding: 15px;
border: none;
}
}
}
.sidebar
{
float: right;
width: 300px;
p
{
font-size: 18px;
margin-bottom: 30px;
line-height: 1.3;
}
}

View File

@@ -0,0 +1,23 @@
.footer
{
padding: 40px 0;
ul
{
float: left;
}
li
{
margin-bottom: 10px;
}
a
{
font-size: 18px;
color: #525252;
font-family: $primary_font, $secondary_font, $tertiary_font;
}
p
{
float: right;
font-size: 18px;
}
}

View File

@@ -0,0 +1,19 @@
#lockitron_header
{
border: none;
a
{
border: none !important;
font-size: inherit !important;
}
}
#header
{
width: 100%;
padding: 26px 0;
-moz-box-shadow: 0px 1px 3px 0px #acacac;
-webkit-box-shadow: 0px 1px 3px 0px #acacac;
box-shadow: 0px 1px 3px 0px #acacac;
background: #fcfcfc;
position: relative;
}

View File

@@ -0,0 +1,33 @@
@import "homepage/stats";
@import "homepage/call_to_action";
@import "homepage/key_points";
@import "homepage/other_points";
@import "homepage/press";
@import "homepage/faq";
#tweet_button
{
margin-top: 5px;
}
.fb-like
{
margin-left: 5px;
float:left;
}
#video
{
float: left;
width: 512px;
height: 385px;
background: #fff;
-moz-box-shadow: 0 2px 6px rgba(0,0,0,.39); /* drop shadow */
-webkit-box-shadow: 0 2px 6px rgba(0,0,0,.39); /* drop shadow */
box-shadow: 0 2px 6px rgba(0,0,0,.39); /* drop shadow */
img:hover
{
opacity: 0.5;
cursor: pointer;
}
}

View File

@@ -0,0 +1,56 @@
#reserve_container
{
float: left;
padding-top: 20px;
border-top: 1px solid #fff;
-moz-box-shadow: 0 -1px 0 #cbcbcb; /* drop shadow */
-webkit-box-shadow: 0 -1px 0 #cbcbcb; /* drop shadow */
box-shadow: 0 -1px 0 #cbcbcb; /* drop shadow */
margin-top: 30px;
text-align: center;
p
{
color: #8b8a8a;
font-size: 18px;
line-height: 1.4;
}
#ship_date
{
color: #4c4c4c;
font-size: 22px;
font-family: $primary_font, $secondary_font, $tertiary_font;
line-height: 1.3;
display: block;
margin: 0 auto;
width: 300px;
}
#price
{
color: #4c4c4c;
font-size: 22px;
font-family: $primary_font, $secondary_font, $tertiary_font;
line-height: 1.3;
display: block;
margin: 0 auto 10px auto;
width: 300px;
}
}
.reserve
{
margin: 0 auto;
margin-top: 20px;
margin-bottom: 20px;
padding: 20px 0;
width: 274px;
font-size: 32px;
}
#middle_reserve
{
padding: 60px;
h2
{
margin-bottom: 26px;
}
}

View File

@@ -0,0 +1,21 @@
#faqs {
padding-bottom: 30px;
border-bottom: 1px solid #dfdfdf;
ul {
margin-top: 50px;
float: left;
width: 50%;
li
{
width: 400px;
margin: 0 49px 30px 0;
padding-left: 18px;
background: url(image_path("bullet.png")) no-repeat left 8px;
p {
margin-top: 10px;
line-height: 1.4;
font-size: 18px;
}
}
}
}

View File

@@ -0,0 +1,50 @@
.big_wrapper {
border-bottom: 1px solid #d2d2d2;
background: #fff;
}
.big_wrapper .wrapper {
padding: 35px 0;
}
.point_copy {
width: 440px;
h3 {
margin: 20px 0 30px 0;
}
}
h3 {
font-size: 42px;
font-family: $primary_font, $secondary_font, $tertiary_font;
color: #292929;
line-height: 1.3;
}
.point_copy p, #other_points li p {
line-height: 1.5;
}
#one {
background: url(image_path("1-background.png")) no-repeat bottom left;
height: 320px;
width: 936px;
}
#two {
background: url(image_path("2-background.png")) no-repeat bottom left;
height: 320px;
}
#three {
background: url(image_path("3-background.png")) no-repeat bottom left;
height: 320px;
}
#four {
background: url(image_path("4-background.png")) no-repeat bottom left;
height: 320px;
}
.right {
margin-left: 500px;
}

View File

@@ -0,0 +1,28 @@
#other_points
{
li
{
width: 400px;
float: left;
margin: 0 120px 50px 0;
padding-top: 60px;
}
#section-1 {
background: url(asset-path("", "images")) no-repeat center top;
}
#section-2 {
background: url(asset-path("", "images")) no-repeat center top;
margin-right: 0px;
}
#section-3 {
background: url(asset-path("", "images")) no-repeat center top;
}
#section-4 {
background: url(asset-path("", "images")) no-repeat center top;
margin-right: 0px;
}
h4 {
width: 400px;
text-align: center;
}
}

View File

@@ -0,0 +1,47 @@
#logos {
padding: 40px 0;
background: #f3f3f3;
-moz-box-shadow: 0px 1px 3px 0px #acacac;
-webkit-box-shadow: 0px 1px 3px 0px #acacac;
box-shadow: 0px 1px 3px 0px #acacac;
li
{
float: left;
margin: 0 16px;
a {
display: block;
height: 48px;
opacity: 0.2;
text-indent: -10000px;
}
a:hover {
opacity: 1;
}
}
#awesomeblog a
{
background: url(image-path("")) no-repeat left center;
width: 176px;
}
#coolpaper a
{
background: url(image-path("")) no-repeat left center;
width: 109px;
}
#nicemag a
{
background: url(image-path("")) no-repeat left center;
width: 149px;
}
#readcrunch a
{
background: url(image-path("")) no-repeat left center;
width: 81px;
}
}

View File

@@ -0,0 +1,96 @@
#backing
{
float: left;
width: 383px;
margin: 20px 0 0 40px;
#backers
{
border-left: none;
padding-left: 0;
ul
{
float: left;
}
}
#days {
border-right: none;
padding-right: 0;
}
ul {
text-align: center;
}
.stats
{
margin: 0 auto;
color: #3f3f3f;
font-size: 24px;
display: block;
display: inline-block;
font-family: $primary_font, $secondary_font, $tertiary_font;
border-right: 1px solid #cbcbcb;
padding-right: 26px;
padding-left: 26px;
text-align: left;
span
{
color: #868686;
font-size: 18px;
margin-top: 5px;
display: block;
font-family: $primary_font, $secondary_font, $tertiary_font;
}
}
}
#progress_bg
{
margin-top: 20px;
float: left;
height: 40px;
-moz-box-shadow: 0 1px 1px rgba(0,0,0,.41); /* drop shadow */
-webkit-box-shadow: 0 1px 1px rgba(0,0,0,.41); /* drop shadow */
box-shadow: 0 1px 1px rgba(0,0,0,.41); /* drop shadow */
-webkit-border-radius: 30px;
-moz-border-radius: 30px;
border-radius: 30px;
width: 383px;
background: #dbdbdb;
#progress
{
height: 40px;
-moz-box-shadow: 0 1px 1px rgba(0,0,0,.59); /* drop shadow */
-webkit-box-shadow: 0 1px 1px rgba(0,0,0,.59); /* drop shadow */
box-shadow: 0 1px 1px rgba(0,0,0,.59); /* drop shadow */
background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+PGxpbmVhckdyYWRpZW50IGlkPSJoYXQwIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjUwJSIgeTE9IjEwMCUiIHgyPSI1MCUiIHkyPSIwJSI+CjxzdG9wIG9mZnNldD0iMCUiIHN0b3AtY29sb3I9IiMxMzkyZGMiIHN0b3Atb3BhY2l0eT0iMSIvPgo8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiMwNjlkZjQiIHN0b3Atb3BhY2l0eT0iMSIvPgogICA8L2xpbmVhckdyYWRpZW50PgoKPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNoYXQwKSIgLz4KPC9zdmc+); /* gradient fill */
background-image: -moz-linear-gradient(90deg, #1392dc 0%, #069df4 100%); /* gradient fill */
background-image: -o-linear-gradient(90deg, #1392dc 0%, #069df4 100%); /* gradient fill */
background-image: -webkit-linear-gradient(90deg, #1392dc 0%, #069df4 100%); /* gradient fill */
background-image: linear-gradient(90deg, #1392dc 0%, #069df4 100%); /* gradient fill */
-webkit-border-radius: 30px;
-moz-border-radius: 30px;
border-radius: 30px;
min-width: 2%;
width: 100%;
max-width: 100%;
display: inline-block;
}
#progress_text
{
margin: 0 auto;
width: 100%;
font-size: 14pt;
display: inline-block;
color: white;
text-shadow: 0 -1px 1px rgba(0, 0, 0, 0.37);
text-align: center;
position: relative;
top: -35px;
}
}
.small
{
height: 20px !important;
#progress
{
height: 20px !important;
}
}

View File

@@ -0,0 +1,8 @@
@import "variables";
@import "primitives";
@import "header";
@import "footer";
@import "homepage";
@import "share";
@import "checkout";

View File

View File

@@ -0,0 +1,232 @@
/* For modern browsers */
.clearfix:before,
.clearfix:after
{
content:"";
display:table;
}
.clearfix:after
{
clear:both;
}
/* For IE 6/7 (trigger hasLayout) */
.clearfix {
zoom:1;
}
code
{
border: 1px solid #CCC;
padding: 1px;
vertical-align: middle;
font-family: "Consolas", "Inconsolata", "Meslo", "Inconsolata-dz", monospace;
text-shadow: none;
font-size: 10pt;
}
html, body {
width: 100%;
}
body {
background: $body_background;
}
.disabled
{
opacity: 0.65;
pointer-events: none;
}
form
{
margin-top: 15px;
}
body, input, textarea
{
font-size: $font_size;
font-family: $primary_font, $secondary_font, $tertiary_font;
color: $text_color;
text-shadow: $text_shadow;
-webkit-font-smoothing: antialiased;
}
a
{
text-decoration: none;
color: $link_color;
}
a:hover
{
text-decoration: underline;
}
i
{
font-style: italic;
}
// Used in the FAQ
details, summary
{
outline: none;
}
summary
{
text-decoration: none;
color: $summary_color;
user-select: none;
-webkit-user-select: none;
-moz-user-select: none;
font-size: 20px;
line-height: 1.3;
}
summary:hover
{
text-decoration: underline;
cursor: pointer;
}
details summary::-webkit-details-marker { display:none; content: ""; }
// Styling the polyfill for browsers that don't support details/summary tags
.no-details details { display: block }
.no-details details > summary::before { content:none }
.no-details details.open > summary::before { content:none }
h1 {
margin: 0 auto;
margin-left: 380px;
width: 174px;
font-family: Helvetica;
font-size: 42px;
font-weight: bold;
color: $h1_color;
letter-spacing: -.05em;
float: left;
a
{
color: $h1_color;
text-decoration: none;
}
a:hover
{
color: $h1_color;
text-decoration: none;
}
}
h2 {
font-family: $primary_font, $secondary_font, $tertiary_font;
font-size: 45px;
color: $h2_color;
margin-bottom: 50px;
}
h4 {
font-size: 36px;
color: $h4_color;
margin-bottom: 30px;
}
h5 {
font-family: $primary_font, $secondary_font, $tertiary_font;
margin-bottom: 10px;
color: $h5_color;
}
.wrapper {
width: 935px;
margin: 0 auto;
}
.center {
text-align: center;
}
.gray_background
{
width: 100%;
padding: 50px 0;
background: $gray_background_top_color; /* Old browsers */
background: -moz-linear-gradient(top, $gray_background_top_color 0%, $gray_background_middle_color 50%, $gray_background_bottom_color 100%); /* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,$gray_background_top_color), color-stop(50%,$gray_background_middle_color), color-stop(100%,$gray_background_bottom_color)); /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, $gray_background_top_color 0%,$gray_background_middle_color 50%,$gray_background_bottom_color 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, $gray_background_top_color 0%,$gray_background_middle_color 50%,$gray_background_bottom_color 100%); /* Opera 11.10+ */
background: -ms-linear-gradient(top, $gray_background_top_color 0%,$gray_background_middle_color 50%,$gray_background_bottom_color 100%); /* IE10+ */
background: linear-gradient(to bottom, $gray_background_top_color 0%,$gray_background_middle_color 50%,$gray_background_bottom_color 100%); /* W3C */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='$gray_background_top_color', endColorstr='$gray_background_bottom_color',GradientType=0 ); /* IE6-9 */
border-bottom: 1px solid $gray_background_border_color;
}
.button:hover {
text-decoration: none;
color: $button_hovered_color;
}
.button:active {
background: $button_active_background;
border: 1px solid $button_active_border;
}
.blue_button {
display: block;
color: $button_color; /* text color */
text-shadow: 0 -1px 1px $button-text_shadow_color; /* drop shadow */
-moz-box-shadow:
0 1px 1px $button_box_shadow_color /* drop shadow */,
inset 0 -1px $button_box_shadow_inset_color /* inner shadow */;
-webkit-box-shadow:
0 1px 1px $button_box_shadow_color /* drop shadow */,
inset 0 -1px 1px $button_box_shadow_inset_color /* inner shadow */;
background-image: $button_top_gradient; /* gradient fill */
background-image: -moz-linear-gradient(90deg, $button_top_gradient 0%, $button_bottom_gradient 100%); /* gradient fill */
background-image: -o-linear-gradient(90deg, $button_top_gradient 0%, $button_bottom_gradient 100%); /* gradient fill */
background-image: -webkit-linear-gradient(90deg, $button_top_gradient 0%, $button_bottom_gradient 100%); /* gradient fill */
background-image: linear-gradient(90deg, $button_top_gradient 0%, $button_bottom_gradient 100%); /* gradient fill */
-webkit-border-radius: $button_border_radius;
-moz-border-radius: $button_border_radius;
border-radius: $button_border_radius;
font-family: $primary_font, $secondary_font, $tertiary_font;
}
.blue_button:hover {
-moz-box-shadow:
0 1px 1px $button_box_shadow_color /* drop shadow */,
inset 0 -1px 1px $button_box_shadow_inset_color /* inner shadow */;
-webkit-box-shadow:
0 1px 1px$button_box_shadow_color /* drop shadow */,
inset 0 -1px 1px $button_box_shadow_inset_color /* inner shadow */;
box-shadow:
0 1px 1px $button_box_shadow_color /* drop shadow */,
inset 0 -1px 1px $button_box_shadow_inset_color /* inner shadow */;
background-image: $button_ie9_gradient_hover; /* gradient fill */
background-image: -moz-linear-gradient(90deg, $button_top_gradient_hover 0%, $button_bottom_gradient_hover 100%); /* gradient fill */
background-image: -o-linear-gradient(90deg, $button_top_gradient_hover 0%, $button_bottom_gradient_hover 100%); /* gradient fill */
background-image: -webkit-linear-gradient(90deg, $button_top_gradient_hover 0%, $button_bottom_gradient_hover 100%); /* gradient fill */
background-image: linear-gradient(90deg, $button_top_gradient_hover 0%, $button_bottom_gradient_hover 100%); /* gradient fill */
text-decoration: none;
}
.blue_button:active {
-moz-box-shadow:
0 1px 1px $button_box_shadow_color /* drop shadow */,
inset 0 3px 5px $button_box_shadow_inset_color /* inner shadow */;
-webkit-box-shadow:
0 1px 1px $button_box_shadow_color /* drop shadow */,
inset 0 3px 5px $button_box_shadow_inset_color /* inner shadow */;
box-shadow:
0 1px 1px $button_box_shadow_color /* drop shadow */,
inset 0 3px 5px $button_box_shadow_inset_color /* inner shadow */;
background-image: $button_ie9_gradient_active /* gradient fill */;
background-image: -moz-linear-gradient(90deg, $button_top_gradient_active 0%, $button_bottom_gradient_active 100%); /* gradient fill */
background-image: -o-linear-gradient(90deg, $button_top_gradient_active 0%, $button_bottom_gradient_active 100%); /* gradient fill */
background-image: -webkit-linear-gradient(90deg, $button_top_gradient_active 0%, $button_bottom_gradient_active 100%); /* gradient fill */
background-image: linear-gradient(90deg, $button_top_gradient_active 0%, $button_bottom_gradient_active 100%); /* gradient fill */
}

View File

@@ -0,0 +1,48 @@
/* http://meyerweb.com/eric/tools/css/reset/
v2.0 | 20110126
License: none (public domain)
*/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}

View File

@@ -0,0 +1,50 @@
#share_container
{
#congrats
{
padding: 70px 0;
h2
{
margin-bottom: 24px;
}
p
{
margin-bottom: 30px;
font-size: 24px;
}
}
#share
{
margin: 0 auto;
text-align: center;
margin: 0 auto;
#facebook_button_container
{
margin: 0 auto;
display: inline-block;
}
#pin_button_container
{
margin: 0 auto;
display: inline-block;
position: relative;
top: 1px;
.pin-it-button
{
}
}
#tweet_button_container
{
margin: 0 auto;
display: inline-block;
}
}
#order_id
{
margin: 0 auto;
margin-top: 15px;
padding: 0px;
opacity: 0.3;
z-index: 9999;
}
}

View File

@@ -0,0 +1,63 @@
// Hi!
// Please change around the settings as you need. These are all the defaults
// These only affect the primitives -- inputs, divs, h1-h5, etc (not classes/IDs, with one exception)
// If you have any questions, create a GitHub issue, or email me us -- hello@lockitron.com
$body_background: #E6E6E6;
// Right now, we don't really use h1 and h2's correctly.
// We'll fix it soon!
$h1_color: #323232;
$h2_color: #4B4B4B;
$h4_color: #292929;
$h5_color: #4B4B4B;
$text_color: #6B6B6B;
$link_color: #0008D6;
$text_shadow: 0 1px 0px #fff;
$font_size: 22px;
// Lockitron uses ProximaNova Regular, but that costs money, so we're defaulting to Helveitca Neue instead.
$primary_font: "Helvetica Neue";
$secondary_font: "Helvetica";
$tertiary_font: "Arial";
// Gray background is a gradient -- top == 0%, middle == 50%, bottom == 100%
$gray_background_top_color: #F6F6F6;
$gray_background_middle_color: #FAFAFA;
$gray_background_bottom_color: #FAFAFA;
// The bottom border on the gray backgrounds
$gray_background_border_color: #C4C4C4;
// Button colors/background/border
$button_color: white;
$button_hovered_color: #0088d6;
$button_active_background: #FAFAFA;
$button_active_border: #C8C8C8;
// This only affects .blue_button, which is the "Reserve Now" button you see on Lockitron's homepage
$button_text_shadow_color: rgba(0,0,0,.37);
$button_box_shadow_color: rgba(255,255,255,.92);
$button_box_shadow_inset_color: rgba(0,0,0,.22);
$button_border_radius: 10px;
// Default State
$button_ie9_gradient: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+PGxpbmVhckdyYWRpZW50IGlkPSJoYXQwIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjUwJSIgeTE9IjEwMCUiIHgyPSI1MCUiIHkyPSIwJSI+CjxzdG9wIG9mZnNldD0iMCUiIHN0b3AtY29sb3I9IiMwZTk2ZTQiIHN0b3Atb3BhY2l0eT0iMSIvPgo8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiMwMmEwZmEiIHN0b3Atb3BhY2l0eT0iMSIvPgogICA8L2xpbmVhckdyYWRpZW50PgoKPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNoYXQwKSIgLz4KPC9zdmc+);
$button_top_gradient: #0E96E4;
$button_bottom_gradient: #02A0FA;
// Hover State
$button_ie9_gradient_hover: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+PGxpbmVhckdyYWRpZW50IGlkPSJoYXQwIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjUwJSIgeTE9IjEwMCUiIHgyPSI1MCUiIHkyPSIwJSI+CjxzdG9wIG9mZnNldD0iMCUiIHN0b3AtY29sb3I9IiMyZGE0ZTkiIHN0b3Atb3BhY2l0eT0iMSIvPgo8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiMyMWFlZmYiIHN0b3Atb3BhY2l0eT0iMSIvPgogICA8L2xpbmVhckdyYWRpZW50PgoKPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNoYXQwKSIgLz4KPC9zdmc+);
$button_top_gradient_hover: #2DA4E9;
$button_bottom_gradient_hover: #21AEFF;
// Active State
$button_ie9_gradient_active: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+PGxpbmVhckdyYWRpZW50IGlkPSJoYXQwIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjUwJSIgeTE9IjEwMCUiIHgyPSI1MCUiIHkyPSIwJSI+CjxzdG9wIG9mZnNldD0iMCUiIHN0b3AtY29sb3I9IiMwMzlmZjciIHN0b3Atb3BhY2l0eT0iMSIvPgo8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiMwMzlmZjciIHN0b3Atb3BhY2l0eT0iMSIvPgogICA8L2xpbmVhckdyYWRpZW50PgoKPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNoYXQwKSIgLz4KPC9zdmc+);
$button_top_gradient_active: #039FF7;
$button_bottom_gradient_active: #039ff7;
// FAQ Entry
$summary_color: #0088D6;

View File

@@ -0,0 +1,3 @@
class ApplicationController < ActionController::Base
protect_from_forgery
end

View File

@@ -0,0 +1,42 @@
class PreorderController < ApplicationController
skip_before_filter :verify_authenticity_token, :only => :ipn
def index
end
def checkout
end
def prefill
@user = User.find_or_create_by_email!(params[:email])
@order = Order.prefill!(:name => Settings.product_name, :price => Settings.price, :user_id => @user.id)
# This is where all the magic happens. We create a multi-use token with Amazon, letting us charge the user's Amazon account
# Then, if they confirm the payment, Amazon POSTs us their shipping details and phone number
# From there, we save it, and voila, we got ourselves a preorder!
@pipeline = AmazonFlexPay.multi_use_pipeline(@order.uuid, :transaction_amount => Settings.price, :global_amount_limit => Settings.charge_limit, :collect_shipping_address => "True", :payment_reason => Settings.payment_description)
redirect_to @pipeline.url("#{request.scheme}://#{request.host}/preorder/postfill")
end
def postfill
unless params[:callerReference].blank?
@order = Order.postfill!(params)
end
# "A" means the user cancelled the preorder before clicking "Confirm" on Amazon Payments.
if params['status'] != 'A' && @order.present?
redirect_to :action => :share, :uuid => @order.uuid
else
redirect_to root_url
end
end
def share
@order = Order.find_by_uuid(params[:uuid])
end
def ipn
end
end

View File

@@ -0,0 +1,2 @@
module ApplicationHelper
end

View File

@@ -0,0 +1,17 @@
module PreorderHelper
def like_button(width = 70, show_faces = false)
raw "<div class=\"fb-like\" data-send=\"false\" data-width=\"#{width}\" data-layout=\"box_count\" data-show-faces=\"true\"></div>"
end
def pin_it_button
image_url = URI.encode("#{request.scheme}://#{request.host}#{image_path(Settings.product_image_url)}")
raw "<a href='http://pinterest.com/pin/create/button/?url=#{encoded_root_url}&media=#{image_url}' class='pin-it-button' count-layout='vertical'><img border='0' src='//assets.pinterest.com/images/PinExt.png' title='Pin It' /></a>"
end
def tweet_button
tweet_text = "I'm #{Settings.primary_stat_verb} number #{number_with_delimiter @order.number, :delimiter => ","} #{Settings.tweet_text}!"
raw "<a href='https://twitter.com/share?url=/' id='tweet_button' class='twitter-share-button twitter-button' data-url=#{request.scheme}//#{request.host}' data-via='#{Settings.product_name}' data-lang='en' data-count='vertical' data-text=\"#{tweet_text}\">Tweet</a>"
end
def encoded_root_url
raw URI.encode "#{request.scheme}://#{request.host}/preorder"
end
end

0
app/mailers/.gitkeep Normal file
View File

0
app/models/.gitkeep Normal file
View File

68
app/models/order.rb Normal file
View File

@@ -0,0 +1,68 @@
class Order < ActiveRecord::Base
attr_accessible :address_one, :address_two, :city, :country, :number, :state, :status, :token, :transaction_id, :zip, :shipping, :tracking_number, :name, :price, :phone, :expiration
attr_readonly :uuid
before_validation :generate_uuid!, :on => :create
belongs_to :user
self.primary_key = 'uuid'
# This is where we create our Caller Reference for Amazon Payments, and prefill some other information.
def self.prefill!(options = {})
@order = Order.new
@order.name = options[:name]
@order.user_id = options[:user_id]
@order.price = options[:price]
@order.number = Order.next_order_number || 1
@order.save!
return @order
end
# After authenticating with Amazon, we get the rest of the details
def self.postfill!(options = {})
@order = Order.find_by_uuid!(options[:callerReference])
@order.token = options[:tokenID]
if !@order.token.blank?
@order.address_one = options[:addressLine1]
@order.address_two = options[:addressLine2]
@order.city = options[:city]
@order.state = options[:state]
@order.status = options[:status]
@order.zip = options[:zip]
@order.phone = options[:phoneNumber]
@order.country = options[:country]
@order.expiration = Date.parse(options[:expiry])
@order.save!
@order
end
end
def self.next_order_number
Order.order("number DESC").limit(1).first.number.to_i + 1 if Order.count > 0
end
def generate_uuid!
self.uuid = SecureRandom.hex(16)
end
# Implement these three methods to
def self.goal
Settings.project_goal
end
def self.percent
(Order.current.to_f / Order.goal.to_f) * 100.to_f
end
# See what it looks like when you have some backers! Drop in a number instead of Order.count
def self.current
Order.count
end
def self.revenue
Order.current.to_f * Settings.price
end
validates_presence_of :name, :price, :user_id
end

4
app/models/user.rb Normal file
View File

@@ -0,0 +1,4 @@
class User < ActiveRecord::Base
attr_accessible :email
has_many :orders
end

View File

@@ -0,0 +1,22 @@
<div class="footer">
<div class="wrapper clearfix">
<ul>
<li>
<a href="#" %>/faq">Help & FAQs</a>
</li>
<li>
<a href="#">Press & Media</a>
</li>
<li>
<a href="http://blog.lockitron.com/">Blog</a>
</li>
<li>
<a href="#">Privacy Policy</a>
</li>
<li>
<a href="/account/login">Login</a>
</li>
</ul>
<p>© 2009-2012 Apigy Inc. All rights reserved. Patents pending.</p>
</div>
</div>

View File

@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<title><%= Settings.product_name %></title>
<%= stylesheet_link_tag "application" %>
<%= javascript_include_tag "application" %>
</head>
<body>
<%= render 'header' %>
<%= yield %>
<%= render 'footer' %>
</body>
</html>

View File

@@ -0,0 +1 @@
<p>© You. Made by the guys at <a href="https://lockitron.com">Lockitron</a>. MIT License.</p>

View File

@@ -0,0 +1,6 @@
<div class="footer">
<div class="wrapper clearfix">
<%= render 'copyright' %>
</div>
</div>
<%= render 'google_analytics' %>

View File

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

View File

@@ -0,0 +1,5 @@
<div id="header">
<div class="wrapper clearfix">
<h1 id="lockitron_header"><a href="/"><%= Settings.product_name %></a></h1>
</div>
</div>

View File

@@ -0,0 +1,20 @@
<div class="gray_background">
<div class="wrapper clearfix">
<div class="main_content">
<h3>Check out</h3>
<p>
Let your backers know how their payment information will be handled.
<br />
<br />
Enter your email address below.
</p>
<%= form_tag "/preorder/prefill", :id => "checkout" do %>
<%= email_field_tag "email", nil, :placeholder => "hello@lockitron.com", :required => "required", :id => "email" %>
<%= hidden_field_tag "preorder", true %>
<%= hidden_field_tag "quantity", params[:quantity] %>
<%= submit_tag "Checkout", :class => "blue_button disabled", :id => "amazon_button" %>
<% end %>
</div>
<%= render 'preorder/checkout/sidebar' %>
</div>
</div>

View File

@@ -0,0 +1,6 @@
<div class="sidebar">
<h5>When will I be charged?</h5>
<p>
We recommend that you only charge backers when you can ship, otherwise your payment provider won't be happy.
</p>
</div>

View File

@@ -0,0 +1,71 @@
<div class="gray_background" id="faqs">
<div class="wrapper clearfix">
<h4>Frequently Asked Questions</h4>
<ul>
<li class=''>
<details class=''>
<summary class=''>How do I setup Amazon Payments?</summary>
<p>You'll need to <a href="https://payments.amazon.com/sdui/sdui/accountstatus">create an Amazon Seller Central account</a>. Afterwards, get your access key and secret key from the "Integration" tab on your AWS account. <a href="https://payments.amazon.com/sdui/sdui/helpTab/Checkout-by-Amazon/Advanced-Integration-Help/Using-Your-Access-Key">Click here for more info</a>.
<br />
<br />
Once you have your access key and secret key, head over to <code>config/settings.yml</code>. Change <code>amazon_access_key</code> and <code>amazon_secret_key</code> appropriately.</p>
</details>
</li>
<li>
<details class=''>
<summary>Can I use another payments provider?</summary>
<p>Of course. We haven't built in support for other providers, but we recommend that you take a look at <a href="https://stripe.com">Stripe</a> or <a href="https://wepay.com">WePay</a>.</p>
</details>
</li>
<li>
<details class=''>
<summary>How do I edit the FAQ?</summary>
<p>The faq is a partial located in <code>app/views/preorder/homepage/_faq.html.erb</code> The <code>summary</code> tag is the title, the <code>p</code> is the body. Make sure to add an <code>li</code> tag for each FAQ entry.</p>
</details>
</li>
<li>
<details class=''>
<summary>How do I change around the images, product name, etc?</summary>
<p>The best way is in <code>config/settings.yml</code>. It has variables for several different parts, the YouTube video, the product name, the call to action button ("Fork Now"), and several more.
</p>
</details>
</li>
</ul>
<ul class='col2'>
<li>
<details class=''>
<summary>How do I change the CSS?</summary>
<p>Head over to <code>app/assets/stylesheets/variables.css.scss</code>. It makes it easy to change around the elements used throughout the HTML.
<br />
<br />
Alternatively, you can dive right into the CSS, have a look at <code>app/assets/stylesheets/main.css.scss</code>.</p>
</details>
</li>
<li class=''>
<details class=''>
<summary>Why did you release this?</summary>
<p>Hardware startups are less welcome on Kickstarter than they were 6 months ago. We needed to roll our own kickstarter, so we did. Other hardware startups probably will too, so we made it easier for them by open sourcing our way of doing it.</p>
</details>
</li>
<li class=''>
<details class=''>
<summary class=''>What software stack does this use?</summary>
<p>It's a Ruby on Rails app that makes heavy use of SCSS, Kickstarter's wonderful <code>amazon_flex_pay</code> gem, and a hint of CoffeeScript.</p>
</details>
</li>
<li class=''>
<details class=''>
<summary class=''>How do I deploy it?</summary>
<p>We recommend using Heroku. We include a Procfile for you, so all you need to do is:
<p>
<p>Install the <a href="https://toolbelt.heroku.com/">Heroku Toolbelt</a></p>
<p>Run <code>heroku create</code> in Selfstarter's folder</code></p>
<p>Run <code>git push heroku master</code> in Selfstarter's folder</p>
</p>
</p>
</details>
</li>
</ul>
</div>
</div>

View File

@@ -0,0 +1,51 @@
<div class="big_wrapper">
<div class="wrapper" id="one">
<div class="point_copy">
<h3>
What is Selfstarter?
</h3>
<p>
Selfstarter is an open source starting point for building your own ad-hoc crowdfunding site. It was put together by <a href="https://lockitron.com">Lockitron</a> after they were <a href="http://techcrunch.com/2012/10/07/the-story-of-lockitron-crowdfunding-without-kickstarter/">turned down from Kickstarter</a>.
<p>
</div>
</div>
</div>
<div class="big_wrapper">
<div class="wrapper" id="two">
<div class="point_copy right">
<h3>
How do I use it?
</h3>
<p>
Selftstarter is a starting point for you to build your own solution. It is set up to collect reservations using Amazon Payments, but you can choose you own provider too.
<p>
</div>
</div>
</div>
<div class="big_wrapper">
<div class="wrapper" id="three">
<div class="point_copy">
<h3>
It's just a skeleton
</h3>
<p>
We've kept Selfstarter really simple, but that also means that you should beef it up with your own authentication, administration and product management code.
<p>
</div>
</div>
</div>
<div class="big_wrapper">
<div class="wrapper" id="four">
<div class="point_copy right">
<h3>
Let's get started
</h3>
<p>
Most of what you need to get started is in the Readme. Selfstarter is based on Ruby on Rails, and we've tried to break up all of the different parts in a sensible fashion.
<p>
</div>
</div>
</div>

View File

@@ -0,0 +1,6 @@
<div class="big_wrapper">
<div class="wrapper center" id="middle_reserve">
<h2><%= Settings.ships %></h2>
<a href="/preorder/checkout" class="blue_button reserve"><%= Settings.middle_reserve_text %></a>
</div>
</div>

View File

@@ -0,0 +1,20 @@
<div class="gray_background">
<ul class="wrapper clearfix" id="other_points">
<li id="section-1">
<h4>Section 1</h4>
<p>Morbi tempus dapibus egestas. Nullam accumsan dolor ut purus ornare congue. Phasellus ac commodo neque. Quisque non ligula lacus, id hendrerit eros.</p>
</li>
<li id="section-2">
<h4>Section 2</h4>
<p>Vivamus nec posuere mauris. Suspendisse mi sem, egestas ac tristique ac, varius ac lectus. Sed porttitor dolor adipiscing mauris sagittis.</p>
</li>
<li id="section-3">
<h4>Section 3</h4>
<p>Curabitur dolor elit, placerat et malesuada et, tristique vel nulla. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</p>
</li>
<li id="section-4">
<h4>Section 4</h4>
<p>Curabitur ac mi elit, nec tempor odio. Nam sollicitudin, sapien sit amet elementum pretium, turpis mi fermentum nisl, ac vehicula purus lacus non velit.</p>
</li>
</ul>
</div>

View File

@@ -0,0 +1,8 @@
<div id='logos'>
<ul class="wrapper clearfix">
<li id="awesomeblog"><a href=""></a></li>
<li id="coolpaper"><a href=""></a></li>
<li id="nicemag"><a href=""></a></li>
<li id="readcrunch"><a href=""></a></li>
</ul>
</div>

View File

@@ -0,0 +1,4 @@
<div class="gray_background">
<%= render 'preorder/homepage/value_proposition' %>
<%= render 'preorder/homepage/stats' %>
</div>

View File

@@ -0,0 +1,53 @@
<div class="wrapper clearfix">
<div id="video">
<iframe width='512' height='385' src="<%= Settings.youtube_embed_url %>?autohide=1&showinfo=0&rel=0&autoplay=0"></iframe>
</div>
<div id="backing">
<ul>
<li class="stats" id="backers">
<%= number_with_delimiter Order.current, :delimiter => "," %>
<span><%= Settings.primary_stat %></span>
</li>
<li class="stats">
<%= number_to_currency Order.revenue, :precision => 0 %>
<span>of <%= number_to_currency Settings.project_goal.to_f * Settings.price.to_f, :precision => 0 %></span>
</li>
<% if Settings.expiration_date.present? %>
<li class="stats" id="days">
<%= distance_of_time_in_words_to_now(Settings.expiration_date).gsub(/\D/, "") %>
<span><%= distance_of_time_in_words_to_now(Settings.expiration_date).gsub(/\d/, "").gsub("about", "") %> left</span>
</li>
<% else %>
<li class="stats" id="days">
&infin;
<span>days left</span>
</li>
<% end %>
</ul>
<% if Order.current < Order.goal %>
<div id='progress_bg' class='small'>
<div id='progress' class='' style='width: <%= Order.percent %>%;'>
</div>
</div>
<% else %>
<div id="progress_bg">
<div id="progress">
</div>
<div id='progress_text'><%= Order.percent %>% <%= Settings.progress_text %></div>
</div>
<% end %>
<div id="reserve_container">
<p id="ship_date"><%= Settings.ships %></p>
<a href="/preorder/checkout" class="blue_button reserve"><%= Settings.call_to_action %></a>
<p id="price"><%= Settings.price_human %></p>
<p><%= Settings.dont_give_them_a_reason_to_say_no %></p>
<%= like_button %>
</div>
</div>
</div>

View File

@@ -0,0 +1,3 @@
<div class="wrapper center">
<h2><%= Settings.value_proposition %></h2>
</div>

View File

@@ -0,0 +1,6 @@
<%= render 'preorder/homepage/show_dont_tell' %>
<%= render 'preorder/homepage/key_points' %>
<%= render 'preorder/homepage/other_points' %>
<%= render 'preorder/homepage/middle_reserve' %>
<%= render 'preorder/homepage/faqs' %>
<%= render 'preorder/homepage/press' %>

View File

@@ -0,0 +1,26 @@
<div class="gray_background" id='share_container'>
<div class="wrapper center" id="congrats">
<h2>
Hooray! You've just reserved a <%= Settings.product_name %>!
</h2>
<p>Congratulations, you're <%= Settings.primary_stat_verb %> number <span id="backer_number"><%= number_with_delimiter @order.number, :delimiter => "," %></span>, in supporting <%= Settings.product_name %>. Share the great news!</p>
<br />
<br />
<div id="share" class="clearfix">
<div id='pin_button_container'>
<%= pin_it_button %>
</div>
<div id='tweet_button_container'>
<%= tweet_button %>
</div>
<div id='facebook_button_container'>
<%= like_button(450, true) %>
</div>
</div>
<div id="order_id">Reservation ID: <%= @order.uuid %>. You can bookmark or print this page for your records.</div>
</div>
</div>
<%= render 'preorder/share/twitter_js' %>
<%= render 'preorder/share/facebook_js' %>

View File

@@ -0,0 +1,8 @@
<div id="fb-root"></div>
<script>(function(d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) return;
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/en_US/all.js#xfbml=1&appId=<%= Settings.facebook_app_id %>";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));</script>

View File

@@ -0,0 +1 @@
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="https://platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

4
config.ru Normal file
View File

@@ -0,0 +1,4 @@
# This file is used by Rack-based servers to start the application.
require ::File.expand_path('../config/environment', __FILE__)
run Selfstarter::Application

24
config/application.rb Normal file
View File

@@ -0,0 +1,24 @@
require File.expand_path('../boot', __FILE__)
require 'rails/all'
if defined?(Bundler)
Bundler.require(*Rails.groups(:assets => %w(development test)))
end
module Selfstarter
class Application < Rails::Application
# --- Standard Rails Config ---
config.time_zone = 'Pacific Time (US & Canada)'
config.encoding = "utf-8"
config.filter_parameters += [:password]
config.active_record.whitelist_attributes = true
# Enable the asset pipeline
config.assets.enabled = true
# Version of your assets, change this if you want to expire all your assets
config.assets.version = '1.0'
# --- Standard Rails Config ---
end
end

6
config/boot.rb Normal file
View File

@@ -0,0 +1,6 @@
require 'rubygems'
# Set up gems listed in the Gemfile.
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])

25
config/database.yml Normal file
View File

@@ -0,0 +1,25 @@
# SQLite version 3.x
# gem install sqlite3
#
# Ensure the SQLite 3 gem is defined in your Gemfile
# gem 'sqlite3'
development:
adapter: sqlite3
database: db/development.sqlite3
pool: 5
timeout: 5000
# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
adapter: sqlite3
database: db/test.sqlite3
pool: 5
timeout: 5000
production:
adapter: sqlite3
database: db/production.sqlite3
pool: 5
timeout: 5000

5
config/environment.rb Normal file
View File

@@ -0,0 +1,5 @@
# Load the rails application
require File.expand_path('../application', __FILE__)
# Initialize the rails application
Selfstarter::Application.initialize!

View File

@@ -0,0 +1,37 @@
Selfstarter::Application.configure do
# Settings specified here will take precedence over those in config/application.rb
# In the development environment your application's code is reloaded on
# every request. This slows down response time but is perfect for development
# since you don't have to restart the web server when you make code changes.
config.cache_classes = false
# Log error messages when you accidentally call methods on nil.
config.whiny_nils = true
# Show full error reports and disable caching
config.consider_all_requests_local = true
config.action_controller.perform_caching = false
# Don't care if the mailer can't send
config.action_mailer.raise_delivery_errors = false
# Print deprecation notices to the Rails logger
config.active_support.deprecation = :log
# Only use best-standards-support built into browsers
config.action_dispatch.best_standards_support = :builtin
# Raise exception on mass assignment protection for Active Record models
config.active_record.mass_assignment_sanitizer = :strict
# Log the query plan for queries taking more than this (works
# with SQLite, MySQL, and PostgreSQL)
config.active_record.auto_explain_threshold_in_seconds = 0.5
# Do not compress assets
config.assets.compress = false
# Expands the lines which load the assets
config.assets.debug = true
end

View File

@@ -0,0 +1,67 @@
Selfstarter::Application.configure do
# Settings specified here will take precedence over those in config/application.rb
# Code is not reloaded between requests
config.cache_classes = true
# Full error reports are disabled and caching is turned on
config.consider_all_requests_local = false
config.action_controller.perform_caching = true
# Disable Rails's static asset server (Apache or nginx will already do this)
config.serve_static_assets = false
# Compress JavaScripts and CSS
config.assets.compress = true
# Don't fallback to assets pipeline if a precompiled asset is missed
config.assets.compile = false
# Generate digests for assets URLs
config.assets.digest = true
# Defaults to nil and saved in location specified by config.assets.prefix
# config.assets.manifest = YOUR_PATH
# Specifies the header that your server uses for sending files
# config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache
# config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
# config.force_ssl = true
# See everything in the log (default is :info)
# config.log_level = :debug
# Prepend all log lines with the following tags
# config.log_tags = [ :subdomain, :uuid ]
# Use a different logger for distributed setups
# config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
# Use a different cache store in production
# config.cache_store = :mem_cache_store
# Enable serving of images, stylesheets, and JavaScripts from an asset server
# config.action_controller.asset_host = "http://assets.example.com"
# Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
config.assets.precompile += %w( application.js application.css )
# Disable delivery errors, bad email addresses will be ignored
# config.action_mailer.raise_delivery_errors = false
# Enable threaded mode
# config.threadsafe!
# Enable locale fallbacks for I18n (makes lookups for any locale fall back to
# the I18n.default_locale when a translation can not be found)
config.i18n.fallbacks = true
# Send deprecation notices to registered listeners
config.active_support.deprecation = :notify
# Log the query plan for queries taking more than this (works
# with SQLite, MySQL, and PostgreSQL)
# config.active_record.auto_explain_threshold_in_seconds = 0.5
end

View File

@@ -0,0 +1,37 @@
Selfstarter::Application.configure do
# Settings specified here will take precedence over those in config/application.rb
# The test environment is used exclusively to run your application's
# test suite. You never need to work with it otherwise. Remember that
# your test database is "scratch space" for the test suite and is wiped
# and recreated between test runs. Don't rely on the data there!
config.cache_classes = true
# Configure static asset server for tests with Cache-Control for performance
config.serve_static_assets = true
config.static_cache_control = "public, max-age=3600"
# Log error messages when you accidentally call methods on nil
config.whiny_nils = true
# Show full error reports and disable caching
config.consider_all_requests_local = true
config.action_controller.perform_caching = false
# Raise exceptions instead of rendering exception templates
config.action_dispatch.show_exceptions = false
# Disable request forgery protection in test environment
config.action_controller.allow_forgery_protection = false
# Tell Action Mailer not to deliver emails to the real world.
# The :test delivery method accumulates sent emails in the
# ActionMailer::Base.deliveries array.
config.action_mailer.delivery_method = :test
# Raise exception on mass assignment protection for Active Record models
config.active_record.mass_assignment_sanitizer = :strict
# Print deprecation notices to the stderr
config.active_support.deprecation = :stderr
end

View File

@@ -0,0 +1,3 @@
AmazonFlexPay.access_key = Settings.amazon_access_key
AmazonFlexPay.secret_key = Settings.amazon_secret_key
AmazonFlexPay.go_live! if Rails.env.production?

View File

@@ -0,0 +1,7 @@
# Be sure to restart your server when you modify this file.
# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
# Rails.backtrace_cleaner.remove_silencers!

View File

@@ -0,0 +1,15 @@
# Be sure to restart your server when you modify this file.
# Add new inflection rules using the following format
# (all these examples are active by default):
# ActiveSupport::Inflector.inflections do |inflect|
# inflect.plural /^(ox)$/i, '\1en'
# inflect.singular /^(ox)en/i, '\1'
# inflect.irregular 'person', 'people'
# inflect.uncountable %w( fish sheep )
# end
#
# These inflection rules are supported but not enabled by default:
# ActiveSupport::Inflector.inflections do |inflect|
# inflect.acronym 'RESTful'
# end

View File

@@ -0,0 +1,5 @@
# Be sure to restart your server when you modify this file.
# Add new mime types for use in respond_to blocks:
# Mime::Type.register "text/richtext", :rtf
# Mime::Type.register_alias "text/html", :iphone

View File

@@ -0,0 +1,3 @@
RailsConfig.setup do |config|
config.const_name = "Settings"
end

View File

@@ -0,0 +1,7 @@
# Be sure to restart your server when you modify this file.
# Your secret key for verifying the integrity of signed cookies.
# If you change this key, all old signed cookies will become invalid!
# Make sure the secret is at least 30 characters and all random,
# no regular words or you'll be exposed to dictionary attacks.
Selfstarter::Application.config.secret_token = '686a073cf783e29dee02cb7544762d17a7c769acf7baa148a0d9726a39e45123532418f9ce7cd3def2ca0e3d5bff9d0b9ffd41f19b0c6b6dd9d0cc10b77fc5ae'

View File

@@ -0,0 +1,8 @@
# Be sure to restart your server when you modify this file.
Selfstarter::Application.config.session_store :cookie_store, key: '_Selfstarter_session'
# Use the database for sessions instead of the cookie-based default,
# which shouldn't be used to store highly confidential information
# (create the session table with "rails generate session_migration")
# Selfstarter::Application.config.session_store :active_record_store

View File

@@ -0,0 +1,14 @@
# Be sure to restart your server when you modify this file.
#
# This file contains settings for ActionController::ParamsWrapper which
# is enabled by default.
# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
ActiveSupport.on_load(:action_controller) do
wrap_parameters format: [:json]
end
# Disable root element in JSON by default.
ActiveSupport.on_load(:active_record) do
self.include_root_in_json = false
end

5
config/locales/en.yml Normal file
View File

@@ -0,0 +1,5 @@
# Sample localization file for English. Add more files in this directory for other locales.
# See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
en:
hello: "Hello world"

11
config/routes.rb Normal file
View File

@@ -0,0 +1,11 @@
Selfstarter::Application.routes.draw do
root :to => "preorder#index"
match '/preorder' => 'preorder#index'
get "preorder/checkout"
match '/preorder/share/:uuid' => 'preorder#share', :via => :get
match '/preorder/ipn' => 'preorder#ipn', :via => :post
match '/preorder/prefill' => 'preorder#prefill'
match '/preorder/postfill' => 'preorder#postfill'
end

80
config/settings.yml Normal file
View File

@@ -0,0 +1,80 @@
# Hi there!
# These are the settings for Selfstarter.
# This is more tidy than changing the HTML if all you want to do is rename things and swap out images
# You should totally change the HTML and CSS though
# Checkout app/assets/stylesheets/variables.css.scss to change around the CSS quickly
# Set your project goal here - if you manually want to adjust your progress to test the site, head over to the Order model (app/models/order.rb)
project_goal: 100
# If you want to edit the FAQ, head over to app/views/preorder/homepage/_faqs.html.erb
# This'll be both the page title (<title></title>) and the name in the header
product_name: "Selfstarter"
# An image showcasing your product -- it'll show up when you pin your product
# It should be in app/assets/images
product_image_path: "my-product-image.png"
# The message on the preorder page, Lockitron's
value_proposition: "Roll your own crowdfunding"
# YouTube Video URL (The embed URL, without the query string options)
# There's no Vimeo support at the moment, but feel free to implement it and send a pull request!
youtube_embed_url: "https://www.youtube.com/v/D1L3o88GKew"
# Amazon settings -- you'll need an Amazon Payments account, sign up here --> http://bit.ly/SGksTv
# To find your access key and secret key, head over to here --> http://bit.ly/R4I4ky (Follow that guide in the Seller Central page)
amazon_access_key: "YOUR_AMAZON_ACCESS_KEY"
amazon_secret_key: "YOUR_AMAZON_SECRET_KEY"
price: 19.95
payment_description: "You really should change this text because people will see it on Amazon's order page!!!!!"
# Amazon limits how much we can charge people with their Multi-Use tokens.
# You probably should add some leeway to account for international shipping
charge_limit: 25.00
# Stats settings
# On Lockitron, it's "backers"
primary_stat: "backers"
# This'll show up in the tweet as, "I'm forker number ..."
primary_stat_verb: 'backer'
# The 2nd call to action button, towards the middle-ish of the page
middle_reserve_text: "Reserve Now"
# When the project should end
expiration_date: <%= DateTime.now + 29 %>
# Text to show inside the progress bar, when the goal reaches/exceeds 100%
progress_text: "Implemented"
# Call to action section
# On Lockitron, it's "First Batch Ships in March 2013"
ships: "Ships...sometime"
# On Lockitron, it's "Reserve Now"
call_to_action: "Reserve Now"
# On Lockitron, this is "Only $149 for a limited time"
price_human: "It costs money!"
# The paragraph below the price. You'd probably say something about how you're not going to charge them before it ships (so it's less risky).
dont_give_them_a_reason_to_say_no: "You'll get this exact site. All you'll need to get started is a great product."
# Social Stuff
facebook_app_id: "1234567890"
# Tweets are prefixed with "I'm #{Settings.primary_stat} number X for #{Settings.product_name}"
# Maybe mention something about your product vision -- e.g. "to replace keys with my phone"
tweet_text: "to crowdfund"
# Google Analytics
google_id: "1234567890"
# If you want to change the images for the key points (e.g. "Kickstarter is not a store")
# They're in app/assets/images/#{pointer_number}-background.png
# So, the first key point, it's at app/assets/images/1-background.png
# Alternatively, change it up in app/assets/stylesheets/homepage/key_points.css.scss

View File

View File

0
config/settings/test.yml Normal file
View File

View File

@@ -0,0 +1,9 @@
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :email
t.timestamps
end
end
end

View File

@@ -0,0 +1,26 @@
class CreateOrders < ActiveRecord::Migration
def change
create_table :orders, :id => false do |t|
t.string :token
t.string :transaction_id
t.string :address_one
t.string :address_two
t.string :city
t.string :state
t.string :zip
t.string :country
t.string :status
t.string :number
t.string :uuid
t.string :user_id
t.decimal :price
t.decimal :shipping
t.string :tracking_number
t.string :phone
t.string :name
t.date :expiration
t.timestamps
end
end
end

45
db/schema.rb Normal file
View File

@@ -0,0 +1,45 @@
# encoding: UTF-8
# This file is auto-generated from the current state of the database. Instead
# of editing this file, please use the migrations feature of Active Record to
# incrementally modify your database, and then regenerate this schema definition.
#
# Note that this schema.rb definition is the authoritative source for your
# database schema. If you need to create the application database on another
# system, you should be using db:schema:load, not running all the migrations
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
# you'll amass, the slower it'll run and the greater likelihood for issues).
#
# It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20121004072706) do
create_table "orders", :id => false, :force => true do |t|
t.string "token"
t.string "transaction_id"
t.string "address_one"
t.string "address_two"
t.string "city"
t.string "state"
t.string "zip"
t.string "country"
t.string "status"
t.string "number"
t.string "uuid"
t.string "user_id"
t.decimal "price"
t.decimal "shipping"
t.string "tracking_number"
t.string "phone"
t.string "name"
t.date "expiration"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "users", :force => true do |t|
t.string "email"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
end

7
db/seeds.rb Normal file
View File

@@ -0,0 +1,7 @@
# This file should contain all the record creation needed to seed the database with its default values.
# The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).
#
# Examples:
#
# cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }])
# Mayor.create(name: 'Emanuel', city: cities.first)

2
doc/README_FOR_APP Normal file
View File

@@ -0,0 +1,2 @@
Use this README file to introduce your application and point to useful places in the API for learning more.
Run "rake doc:app" to generate API documentation for your models, controllers, helpers, and libraries.

0
lib/assets/.gitkeep Normal file
View File

0
lib/tasks/.gitkeep Normal file
View File

0
log/.gitkeep Normal file
View File

26
public/404.html Normal file
View File

@@ -0,0 +1,26 @@
<!DOCTYPE html>
<html>
<head>
<title>The page you were looking for doesn't exist (404)</title>
<style type="text/css">
body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
div.dialog {
width: 25em;
padding: 0 4em;
margin: 4em auto 0 auto;
border: 1px solid #ccc;
border-right-color: #999;
border-bottom-color: #999;
}
h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
</style>
</head>
<body>
<!-- This file lives in public/404.html -->
<div class="dialog">
<h1>The page you were looking for doesn't exist.</h1>
<p>You may have mistyped the address or the page may have moved.</p>
</div>
</body>
</html>

26
public/422.html Normal file
View File

@@ -0,0 +1,26 @@
<!DOCTYPE html>
<html>
<head>
<title>The change you wanted was rejected (422)</title>
<style type="text/css">
body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
div.dialog {
width: 25em;
padding: 0 4em;
margin: 4em auto 0 auto;
border: 1px solid #ccc;
border-right-color: #999;
border-bottom-color: #999;
}
h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
</style>
</head>
<body>
<!-- This file lives in public/422.html -->
<div class="dialog">
<h1>The change you wanted was rejected.</h1>
<p>Maybe you tried to change something you didn't have access to.</p>
</div>
</body>
</html>

25
public/500.html Normal file
View File

@@ -0,0 +1,25 @@
<!DOCTYPE html>
<html>
<head>
<title>We're sorry, but something went wrong (500)</title>
<style type="text/css">
body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
div.dialog {
width: 25em;
padding: 0 4em;
margin: 4em auto 0 auto;
border: 1px solid #ccc;
border-right-color: #999;
border-bottom-color: #999;
}
h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
</style>
</head>
<body>
<!-- This file lives in public/500.html -->
<div class="dialog">
<h1>We're sorry, but something went wrong.</h1>
</div>
</body>
</html>

0
public/favicon.ico Normal file
View File

5
public/robots.txt Normal file
View File

@@ -0,0 +1,5 @@
# See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file
#
# To ban all spiders from the entire site uncomment the next two lines:
# User-Agent: *
# Disallow: /

6
script/rails Executable file
View File

@@ -0,0 +1,6 @@
#!/usr/bin/env ruby
# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
APP_PATH = File.expand_path('../../config/application', __FILE__)
require File.expand_path('../../config/boot', __FILE__)
require 'rails/commands'

0
test/fixtures/.gitkeep vendored Normal file
View File

Some files were not shown because too many files have changed in this diff Show More