New landing page - initial layout and functionality

This commit is contained in:
alexs
2013-08-05 17:04:56 +10:00
parent c64944d11a
commit 38b0a581e0
28 changed files with 1714 additions and 2 deletions

View File

@@ -30,6 +30,7 @@ gem 'rabl'
gem 'oj'
gem 'chili', :github => 'eaterprises/chili'
gem 'deface', :github => 'spree/deface'
gem 'paperclip'
# Gems used only for assets and not required
# in production environments by default.
@@ -64,6 +65,7 @@ group :test, :development do
gem 'letter_opener'
gem 'timecop'
gem 'poltergeist'
gem 'zurb-foundation'
end
group :chili do

View File

@@ -439,6 +439,8 @@ GEM
websocket (1.0.7)
xpath (1.0.0)
nokogiri (~> 1.3)
zurb-foundation (4.3.1)
sass (>= 3.2.0)
PLATFORMS
ruby
@@ -467,6 +469,7 @@ DEPENDENCIES
local_organics_feature!
newrelic_rpm
oj
paperclip
pg
poltergeist
pry-debugger
@@ -491,3 +494,4 @@ DEPENDENCIES
turn (~> 0.8.3)
uglifier (>= 1.0.3)
unicorn
zurb-foundation

View File

@@ -6,8 +6,11 @@
//
//= require 'jquery'
//= require jquery_ujs
//= require store/spree_core
//= require store/spree_auth
//= require store/spree_promo
//= require foundation
//= require_tree .
$(function(){ $(document).foundation(); });

View File

@@ -0,0 +1,4 @@
/*! Backstretch - v2.0.4 - 2013-06-19
* http://srobbin.com/jquery-plugins/backstretch/
* Copyright (c) 2013 Scott Robbin; Licensed MIT */
(function(a,d,p){a.fn.backstretch=function(c,b){(c===p||0===c.length)&&a.error("No images were supplied for Backstretch");0===a(d).scrollTop()&&d.scrollTo(0,0);return this.each(function(){var d=a(this),g=d.data("backstretch");if(g){if("string"==typeof c&&"function"==typeof g[c]){g[c](b);return}b=a.extend(g.options,b);g.destroy(!0)}g=new q(this,c,b);d.data("backstretch",g)})};a.backstretch=function(c,b){return a("body").backstretch(c,b).data("backstretch")};a.expr[":"].backstretch=function(c){return a(c).data("backstretch")!==p};a.fn.backstretch.defaults={centeredX:!0,centeredY:!0,duration:5E3,fade:0};var r={left:0,top:0,overflow:"hidden",margin:0,padding:0,height:"100%",width:"100%",zIndex:-999999},s={position:"absolute",display:"none",margin:0,padding:0,border:"none",width:"auto",height:"auto",maxHeight:"none",maxWidth:"none",zIndex:-999999},q=function(c,b,e){this.options=a.extend({},a.fn.backstretch.defaults,e||{});this.images=a.isArray(b)?b:[b];a.each(this.images,function(){a("<img />")[0].src=this});this.isBody=c===document.body;this.$container=a(c);this.$root=this.isBody?l?a(d):a(document):this.$container;c=this.$container.children(".backstretch").first();this.$wrap=c.length?c:a('<div class="backstretch"></div>').css(r).appendTo(this.$container);this.isBody||(c=this.$container.css("position"),b=this.$container.css("zIndex"),this.$container.css({position:"static"===c?"relative":c,zIndex:"auto"===b?0:b,background:"none"}),this.$wrap.css({zIndex:-999998}));this.$wrap.css({position:this.isBody&&l?"fixed":"absolute"});this.index=0;this.show(this.index);a(d).on("resize.backstretch",a.proxy(this.resize,this)).on("orientationchange.backstretch",a.proxy(function(){this.isBody&&0===d.pageYOffset&&(d.scrollTo(0,1),this.resize())},this))};q.prototype={resize:function(){try{var a={left:0,top:0},b=this.isBody?this.$root.width():this.$root.innerWidth(),e=b,g=this.isBody?d.innerHeight?d.innerHeight:this.$root.height():this.$root.innerHeight(),j=e/this.$img.data("ratio"),f;j>=g?(f=(j-g)/2,this.options.centeredY&&(a.top="-"+f+"px")):(j=g,e=j*this.$img.data("ratio"),f=(e-b)/2,this.options.centeredX&&(a.left="-"+f+"px"));this.$wrap.css({width:b,height:g}).find("img:not(.deleteable)").css({width:e,height:j}).css(a)}catch(h){}return this},show:function(c){if(!(Math.abs(c)>this.images.length-1)){var b=this,e=b.$wrap.find("img").addClass("deleteable"),d={relatedTarget:b.$container[0]};b.$container.trigger(a.Event("backstretch.before",d),[b,c]);this.index=c;clearInterval(b.interval);b.$img=a("<img />").css(s).bind("load",function(f){var h=this.width||a(f.target).width();f=this.height||a(f.target).height();a(this).data("ratio",h/f);a(this).fadeIn(b.options.speed||b.options.fade,function(){e.remove();b.paused||b.cycle();a(["after","show"]).each(function(){b.$container.trigger(a.Event("backstretch."+this,d),[b,c])})});b.resize()}).appendTo(b.$wrap);b.$img.attr("src",b.images[c]);return b}},next:function(){return this.show(this.index<this.images.length-1?this.index+1:0)},prev:function(){return this.show(0===this.index?this.images.length-1:this.index-1)},pause:function(){this.paused=!0;return this},resume:function(){this.paused=!1;this.next();return this},cycle:function(){1<this.images.length&&(clearInterval(this.interval),this.interval=setInterval(a.proxy(function(){this.paused||this.next()},this),this.options.duration));return this},destroy:function(c){a(d).off("resize.backstretch orientationchange.backstretch");clearInterval(this.interval);c||this.$wrap.remove();this.$container.removeData("backstretch")}};var l,f=navigator.userAgent,m=navigator.platform,e=f.match(/AppleWebKit\/([0-9]+)/),e=!!e&&e[1],h=f.match(/Fennec\/([0-9]+)/),h=!!h&&h[1],n=f.match(/Opera Mobi\/([0-9]+)/),t=!!n&&n[1],k=f.match(/MSIE ([0-9]+)/),k=!!k&&k[1];l=!((-1<m.indexOf("iPhone")||-1<m.indexOf("iPad")||-1<m.indexOf("iPod"))&&e&&534>e||d.operamini&&"[object OperaMini]"==={}.toString.call(d.operamini)||n&&7458>t||-1<f.indexOf("Android")&&e&&533>e||h&&6>h||"palmGetResource"in d&&e&&534>e||-1<f.indexOf("MeeGo")&&-1<f.indexOf("NokiaBrowser/8.5.0")||k&&6>=k)})(jQuery,window);

View File

@@ -0,0 +1,62 @@
//;(function (window, document, $) {
// alert($("#sidebarButton").html());
//}(this, document, jQuery));
//;(function (window, document, $) {
// // Set the negative margin on the top menu for slide-menu pages
// var $selector1 = $('#topMenu'),
// events = 'click.fndtn';
// if ($selector1.length > 0) $selector1.css("margin-top", $selector1.height() * -1);
//
// // Watch for clicks to show the sidebar
// var $selector2 = $('#sidebarButton');
// if ($selector2.length > 0) {
// $('#sidebarButton').on(events, function (e) {
// console.log("testing one two three");
// e.preventDefault();
// $('body').toggleClass('active');
// });
// }
// else {
// console.log("not supposed to be there");
// }
//
// // Watch for clicks to show the menu for slide-menu pages
// var $selector3 = $('#menuButton');
// if ($selector3.length > 0) {
// $('#menuButton').on(events, function (e) {
// e.preventDefault();
// $('body').toggleClass('active-menu');
// });
// }
//
// // // Adjust sidebars and sizes when resized
// // $(window).resize(function() {
// // // if (!navigator.userAgent.match(/Android/i)) $('body').removeClass('active');
// // var $selector4 = $('#topMenu');
// // if ($selector4.length > 0) $selector4.css("margin-top", $selector4.height() * -1);
// // });
//
// // Switch panels for the paneled nav on mobile
// var $selector5 = $('#switchPanels');
// if ($selector5.length > 0) {
// $('#switchPanels dd').on(events, function (e) {
// e.preventDefault();
// var switchToPanel = $(this).children('a').attr('href'),
// switchToIndex = $(switchToPanel).index();
// $(this).toggleClass('active').siblings().removeClass('active');
// $(switchToPanel).parent().css("left", (switchToIndex * (-100) + '%'));
// });
// }
//
// $('#nav li a').on(events, function (e) {
// alert("test");
// e.preventDefault();
// var href = $(this).attr('href'),
// $target = $(href);
// $('html, body').animate({scrollTop : $target.offset().top}, 300);
// });
//}(this, document, jQuery));

View File

@@ -0,0 +1,17 @@
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/
$(document).ready ->
if $("#image-url-container").length > 0
$('body').css('background-color', 'black', 'important');
$.backstretch($("#image-url-container").attr("data-url"));
# off canvas panel trigger
events = 'click.fndtn'
$("#sidebarButton").on events, (e) ->
e.preventDefault()
$("body").toggleClass "active"
$('#new_spree_user').on 'ajax:success', (event, data, status, xhr) ->
console.log "successfully authenticated"

File diff suppressed because one or more lines are too long

View File

@@ -3,5 +3,6 @@
* and any sub-directories. 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 foundation_and_overrides
*= require_tree .
*/

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,90 @@
// Place all the styles related to the home controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/
@import "foundation/variables";
@import "foundation/components/global";
@import "foundation/components/buttons";
@import "foundation/components/panels";
#postcode_select_box {
text-align: center;
padding: 40% 0;
p {
color: white;
font-size: 1.1em;
}
input {
font-size: 2em;
}
.button-huge {
$padding: emCalc(21);
$bg: $primary-color;
$radius: true;
$full-width: false;
$disabled: false;
$is-input: false;
@include button($padding, $bg, $radius, $full-width, $disabled, $is-input);
}
}
.backstretch img {
opacity: 0.4;
filter: alpha(opacity=40);
}
.bgwidth {
width: 100%;
}
.bgheight {
height: 100%;
}
#home-page-nav
{
ul {
margin: 0;
padding: 0;
li {
list-style-type: none;
display: inline;
font-size: 1.2em;
font-weight: bold;
color: #FFF;
a {
&:link {
color: #FFF;
}
}
&:before {
content: " | ";
}
&:first-child {
&:before {
content: none;
}
}
}
}
}
#sidebar {
border: none;
}
.login-panel {
$bg: #222;
$padding: emCalc(20);
$adjust: true;
@include panel($bg, $padding, $adjust);
}

View File

@@ -0,0 +1,51 @@
/* Off canvas layout CSS/JS provided by or adapted from work by Jason Weaver and Luke Wroblewski Requires globals.css grid.css */
body.off-canvas { padding: 0; margin: 0; overflow: hidden}
.container { width: 100%; }
.row { overflow: hidden; }
.row .row { overflow: visible; }
.paneled .container { overflow: hidden; }
.paneled .row { width: 100%; }
[role="main"]:before { content: " "; position: absolute; z-index: -1; top: 0; left: -100%; width: 100%; height: 100%; }
[role="complementary"], [role="main"] { width: 100%; padding: 0 15px; display: block; position: relative; z-index: 1; -webkit-transition: 0.25s all ease-in; -moz-transition: 0.25s all ease-in; -o-transition: 0.25s all ease-in; transition: 0.25s all ease-in; }
.paneled [role="main"] { padding: 0; }
.page-panel { width: 100%; padding: 0 15px; -webkit-transition: 0.3s margin ease-in-out; -moz-transition: 0.3s margin ease-in-out; -o-transition: 0.3s margin ease-in-out; transition: 0.3s margin ease-in-out; background: #fff; }
#switchPanels { margin: 0 -15px; }
.hide-extras [role="complementary"] { display: block; }
[role="navigation"]#topMenu { -webkit-transition: 0.25s all ease-in; -moz-transition: 0.25s all ease-in; -o-transition: 0.25s all ease-in; transition: 0.25s all ease-in; }
[role="navigation"]#topMenu ul { margin-top: 0; }
[role="complementary"] { margin-left: -100%; width: 400px; float: left; z-index: 2; }
[role="main"] { margin-left: 0; float: right; z-index: 1; position: relative; }
.paneled [role="main"] { background: #fff; width: 500%; overflow: hidden; float: none; position: relative; left: 0; -webkit-transition: 0.15s all ease-in; -moz-transition: 0.15s all ease-in; -o-transition: 0.15s all ease-in; transition: 0.15s all ease-in; }
.page-panel { min-height: 400px; float: left; margin: 0; width: 20%; }
.active [role="complementary"] { margin-left: 0; }
.active [role="main"] { margin-right: -420px; }
.active-menu [role="navigation"]#topMenu { margin-top: 0 !important; }
@media all and (min-width: 768px) { menu-button, .sidebar-button { display: none; }
/*[role="complementary"] { width: 20%; margin-left: 0; float: left; padding: 0 15px; }*/
[role="main"] { width: 100%; padding: 0 15px; }
.paneled [role="main"] { width: 100%; padding: 0; background: #f4f4f4; left: 0 !important; }
.page-panel { display: block; min-height: 800px; float: none; margin: 0; width: 100%; background: #f4f4f4; }
.hide-extras [role="main"] { width: 100%; }
.hide-extras [role="complementary"] { display: none; }
[role="navigation"]#topMenu { display: none; } }

View File

@@ -0,0 +1,6 @@
class HomeController < ApplicationController
layout 'landing_page'
def new_landing_page
end
end

View File

@@ -0,0 +1,27 @@
Spree::UserSessionsController.class_eval do
def create
authenticate_spree_user!
if spree_user_signed_in?
respond_to do |format|
format.html {
flash[:success] = t(:logged_in_succesfully)
redirect_back_or_default(after_sign_in_path_for(spree_current_user))
}
format.js {
render json: { email: spree_current_user.login }
}
end
else
respond_to do |format|
format.html {
flash.now[:error] = t('devise.failure.invalid')
render :new
}
format.js {
render json: { message: t('devise.failure.invalid') }, status: :unprocessable_entity
}
end
end
end
end

View File

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

View File

@@ -0,0 +1,10 @@
class LandingPageImage < ActiveRecord::Base
attr_accessible :photo
has_attached_file :photo, styles: { max_common_res: "1920x1080#" }
validates_attachment_presence :photo
def self.random
offset(rand(LandingPageImage.count)).first
end
end

View File

@@ -0,0 +1,42 @@
%span#image-url-container.hide{ "data-url" => "#{LandingPageImage.random.photo.url(:max_common_res)}" }
%section{ role: "main" }
.row
.large-10.large-centered.columns
#postcode_select_box
.row
= form_tag do
.large-10.columns
= text_field_tag :postcode, "", class: "right", placeholder: "Enter your postcode..."
.large-2.columns
= submit_tag "Search", class: "button-huge"
.row
.large-12.large-centered.columns
%p Open Food Web - fresh opportunities for farmers and eaters
.row.show-for-small
.large-12.large-centered.columns#home-page-nav
%ul
%li= link_to "DISTRIBUTORS", "#"
%li= link_to "FARMERS", "#", "data-reveal-id" => "login-modal"
%section#sidebar{ role: "complementary" }
.login-panel
.row
.large-12.large-centered.columns
%h2 Login
= form_for Spree::User.new, :remote => true, :as => :spree_user, :url => spree.spree_user_session_path do |f|
#password-credentials
%p
= f.label :email, t(:email)
%br/
= f.email_field :email, :class => 'title', :tabindex => 1
%p
= f.label :password, t(:password)
%br/
= f.password_field :password, :class => 'title', :tabindex => 2
%p
%label
= f.check_box :remember_me
= f.label :remember_me, t(:remember_me)
%p= f.submit t(:login), :class => 'button primary', :tabindex => 3

View File

@@ -0,0 +1,21 @@
!!!
%html
%head
%meta{charset: 'utf-8'}/
%meta{name: 'viewport', content: "width=device-width,initial-scale=1.0"}/
%title= content_for?(:title) ? yield(:title) : 'Welcome to Open Food Web'
= stylesheet_link_tag "application"
= javascript_include_tag "store/all"
= csrf_meta_tags
%body.off-canvas
%nav.top-bar
%section.top-bar-section
%ul.left
%li= link_to "Login", "#sidebar", id: "sidebarButton", class: "sidebar-button"
%ul.right
%li= link_to "Distributors", "#"
%li.divider
%li= link_to "Farmers", "#"
= yield

View File

@@ -20,6 +20,8 @@ Openfoodweb::Application.routes.draw do
end
end
get "new_landing_page", :controller => 'home', :action => "new_landing_page"
# Mount Spree's routes
mount Spree::Core::Engine, :at => '/'
end

View File

@@ -0,0 +1,7 @@
class CreateLandingPageImages < ActiveRecord::Migration
def change
create_table :landing_page_images do |t|
t.timestamps
end
end
end

View File

@@ -0,0 +1,15 @@
class AddAttachmentPhotoToLandingPageImage < ActiveRecord::Migration
def self.up
add_column :landing_page_images, :photo_file_name, :string
add_column :landing_page_images, :photo_content_type, :string
add_column :landing_page_images, :photo_file_size, :integer
add_column :landing_page_images, :photo_updated_at, :datetime
end
def self.down
remove_column :landing_page_images, :photo_file_name
remove_column :landing_page_images, :photo_content_type
remove_column :landing_page_images, :photo_file_size
remove_column :landing_page_images, :photo_updated_at
end
end

View File

@@ -11,7 +11,7 @@
#
# It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20130729021924) do
ActiveRecord::Schema.define(:version => 20130801012854) do
create_table "cms_blocks", :force => true do |t|
t.integer "page_id", :null => false
@@ -189,6 +189,15 @@ ActiveRecord::Schema.define(:version => 20130729021924) do
t.datetime "updated_at", :null => false
end
create_table "landing_page_images", :force => true do |t|
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.string "photo_file_name"
t.string "photo_content_type"
t.integer "photo_file_size"
t.datetime "photo_updated_at"
end
create_table "order_cycles", :force => true do |t|
t.string "name"
t.datetime "orders_open_at"

View File

@@ -101,3 +101,8 @@ unless Spree::Product.count > 0
:distributor => Enterprise.is_distributor[2],
:shipping_method => Spree::ShippingMethod.first)
end
# -- Landing page images
LandingPageImage.create photo: File.open(File.join(Rails.root, "lib", "seed_data", "carrots.jpg"))
LandingPageImage.create photo: File.open(File.join(Rails.root, "lib", "seed_data", "tomatoes.jpg"))
LandingPageImage.create photo: File.open(File.join(Rails.root, "lib", "seed_data", "potatoes.jpg"))

BIN
lib/seed_data/carrots.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 MiB

BIN
lib/seed_data/potatoes.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 452 KiB

BIN
lib/seed_data/tomatoes.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 KiB

View File

@@ -0,0 +1,15 @@
require 'spec_helper'
# Specs in this file have access to a helper object that includes
# the HomeHelper. For example:
#
# describe HomeHelper do
# describe "string concat" do
# it "concats two strings with spaces" do
# helper.concat_strings("this","that").should == "this that"
# end
# end
# end
describe HomeHelper do
pending "add some examples to (or delete) #{__FILE__}"
end

View File

@@ -0,0 +1,6 @@
require 'spec_helper'
describe LandingPageImage do
it { should have_attached_file(:photo) }
it { should validate_attachment_presence(:photo) }
end

View File

@@ -26,6 +26,7 @@ ActiveRecord::Fixtures.create_fixtures(fixtures_dir, ['spree/states', 'spree/cou
require 'capybara/poltergeist'
Capybara.javascript_driver = :poltergeist
require "paperclip/matchers"
RSpec.configure do |config|
# ## Mock Framework
@@ -76,4 +77,6 @@ RSpec.configure do |config|
# Factory girl
require 'factory_girl_rails'
config.include FactoryGirl::Syntax::Methods
config.include Paperclip::Shoulda::Matchers
end