1. Rich Manalang
  2. atlassian-travel

Commits

Rich Manalang  committed ee8d271

latest

  • Participants
  • Parent commits a811a3c
  • Branches master

Comments (0)

Files changed (149)

File .gitignore

View file
+rsa*
+log/
+tmp/

File Gemfile

View file
+source :rubygems
+gem 'sinatra'
+gem 'omniauth', '>= 1.0.0'
+gem 'omniauth-jira', :path => '../omniauth-jira'
+gem 'multi_json'
+gem 'oauth'
+gem 'bson', '>=1.6.1'
+gem 'bson_ext', '>=1.6.1'
+gem 'mongo_mapper'
+gem 'rack-flash', :git => 'git://github.com/ChrisCauser/rack-flash.git'
+gem 'slim'
+gem 'jira-ruby', :require => 'jira'
+
+group :development do
+  gem 'shotgun'
+end

File Gemfile.lock

View file
+GIT
+  remote: git://github.com/ChrisCauser/rack-flash.git
+  revision: d8fd1d2c0b176d04bcb904a22cd84debe85f2061
+  specs:
+    rack-flash (0.1.2)
+      rack
+
+PATH
+  remote: ../omniauth-jira
+  specs:
+    omniauth-jira (0.1.0)
+      multi_json (~> 1.3)
+      oauth
+      omniauth (~> 1.0)
+      omniauth-oauth (~> 1.0)
+
+GEM
+  remote: http://rubygems.org/
+  specs:
+    actionpack (3.2.3)
+      activemodel (= 3.2.3)
+      activesupport (= 3.2.3)
+      builder (~> 3.0.0)
+      erubis (~> 2.7.0)
+      journey (~> 1.0.1)
+      rack (~> 1.4.0)
+      rack-cache (~> 1.2)
+      rack-test (~> 0.6.1)
+      sprockets (~> 2.1.2)
+    activemodel (3.2.3)
+      activesupport (= 3.2.3)
+      builder (~> 3.0.0)
+    activesupport (3.2.3)
+      i18n (~> 0.6)
+      multi_json (~> 1.0)
+    bson (1.6.2)
+    bson_ext (1.6.2)
+      bson (~> 1.6.2)
+    builder (3.0.0)
+    erubis (2.7.0)
+    hashie (1.2.0)
+    hike (1.2.1)
+    i18n (0.6.0)
+    jira-ruby (0.0.3)
+      activesupport
+      oauth
+      railties
+    journey (1.0.3)
+    json (1.7.1)
+    mongo (1.6.2)
+      bson (~> 1.6.2)
+    mongo_mapper (0.11.1)
+      activemodel (~> 3.0)
+      activesupport (~> 3.0)
+      plucky (~> 0.4.0)
+    multi_json (1.3.4)
+    oauth (0.4.6)
+    omniauth (1.1.0)
+      hashie (~> 1.2)
+      rack
+    omniauth-oauth (1.0.1)
+      oauth
+      omniauth (~> 1.0)
+    plucky (0.4.4)
+      mongo (~> 1.5)
+    rack (1.4.1)
+    rack-cache (1.2)
+      rack (>= 0.4)
+    rack-protection (1.2.0)
+      rack
+    rack-ssl (1.3.2)
+      rack
+    rack-test (0.6.1)
+      rack (>= 1.0)
+    railties (3.2.3)
+      actionpack (= 3.2.3)
+      activesupport (= 3.2.3)
+      rack-ssl (~> 1.3.2)
+      rake (>= 0.8.7)
+      rdoc (~> 3.4)
+      thor (~> 0.14.6)
+    rake (0.9.2.2)
+    rdoc (3.12)
+      json (~> 1.4)
+    shotgun (0.9)
+      rack (>= 1.0)
+    sinatra (1.3.2)
+      rack (~> 1.3, >= 1.3.6)
+      rack-protection (~> 1.2)
+      tilt (~> 1.3, >= 1.3.3)
+    slim (1.2.0)
+      temple (~> 0.4.0)
+      tilt (~> 1.3.3)
+    sprockets (2.1.3)
+      hike (~> 1.2)
+      rack (~> 1.0)
+      tilt (~> 1.1, != 1.3.0)
+    temple (0.4.0)
+    thor (0.14.6)
+    tilt (1.3.3)
+
+PLATFORMS
+  ruby
+
+DEPENDENCIES
+  bson (>= 1.6.1)
+  bson_ext (>= 1.6.1)
+  jira-ruby
+  mongo_mapper
+  multi_json
+  oauth
+  omniauth (>= 1.0.0)
+  omniauth-jira!
+  rack-flash!
+  shotgun
+  sinatra
+  slim

File app.rb

View file
+require 'sinatra'
+require 'multi_json'
+require 'net/http'
+require 'uri'
+require 'omniauth'
+
+CONSUMER_KEY = 'travel'
+
+use Rack::Session::Cookie
+use Rack::Flash
+use OmniAuth::Builder do
+  provider :JIRA, CONSUMER_KEY, "",
+    :client_options => { :site => "http://localhost:2990/jira", :private_key_file => 'rsa.pem' }
+end
+
+before do
+  @current_user = session[:current_user] || nil
+  if session['access_token']
+    @jira = JIRA::Client.new(CONSUMER_KEY,'', session[:access_token].consumer.options.merge({:rest_base_path => '/rest/api/2'}))
+    @jira.set_access_token(session[:access_token].token, session['access_token'].secret)
+  end
+
+  if !@jira.nil? and @project.nil?
+    @project = @jira.Project.find('TRAVEL')
+  end
+end
+
+get '/' do
+  if @current_user
+    @user = @jira.User.find(@current_user.name)
+    slim :index
+  else
+    slim :public
+  end
+end
+
+get '/signin' do
+  redirect '/auth/JIRA'
+end
+
+get '/signout' do
+  session[:current_user] = nil
+  session[:access_token] = nil
+  @current_user = nil
+  redirect "/"
+end
+
+post '/request' do
+  @req = @jira.Issue.create()
+end
+
+%w(get post).each do |method|
+  send(method, "/auth/:provider/callback") do
+    session[:current_user] = request.env['omniauth.auth'].info
+    session[:access_token] = request.env['omniauth.auth'].extra.access_token
+    redirect '/'
+  end
+end
+
+get '/auth/failure' do
+  flash[:notice] = params[:message] # if using sinatra-flash or rack-flash
+  redirect '/'
+end

File client/app/app.coffee

View file
+# TODO
+# * Search results
+# * Step train
+# * Calendar dismissal
+# * Calendar validations
+# * Pretty dates
+# * Column sorting
+
+getRate = (from, to) ->
+  $('#currscript').remove()
+  script = document.createElement 'script'
+  script.setAttribute 'src', 
+    "http://query.yahooapis.com/v1/public/yql?q=select%20rate%2Cname%20from%20csv%20where%20url%3D'http%3A%2F%2Fdownload.finance.yahoo.com%2Fd%2Fquotes%3Fs%3D#{from}#{to}%253DX%26f%3Dl1n'%20and%20columns%3D'rate%2Cname'&format=json&callback=parseExchangeRate"
+  script.setAttribute 'id', 'currscript'
+  document.body.appendChild script
+
+window.parseExchangeRate = (data) ->
+  name = data.query.results.row.name
+  rate = parseFloat data.query.results.row.rate, 10
+  $('#costin').html (parseFloat $('#cost').val() * rate)
+    .round(2)
+    .format(2) + 
+    " AUD"
+
+class User extends Backbone.Model
+  url: =>
+    '/jira/rest/api/2/user?username=' + @id
+  initialize: (options) ->
+    @fetch(options).done (d) =>
+      options.callback d
+
+class CurrentUser extends Backbone.Model
+  url: '/jira/rest/auth/1/session'
+
+  initialize: ->
+    @fetch()
+
+  fetch: ->
+    super.done =>
+      new User 
+        id        : @get 'name'
+        callback  : (d) =>
+          @set 'profile', d
+          @setLoggedIn()
+
+  setLoggedIn: ->
+    console.log 'setting logged in user'
+    $('.curruser').html currentUser.get('profile').displayName
+    $('.avatar').attr('src', currentUser.get('profile').avatarUrls["48x48"])
+
+
+class Project extends Backbone.Model
+
+class Projects extends Backbone.Collection
+  url: '/jira/rest/api/2/project'
+  model: Project
+
+class TripModel extends Backbone.Model
+  defaults: ->
+    updatedAt: Date.create()
+    createdAt: Date.create()
+    createdBy: "rmanalang@atlassian.com"
+
+  initialize: ->
+    @bind 'error', (model, errs) =>
+      console.log 'TripModel Error', arguments
+      errs
+
+  validate: 
+    createdBy:
+      required: true
+    description:
+      required: true
+    from:
+      required: true
+    to:
+      required: true
+    departDate:
+      required: true
+    returnDate:
+      required: true
+    cost:
+      required: true
+      # type: "number"
+    currency:
+      required: true
+    justification:
+      required: true
+    approver:
+      required: true
+
+class TripCollection extends Backbone.Collection
+  model: TripModel
+
+class AddTripView extends Backbone.View
+  el: $ '#addtrip'
+
+  template: _.template $('#addtrip-template').html()
+
+  initialize: (options) ->
+    @render()
+
+  events:
+    # 'changeDate .date':       'renderFriendlyDate'
+    'change #cost':           'updateConvertedRate'
+    'change #curr':           'updateConvertedRate'
+    'submit #add-trip-form':  'saveTrip'
+
+  render: ->
+    @$el.html @.template()
+    $('div.date').datepicker().on 'changeDate', (e) =>
+      console.log @, e
+    $('#approver').typeahead
+      source: [
+        "Jay Simons"
+        "Mike Cannon-Brookes"
+        "Scott Farquar"
+        "Daniel Freeman"
+        "Rich Manalang"
+      ]
+
+    $('#cost, #curr').on('change keyup', =>)
+    @
+
+  updateConvertedRate: ->
+    getRate $('#curr').val(), 'AUD'
+
+  focus: ->
+    focusCb = => @$el.find("input[type='text']:first").focus()
+    setTimeout focusCb, 0
+
+  showInvalid: (model, errs) =>
+    for attr of errs
+      @$el.find('.'+attr).addClass 'error'
+
+  showSavedToast: ->
+    @flash = new FlashView
+      flash: 
+        title:    'Success'
+        message:  'Your travel approval request has been saved and sent for approval'
+
+  saveTrip: ->
+    console.log "save"
+    @$('.error').removeClass 'error'    
+    @model = new TripModel
+    @model.on 'error', @showInvalid
+    rslt = @model.save $('form').serializeObject()
+    console.log "save",rslt
+    try
+      @collection.add @model if !rslt
+      @render()
+      @showSavedToast()
+    catch err
+    false
+
+class MyTripView extends Backbone.View
+  template: _.template $('#mytrip-template').html()
+
+  tagName: 'tr'
+  
+  initialize: (options) ->
+    @model.bind 'change', @render
+    @model.bind 'destroy', @remove
+
+  render: ->
+    @$el.html @template(@model.toJSON()) if @model
+
+  remove: ->
+    @$el.remove()
+
+class MyTripsView extends Backbone.View
+  el: $ '#mytrips'
+
+  template: _.template $('#mytrips-template').html()
+
+  initialize: (options) ->
+    @collection.on 'add', @addOne
+    @render()
+
+  render: ->
+    @$el.html @template()
+    @addAll()
+
+  addOne: (model) =>
+    myTripView = new MyTripView({model: model})
+    myTripView.render();
+    @$el.find('#mytrips-rows').prepend myTripView.el
+    model.bind 'remove', myTripView.remove
+
+  addAll: ->
+    @collection.each @addOne
+
+
+class FlashView extends Backbone.View
+  tagName: "div"
+  
+  className: "alert"
+  
+  template: _.template $('#flash-template').html()
+  
+  initialize: (options) ->
+    @render()
+  
+  render: ->
+    @$el.addClass @options.flash.class if @options.flash.class
+    @$el.html(@template(@options.flash)).prependTo('#flash')
+
+class AppRouter extends Backbone.Router
+  routes:
+    ''          : 'addTrip'
+    'trips'     : 'myTrips'
+    'trip/book' : 'bookTrip'
+    'trip/new'  : 'addTrip'
+    '*path'     : 'notFound'
+
+  before: ->
+    @flash.remove() if @flash
+
+  activate: (id) ->
+    $('.content').addClass 'hidden'
+    $('#'+id).removeClass 'hidden'
+    $('.topnav').removeClass 'active'
+    $('.'+id).addClass 'active'
+    return @
+
+  addTrip: ->
+    @activate 'addtrip'
+    addTripView.focus()
+
+  myTrips: ->
+    @activate 'mytrips'
+
+  bookTrip: ->
+    @activate 'booktrip'
+
+  notFound: ->
+    @activate '404'
+    
+
+window.trips = new TripCollection
+# trips.fetch()
+
+addTripView = new AddTripView({collection: trips})
+myTripsView = new MyTripsView({collection: trips})
+
+currentUser = new CurrentUser
+
+appRouter = new AppRouter
+Backbone.history.start()

File client/app/config.coffee

Empty file added.

File client/less/accordion.less

View file
+// ACCORDION
+// ---------
+
+
+// Parent container
+.accordion {
+  margin-bottom: @baseLineHeight;
+}
+
+// Group == heading + body
+.accordion-group {
+  margin-bottom: 2px;
+  border: 1px solid #e5e5e5;
+  .border-radius(4px);
+}
+.accordion-heading {
+  border-bottom: 0;
+}
+.accordion-heading .accordion-toggle {
+  display: block;
+  padding: 8px 15px;
+}
+
+// Inner needs the styles because you can't animate properly with any styles on the element
+.accordion-inner {
+  padding: 9px 15px;
+  border-top: 1px solid #e5e5e5;
+}

File client/less/alerts.less

View file
+// ALERT STYLES
+// ------------
+
+// Base alert styles
+.alert {
+  padding: 8px 35px 8px 14px;
+  margin-bottom: @baseLineHeight;
+  text-shadow: 0 1px 0 rgba(255,255,255,.5);
+  background-color: @warningBackground;
+  border: 1px solid @warningBorder;
+  .border-radius(4px);
+  color: @warningText;
+}
+.alert-heading {
+  color: inherit;
+}
+
+// Adjust close link position
+.alert .close {
+  position: relative;
+  top: -2px;
+  right: -21px;
+  line-height: 18px;
+}
+
+// Alternate styles
+// ----------------
+
+.alert-success {
+  background-color: @successBackground;
+  border-color: @successBorder;  
+  color: @successText;
+}
+.alert-danger,
+.alert-error {
+  background-color: @errorBackground;
+  border-color: @errorBorder;
+  color: @errorText;
+}
+.alert-info {
+  background-color: @infoBackground;
+  border-color: @infoBorder;
+  color: @infoText;
+}
+
+// Block alerts
+// ------------------------
+.alert-block {
+  padding-top: 14px;
+  padding-bottom: 14px;
+}
+.alert-block > p,
+.alert-block > ul {
+  margin-bottom: 0;
+}
+.alert-block p + p {
+  margin-top: 5px;
+}

File client/less/badges.less

View file
+// BADGES
+// ------
+
+// Base
+.badge {
+  padding: 1px 9px 2px;
+  font-size: @baseFontSize * .925;
+  font-weight: bold;
+  white-space: nowrap;
+  color: @white;
+  background-color: @grayLight;
+  .border-radius(9px);
+}
+
+// Hover state
+.badge:hover {
+  color: @white;
+  text-decoration: none;
+  cursor: pointer;
+}
+
+// Colors
+.badge-error            { background-color: @errorText; }
+.badge-error:hover      { background-color: darken(@errorText, 10%); }
+
+.badge-warning          { background-color: @orange; }
+.badge-warning:hover    { background-color: darken(@orange, 10%); }
+
+.badge-success          { background-color: @successText; }
+.badge-success:hover    { background-color: darken(@successText, 10%); }
+
+.badge-info             { background-color: @infoText; }
+.badge-info:hover       { background-color: darken(@infoText, 10%); }
+
+.badge-inverse          { background-color: @grayDark; }
+.badge-inverse:hover    { background-color: darken(@grayDark, 10%); }

File client/less/bootstrap.less

View file
+/*!
+ * Bootstrap v2.0.2
+ *
+ * Copyright 2012 Twitter, Inc
+ * Licensed under the Apache License v2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Designed and built with all the love in the world @twitter by @mdo and @fat.
+ */
+
+// CSS Reset
+@import "reset.less";
+
+// Core variables and mixins
+@import "variables.less"; // Modify this for custom colors, font-sizes, etc
+@import "mixins.less";
+
+// Grid system and page structure
+@import "scaffolding.less";
+@import "grid.less";
+@import "layouts.less";
+
+// Base CSS
+@import "type.less";
+@import "code.less";
+@import "forms.less";
+@import "tables.less";
+
+// Components: common
+@import "sprites.less";
+@import "dropdowns.less";
+@import "wells.less";
+@import "component-animations.less";
+@import "close.less";
+
+// Components: Buttons & Alerts
+@import "buttons.less";
+@import "button-groups.less";
+@import "alerts.less"; // Note: alerts share common CSS with buttons and thus have styles in buttons.less
+
+// Components: Nav
+@import "navs.less";
+@import "navbar.less";
+@import "breadcrumbs.less";
+@import "pagination.less";
+@import "pager.less";
+
+// Components: Popovers
+@import "modals.less";
+@import "tooltip.less";
+@import "popovers.less";
+
+// Components: Misc
+@import "thumbnails.less";
+@import "labels.less";
+@import "badges.less";
+@import "progress-bars.less";
+@import "accordion.less";
+@import "carousel.less";
+@import "hero-unit.less";
+
+// Utility classes
+@import "utilities.less"; // Has to be last to override when necessary

File client/less/breadcrumbs.less

View file
+// BREADCRUMBS
+// -----------
+
+.breadcrumb {
+  padding: 7px 14px;
+  margin: 0 0 @baseLineHeight;
+  list-style: none;
+  #gradient > .vertical(@white, #f5f5f5);
+  border: 1px solid #ddd;
+  .border-radius(3px);
+  .box-shadow(inset 0 1px 0 @white);
+  li {
+    display: inline-block;
+    .ie7-inline-block();
+    text-shadow: 0 1px 0 @white;
+  }
+  .divider {
+    padding: 0 5px;
+    color: @grayLight;
+  }
+  .active a {
+    color: @grayDark;
+  }
+}

File client/less/button-groups.less

View file
+// BUTTON GROUPS
+// -------------
+
+
+// Make the div behave like a button
+.btn-group {
+  position: relative;
+  .clearfix(); // clears the floated buttons
+  .ie7-restore-left-whitespace();
+}
+
+// Space out series of button groups
+.btn-group + .btn-group {
+  margin-left: 5px;
+}
+
+// Optional: Group multiple button groups together for a toolbar
+.btn-toolbar {
+  margin-top: @baseLineHeight / 2;
+  margin-bottom: @baseLineHeight / 2;
+  .btn-group {
+    display: inline-block;
+    .ie7-inline-block();
+  }
+}
+
+// Float them, remove border radius, then re-add to first and last elements
+.btn-group .btn {
+  position: relative;
+  float: left;
+  margin-left: -1px;
+  .border-radius(0);
+}
+// Set corners individual because sometimes a single button can be in a .btn-group and we need :first-child and :last-child to both match
+.btn-group .btn:first-child {
+  margin-left: 0;
+     -webkit-border-top-left-radius: 4px;
+         -moz-border-radius-topleft: 4px;
+             border-top-left-radius: 4px;
+  -webkit-border-bottom-left-radius: 4px;
+      -moz-border-radius-bottomleft: 4px;
+          border-bottom-left-radius: 4px;
+}
+.btn-group .btn:last-child,
+.btn-group .dropdown-toggle {
+     -webkit-border-top-right-radius: 4px;
+         -moz-border-radius-topright: 4px;
+             border-top-right-radius: 4px;
+  -webkit-border-bottom-right-radius: 4px;
+      -moz-border-radius-bottomright: 4px;
+          border-bottom-right-radius: 4px;
+}
+// Reset corners for large buttons
+.btn-group .btn.large:first-child {
+  margin-left: 0;
+     -webkit-border-top-left-radius: 6px;
+         -moz-border-radius-topleft: 6px;
+             border-top-left-radius: 6px;
+  -webkit-border-bottom-left-radius: 6px;
+      -moz-border-radius-bottomleft: 6px;
+          border-bottom-left-radius: 6px;
+}
+.btn-group .btn.large:last-child,
+.btn-group .large.dropdown-toggle {
+     -webkit-border-top-right-radius: 6px;
+         -moz-border-radius-topright: 6px;
+             border-top-right-radius: 6px;
+  -webkit-border-bottom-right-radius: 6px;
+      -moz-border-radius-bottomright: 6px;
+          border-bottom-right-radius: 6px;
+}
+
+// On hover/focus/active, bring the proper btn to front
+.btn-group .btn:hover,
+.btn-group .btn:focus,
+.btn-group .btn:active,
+.btn-group .btn.active {
+  z-index: 2;
+}
+
+// On active and open, don't show outline
+.btn-group .dropdown-toggle:active,
+.btn-group.open .dropdown-toggle {
+  outline: 0;
+}
+
+
+
+// Split button dropdowns
+// ----------------------
+
+// Give the line between buttons some depth
+.btn-group .dropdown-toggle {
+  padding-left: 8px;
+  padding-right: 8px;
+  @shadow: inset 1px 0 0 rgba(255,255,255,.125), inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);
+  .box-shadow(@shadow);
+  *padding-top: 3px;
+  *padding-bottom: 3px;
+}
+.btn-group .btn-mini.dropdown-toggle {
+  padding-left: 5px;
+  padding-right: 5px;
+  *padding-top: 1px;
+  *padding-bottom: 1px;
+}
+.btn-group .btn-small.dropdown-toggle {
+  *padding-top: 4px;
+  *padding-bottom: 4px;
+}
+.btn-group .btn-large.dropdown-toggle {
+  padding-left: 12px;
+  padding-right: 12px;
+}
+
+.btn-group.open {
+  // IE7's z-index only goes to the nearest positioned ancestor, which would
+  // make the menu appear below buttons that appeared later on the page
+  *z-index: @zindexDropdown;
+
+  // Reposition menu on open and round all corners
+  .dropdown-menu {
+    display: block;
+    margin-top: 1px;
+    .border-radius(5px);
+  }
+
+  .dropdown-toggle {
+    background-image: none;
+    @shadow: inset 0 1px 6px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);
+    .box-shadow(@shadow);
+  }
+}
+
+// Reposition the caret
+.btn .caret {
+  margin-top: 7px;
+  margin-left: 0;
+}
+.btn:hover .caret,
+.open.btn-group .caret {
+  .opacity(100);
+}
+// Carets in other button sizes
+.btn-mini .caret {
+  margin-top: 5px;
+}
+.btn-small .caret {
+  margin-top: 6px;
+}
+.btn-large .caret {
+  margin-top: 6px;
+  border-left:  5px solid transparent;
+  border-right: 5px solid transparent;
+  border-top:   5px solid @black;
+}
+
+
+// Account for other colors
+.btn-primary,
+.btn-warning,
+.btn-danger,
+.btn-info,
+.btn-success,
+.btn-inverse {
+  .caret {
+    border-top-color: @white;
+    border-bottom-color: @white;
+    .opacity(75);
+  }
+}
+

File client/less/buttons.less

View file
+// BUTTON STYLES
+// -------------
+
+
+// Base styles
+// --------------------------------------------------
+
+// Core
+.btn {
+  display: inline-block;
+  .ie7-inline-block();
+  padding: 4px 10px 4px;
+  margin-bottom: 0; // For input.btn
+  font-size: @baseFontSize;
+  line-height: @baseLineHeight;
+  color: @grayDark;
+  text-align: center;
+  text-shadow: 0 1px 1px rgba(255,255,255,.75);
+  vertical-align: middle;
+  .buttonBackground(@btnBackground, @btnBackgroundHighlight);
+  border: 1px solid @btnBorder;
+  border-bottom-color: darken(@btnBorder, 10%);
+  .border-radius(4px);
+  @shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);
+  .box-shadow(@shadow);
+  cursor: pointer;
+
+  // Give IE7 some love
+  .ie7-restore-left-whitespace();
+}
+
+// Hover state
+.btn:hover {
+  color: @grayDark;
+  text-decoration: none;
+  background-color: darken(@white, 10%);
+  background-position: 0 -15px;
+
+  // transition is only when going to hover, otherwise the background
+  // behind the gradient (there for IE<=9 fallback) gets mismatched
+  .transition(background-position .1s linear);
+}
+
+// Focus state for keyboard and accessibility
+.btn:focus {
+  .tab-focus();
+}
+
+// Active state
+.btn.active,
+.btn:active {
+  background-image: none;
+  @shadow: inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);
+  .box-shadow(@shadow);
+  background-color: darken(@white, 10%);
+  background-color: darken(@white, 15%) e("\9");
+  outline: 0;
+}
+
+// Disabled state
+.btn.disabled,
+.btn[disabled] {
+  cursor: default;
+  background-image: none;
+  background-color: darken(@white, 10%);
+  .opacity(65);
+  .box-shadow(none);
+}
+
+
+// Button Sizes
+// --------------------------------------------------
+
+// Large
+.btn-large {
+  padding: 9px 14px;
+  font-size: @baseFontSize + 2px;
+  line-height: normal;
+  .border-radius(5px);
+}
+.btn-large [class^="icon-"] {
+  margin-top: 1px;
+}
+
+// Small
+.btn-small {
+  padding: 5px 9px;
+  font-size: @baseFontSize - 2px;
+  line-height: @baseLineHeight - 2px;
+}
+.btn-small [class^="icon-"] {
+  margin-top: -1px;
+}
+
+// Mini
+.btn-mini {
+  padding: 2px 6px;
+  font-size: @baseFontSize - 2px;
+  line-height: @baseLineHeight - 4px;
+}
+
+
+// Alternate buttons
+// --------------------------------------------------
+
+// Set text color
+// -------------------------
+.btn-primary,
+.btn-primary:hover,
+.btn-warning,
+.btn-warning:hover,
+.btn-danger,
+.btn-danger:hover,
+.btn-success,
+.btn-success:hover,
+.btn-info,
+.btn-info:hover,
+.btn-inverse,
+.btn-inverse:hover {
+  text-shadow: 0 -1px 0 rgba(0,0,0,.25);
+  color: @white;
+}
+// Provide *some* extra contrast for those who can get it
+.btn-primary.active,
+.btn-warning.active,
+.btn-danger.active,
+.btn-success.active,
+.btn-info.active,
+.btn-inverse.active {
+  color: rgba(255,255,255,.75);
+}
+
+// Set the backgrounds
+// -------------------------
+.btn-primary {
+  .buttonBackground(@btnPrimaryBackground, @btnPrimaryBackgroundHighlight);
+}
+// Warning appears are orange
+.btn-warning {
+  .buttonBackground(@btnWarningBackground, @btnWarningBackgroundHighlight);
+}
+// Danger and error appear as red
+.btn-danger {
+  .buttonBackground(@btnDangerBackground, @btnDangerBackgroundHighlight);
+}
+// Success appears as green
+.btn-success {
+  .buttonBackground(@btnSuccessBackground, @btnSuccessBackgroundHighlight);
+}
+// Info appears as a neutral blue
+.btn-info {
+  .buttonBackground(@btnInfoBackground, @btnInfoBackgroundHighlight);
+}
+// Inverse appears as dark gray
+.btn-inverse {
+  .buttonBackground(@btnInverseBackground, @btnInverseBackgroundHighlight);
+}
+
+
+// Cross-browser Jank
+// --------------------------------------------------
+
+button.btn,
+input[type="submit"].btn {
+
+  // Firefox 3.6 only I believe
+  &::-moz-focus-inner {
+    padding: 0;
+    border: 0;
+  }
+
+  // IE7 has some default padding on button controls
+  *padding-top: 2px;
+  *padding-bottom: 2px;
+  &.btn-large {
+    *padding-top: 7px;
+    *padding-bottom: 7px;
+  }
+  &.btn-small {
+    *padding-top: 3px;
+    *padding-bottom: 3px;
+  }
+  &.btn-mini {
+    *padding-top: 1px;
+    *padding-bottom: 1px;
+  }
+}

File client/less/carousel.less

View file
+// CAROUSEL
+// --------
+
+.carousel {
+  position: relative;
+  margin-bottom: @baseLineHeight;
+  line-height: 1;
+}
+
+.carousel-inner {
+  overflow: hidden;
+  width: 100%;
+  position: relative;
+}
+
+.carousel {
+
+  .item {
+    display: none;
+    position: relative;
+    .transition(.6s ease-in-out left);
+  }
+
+  // Account for jankitude on images
+  .item > img {
+    display: block;
+    line-height: 1;
+  }
+
+  .active,
+  .next,
+  .prev { display: block; }
+
+  .active {
+    left: 0;
+  }
+
+  .next,
+  .prev {
+    position: absolute;
+    top: 0;
+    width: 100%;
+  }
+
+  .next {
+    left: 100%;
+  }
+  .prev {
+    left: -100%;
+  }
+  .next.left,
+  .prev.right {
+    left: 0;
+  }
+
+  .active.left {
+    left: -100%;
+  }
+  .active.right {
+    left: 100%;
+  }
+
+}
+
+// Left/right controls for nav
+// ---------------------------
+
+.carousel-control {
+  position: absolute;
+  top: 40%;
+  left: 15px;
+  width: 40px;
+  height: 40px;
+  margin-top: -20px;
+  font-size: 60px;
+  font-weight: 100;
+  line-height: 30px;
+  color: @white;
+  text-align: center;
+  background: @grayDarker;
+  border: 3px solid @white;
+  .border-radius(23px);
+  .opacity(50);
+
+  // we can't have this transition here
+  // because webkit cancels the carousel
+  // animation if you trip this while
+  // in the middle of another animation
+  // ;_;
+  // .transition(opacity .2s linear);
+
+  // Reposition the right one
+  &.right {
+    left: auto;
+    right: 15px;
+  }
+
+  // Hover state
+  &:hover {
+    color: @white;
+    text-decoration: none;
+    .opacity(90);
+  }
+}
+
+// Caption for text below images
+// -----------------------------
+
+.carousel-caption {
+  position: absolute;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  padding: 10px 15px 5px;
+  background: @grayDark;
+  background: rgba(0,0,0,.75);
+}
+.carousel-caption h4,
+.carousel-caption p {
+  color: @white;
+}

File client/less/close.less

View file
+// CLOSE ICONS
+// -----------
+
+.close {
+  float: right;
+  font-size: 20px;
+  font-weight: bold;
+  line-height: @baseLineHeight;
+  color: @black;
+  text-shadow: 0 1px 0 rgba(255,255,255,1);
+  .opacity(20);
+  &:hover {
+    color: @black;
+    text-decoration: none;
+    .opacity(40);
+    cursor: pointer;
+  }
+}

File client/less/code.less

View file
+// Code.less
+// Code typography styles for the <code> and <pre> elements
+// --------------------------------------------------------
+
+// Inline and block code styles
+code,
+pre {
+  padding: 0 3px 2px;
+  #font > #family > .monospace;
+  font-size: @baseFontSize - 1;
+  color: @grayDark;
+  .border-radius(3px);
+}
+
+// Inline code
+code {
+  padding: 2px 4px;
+  color: #d14;
+  background-color: #f7f7f9;
+  border: 1px solid #e1e1e8;
+}
+
+// Blocks of code
+pre {
+  display: block;
+  padding: (@baseLineHeight - 1) / 2;
+  margin: 0 0 @baseLineHeight / 2;
+  font-size: @baseFontSize * .925; // 13px to 12px
+  line-height: @baseLineHeight;
+  background-color: #f5f5f5;
+  border: 1px solid #ccc; // fallback for IE7-8
+  border: 1px solid rgba(0,0,0,.15);
+  .border-radius(4px);
+  white-space: pre;
+  white-space: pre-wrap;
+  word-break: break-all;
+  word-wrap: break-word;
+
+  // Make prettyprint styles more spaced out for readability
+  &.prettyprint {
+    margin-bottom: @baseLineHeight;
+  }
+
+  // Account for some code outputs that place code tags in pre tags
+  code {
+    padding: 0;
+    color: inherit;
+    background-color: transparent;
+    border: 0;
+  }
+}
+
+// Enable scrollable blocks of code
+.pre-scrollable {
+  max-height: 340px;
+  overflow-y: scroll;
+}

File client/less/component-animations.less

View file
+// COMPONENT ANIMATIONS
+// --------------------
+
+.fade {
+  .transition(opacity .15s linear);
+  opacity: 0;
+  &.in {
+    opacity: 1;
+  }
+}
+
+.collapse {
+  .transition(height .35s ease);
+  position:relative;
+  overflow:hidden;
+  height: 0;
+  &.in {
+    height: auto;
+  }
+}

File client/less/dropdowns.less

View file
+// DROPDOWN MENUS
+// --------------
+
+// Use the .menu class on any <li> element within the topbar or ul.tabs and you'll get some superfancy dropdowns
+.dropdown {
+  position: relative;
+}
+.dropdown-toggle {
+  // The caret makes the toggle a bit too tall in IE7
+  *margin-bottom: -3px;
+}
+.dropdown-toggle:active,
+.open .dropdown-toggle {
+  outline: 0;
+}
+
+// Dropdown arrow/caret
+// --------------------
+.caret {
+  display: inline-block;
+  width: 0;
+  height: 0;
+  vertical-align: top;
+  border-left:  4px solid transparent;
+  border-right: 4px solid transparent;
+  border-top:   4px solid @black;
+  .opacity(30);
+  content: "";
+}
+
+// Place the caret
+.dropdown .caret {
+  margin-top: 8px;
+  margin-left: 2px;
+}
+.dropdown:hover .caret,
+.open.dropdown .caret {
+  .opacity(100);
+}
+
+// The dropdown menu (ul)
+// ----------------------
+.dropdown-menu {
+  position: absolute;
+  top: 100%;
+  left: 0;
+  z-index: @zindexDropdown;
+  float: left;
+  display: none; // none by default, but block on "open" of the menu
+  min-width: 160px;
+  padding: 4px 0;
+  margin: 0; // override default ul
+  list-style: none;
+  background-color: @dropdownBackground;
+  border-color: #ccc;
+  border-color: rgba(0,0,0,.2);
+  border-style: solid;
+  border-width: 1px;
+  .border-radius(0 0 5px 5px);
+  .box-shadow(0 5px 10px rgba(0,0,0,.2));
+  -webkit-background-clip: padding-box;
+     -moz-background-clip: padding;
+          background-clip: padding-box;
+  *border-right-width: 2px;
+  *border-bottom-width: 2px;
+
+  // Aligns the dropdown menu to right
+  &.pull-right {
+    right: 0;
+    left: auto;
+  }
+
+  // Dividers (basically an hr) within the dropdown
+  .divider {
+    .nav-divider();
+  }
+
+  // Links within the dropdown menu
+  a {
+    display: block;
+    padding: 3px 15px;
+    clear: both;
+    font-weight: normal;
+    line-height: @baseLineHeight;
+    color: @dropdownLinkColor;
+    white-space: nowrap;
+  }
+}
+
+// Hover state
+// -----------
+.dropdown-menu li > a:hover,
+.dropdown-menu .active > a,
+.dropdown-menu .active > a:hover {
+  color: @dropdownLinkColorHover;
+  text-decoration: none;
+  background-color: @dropdownLinkBackgroundHover;
+}
+
+// Open state for the dropdown
+// ---------------------------
+.dropdown.open {
+  // IE7's z-index only goes to the nearest positioned ancestor, which would
+  // make the menu appear below buttons that appeared later on the page
+  *z-index: @zindexDropdown;
+
+  .dropdown-toggle {
+    color: @white;
+    background: #ccc;
+    background: rgba(0,0,0,.3);
+  }
+  .dropdown-menu {
+    display: block;
+  }
+}
+
+// Right aligned dropdowns
+.pull-right .dropdown-menu {
+  left: auto;
+  right: 0;
+}
+
+// Allow for dropdowns to go bottom up (aka, dropup-menu)
+// ------------------------------------------------------
+// Just add .dropup after the standard .dropdown class and you're set, bro.
+// TODO: abstract this so that the navbar fixed styles are not placed here?
+.dropup,
+.navbar-fixed-bottom .dropdown {
+  // Reverse the caret
+  .caret {
+    border-top: 0;
+    border-bottom: 4px solid @black;
+    content: "\2191";
+  }
+  // Different positioning for bottom up menu
+  .dropdown-menu {
+    top: auto;
+    bottom: 100%;
+    margin-bottom: 1px;
+  }
+}
+
+// Typeahead
+// ---------
+.typeahead {
+  margin-top: 2px; // give it some space to breathe
+  .border-radius(4px);
+}

File client/less/forms.less

View file
+// Forms.less
+// Base styles for various input types, form layouts, and states
+// -------------------------------------------------------------
+
+
+// GENERAL STYLES
+// --------------
+
+// Make all forms have space below them
+form {
+  margin: 0 0 @baseLineHeight;
+}
+
+fieldset {
+  padding: 0;
+  margin: 0;
+  border: 0;
+}
+
+// Groups of fields with labels on top (legends)
+legend {
+  display: block;
+  width: 100%;
+  padding: 0;
+  margin-bottom: @baseLineHeight * 1.5;
+  font-size: @baseFontSize * 1.5;
+  line-height: @baseLineHeight * 2;
+  color: @grayDark;
+  border: 0;
+  border-bottom: 1px solid #eee;
+
+  // Small
+  small {
+    font-size: @baseLineHeight * .75;
+    color: @grayLight;
+  }
+}
+
+// Set font for forms
+label,
+input,
+button,
+select,
+textarea {
+  #font > .shorthand(@baseFontSize,normal,@baseLineHeight); // Set size, weight, line-height here
+}
+input,
+button,
+select,
+textarea {
+  font-family: @baseFontFamily; // And only set font-family here for those that need it (note the missing label element)
+}
+
+// Identify controls by their labels
+label {
+  display: block;
+  margin-bottom: 5px;
+  color: @grayDark;
+}
+
+// Inputs, Textareas, Selects
+input,
+textarea,
+select,
+.uneditable-input {
+  display: inline-block;
+  width: 210px;
+  height: @baseLineHeight;
+  padding: 4px;
+  margin-bottom: 9px;
+  font-size: @baseFontSize;
+  line-height: @baseLineHeight;
+  color: @gray;
+  border: 1px solid @inputBorder;
+  .border-radius(3px);
+}
+.uneditable-textarea {
+  width: auto;
+  height: auto;
+}
+
+// Inputs within a label
+label input,
+label textarea,
+label select {
+  display: block;
+}
+
+// Mini reset for unique input types
+input[type="image"],
+input[type="checkbox"],
+input[type="radio"] {
+  width: auto;
+  height: auto;
+  padding: 0;
+  margin: 3px 0;
+  *margin-top: 0; /* IE7 */
+  line-height: normal;
+  cursor: pointer;
+  .border-radius(0);
+  border: 0 \9; /* IE9 and down */
+}
+input[type="image"] {
+  border: 0;
+}
+
+// Reset the file input to browser defaults
+input[type="file"] {
+  width: auto;
+  padding: initial;
+  line-height: initial;
+  border: initial;
+  background-color: @inputBackground;
+  background-color: initial;
+  .box-shadow(none);
+}
+
+// Help out input buttons
+input[type="button"],
+input[type="reset"],
+input[type="submit"] {
+  width: auto;
+  height: auto;
+}
+
+// Set the height of select and file controls to match text inputs
+select,
+input[type="file"] {
+  height: 28px; /* In IE7, the height of the select element cannot be changed by height, only font-size */
+  *margin-top: 4px; /* For IE7, add top margin to align select with labels */
+  line-height: 28px;
+}
+
+// Reset line-height for IE
+input[type="file"] {
+  line-height: 18px \9;
+}
+
+// Chrome on Linux and Mobile Safari need background-color
+select {
+  width: 220px; // default input width + 10px of padding that doesn't get applied
+  background-color: @inputBackground;
+}
+
+// Make multiple select elements height not fixed
+select[multiple],
+select[size] {
+  height: auto;
+}
+
+// Remove shadow from image inputs
+input[type="image"] {
+  .box-shadow(none);
+}
+
+// Make textarea height behave
+textarea {
+  height: auto;
+}
+
+// Hidden inputs
+input[type="hidden"] {
+  display: none;
+}
+
+
+
+// CHECKBOXES & RADIOS
+// -------------------
+
+// Indent the labels to position radios/checkboxes as hanging
+.radio,
+.checkbox {
+  padding-left: 18px;
+}
+.radio input[type="radio"],
+.checkbox input[type="checkbox"] {
+  float: left;
+  margin-left: -18px;
+}
+
+// Move the options list down to align with labels
+.controls > .radio:first-child,
+.controls > .checkbox:first-child {
+  padding-top: 5px; // has to be padding because margin collaspes
+}
+
+// Radios and checkboxes on same line
+// TODO v3: Convert .inline to .control-inline
+.radio.inline,
+.checkbox.inline {
+  display: inline-block;
+  padding-top: 5px;
+  margin-bottom: 0;
+  vertical-align: middle;
+}
+.radio.inline + .radio.inline,
+.checkbox.inline + .checkbox.inline {
+  margin-left: 10px; // space out consecutive inline controls
+}
+
+
+
+// FOCUS STATE
+// -----------
+
+input,
+textarea {
+  .box-shadow(inset 0 1px 1px rgba(0,0,0,.075));
+  @transition: border linear .2s, box-shadow linear .2s;
+  .transition(@transition);
+}
+input:focus,
+textarea:focus {
+  border-color: rgba(82,168,236,.8);
+  @shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6);
+  .box-shadow(@shadow);
+  outline: 0;
+  outline: thin dotted \9; /* IE6-9 */
+}
+input[type="file"]:focus,
+input[type="radio"]:focus,
+input[type="checkbox"]:focus,
+select:focus {
+  .box-shadow(none); // override for file inputs
+  .tab-focus();
+}
+
+
+
+// INPUT SIZES
+// -----------
+
+// General classes for quick sizes
+.input-mini       { width: 60px; }
+.input-small      { width: 90px; }
+.input-medium     { width: 150px; }
+.input-large      { width: 210px; }
+.input-xlarge     { width: 270px; }
+.input-xxlarge    { width: 530px; }
+
+// Grid style input sizes
+input[class*="span"],
+select[class*="span"],
+textarea[class*="span"],
+.uneditable-input {
+  float: none;
+  margin-left: 0;
+}
+
+
+
+// GRID SIZING FOR INPUTS
+// ----------------------
+
+#grid > .input (@gridColumnWidth, @gridGutterWidth);
+
+
+
+
+// DISABLED STATE
+// --------------
+
+// Disabled and read-only inputs
+input[disabled],
+select[disabled],
+textarea[disabled],
+input[readonly],
+select[readonly],
+textarea[readonly] {
+  background-color: @inputDisabledBackground;
+  border-color: #ddd;
+  cursor: not-allowed;
+}
+
+
+
+
+// FORM FIELD FEEDBACK STATES
+// --------------------------
+
+// Warning
+.control-group.warning {
+  .formFieldState(@warningText, @warningText, @warningBackground);
+}
+// Error
+.control-group.error {
+  .formFieldState(@errorText, @errorText, @errorBackground);
+}
+// Success
+.control-group.success {
+  .formFieldState(@successText, @successText, @successBackground);
+}
+
+// HTML5 invalid states
+// Shares styles with the .control-group.error above
+input:focus:required:invalid,
+textarea:focus:required:invalid,
+select:focus:required:invalid {
+  color: #b94a48;
+  border-color: #ee5f5b;
+  &:focus {
+    border-color: darken(#ee5f5b, 10%);
+    .box-shadow(0 0 6px lighten(#ee5f5b, 20%));
+  }
+}
+
+
+
+// FORM ACTIONS
+// ------------
+
+.form-actions {
+  padding: (@baseLineHeight - 1) 20px @baseLineHeight;
+  margin-top: @baseLineHeight;
+  margin-bottom: @baseLineHeight;
+  background-color: @grayLighter;
+  border-top: 1px solid #ddd;
+  .clearfix(); // Adding clearfix to allow for .pull-right button containers
+}
+
+// For text that needs to appear as an input but should not be an input
+.uneditable-input {
+  display: block;
+  background-color: @inputBackground;
+  border-color: #eee;
+  .box-shadow(inset 0 1px 2px rgba(0,0,0,.025));
+  cursor: not-allowed;
+}
+
+// Placeholder text gets special styles; can't be bundled together though for some reason
+.placeholder(@grayLight);
+
+
+
+// HELP TEXT
+// ---------
+
+.help-block,
+.help-inline {
+  color: @gray; // lighten the text some for contrast
+}
+
+.help-block {
+  display: block; // account for any element using help-block
+  margin-bottom: @baseLineHeight / 2;
+}
+
+.help-inline {
+  display: inline-block;
+  .ie7-inline-block();
+  vertical-align: middle;
+  padding-left: 5px;
+}
+
+
+
+// INPUT GROUPS
+// ------------
+
+// Allow us to put symbols and text within the input field for a cleaner look
+.input-prepend,
+.input-append {
+  margin-bottom: 5px;
+  input,
+  select,
+  .uneditable-input {
+    *margin-left: 0;
+    .border-radius(0 3px 3px 0);
+    &:focus {
+      position: relative;
+      z-index: 2;
+    }
+  }
+  .uneditable-input {
+    border-left-color: #ccc;
+  }
+  .add-on {
+    display: inline-block;
+    width: auto;
+    min-width: 16px;
+    height: @baseLineHeight;
+    padding: 4px 5px;
+    font-weight: normal;
+    line-height: @baseLineHeight;
+    text-align: center;
+    text-shadow: 0 1px 0 @white;
+    vertical-align: middle;
+    background-color: @grayLighter;
+    border: 1px solid #ccc;
+  }
+  .add-on,
+  .btn {
+    .border-radius(3px 0 0 3px);
+  }
+  .active {
+    background-color: lighten(@green, 30);
+    border-color: @green;
+  }
+}
+.input-prepend {
+  .add-on,
+  .btn {
+    margin-right: -1px;
+  }
+}
+.input-append {
+  input,
+  select
+  .uneditable-input {
+    .border-radius(3px 0 0 3px);
+  }
+  .uneditable-input {
+    border-left-color: #eee;
+    border-right-color: #ccc;
+  }
+  .add-on,
+  .btn {
+    margin-left: -1px;
+    .border-radius(0 3px 3px 0);
+  }
+}
+// Remove all border-radius for inputs with both prepend and append
+.input-prepend.input-append {
+  input,
+  select,
+  .uneditable-input {
+    .border-radius(0);
+  }
+  .add-on:first-child,
+  .btn:first-child {
+    margin-right: -1px;
+    .border-radius(3px 0 0 3px);
+  }
+  .add-on:last-child,
+  .btn:last-child {
+    margin-left: -1px;
+    .border-radius(0 3px 3px 0);
+  }
+}
+
+
+
+// SEARCH FORM
+// -----------
+
+.search-query {
+  padding-left: 14px;
+  padding-right: 14px;
+  margin-bottom: 0; // remove the default margin on all inputs
+  .border-radius(14px);
+}
+
+
+
+// HORIZONTAL & VERTICAL FORMS
+// ---------------------------
+
+// Common properties
+// -----------------
+
+.form-search,
+.form-inline,
+.form-horizontal {
+  input,
+  textarea,
+  select,
+  .help-inline,
+  .uneditable-input,
+  .input-prepend,
+  .input-append {
+    display: inline-block;
+    margin-bottom: 0;
+  }
+  // Re-hide hidden elements due to specifity
+  .hide {
+    display: none;
+  }
+}
+.form-search label,
+.form-inline label {
+  display: inline-block;
+}
+// Remove margin for input-prepend/-append
+.form-search .input-append,
+.form-inline .input-append,
+.form-search .input-prepend,
+.form-inline .input-prepend {
+  margin-bottom: 0;
+}
+// Inline checkbox/radio labels (remove padding on left)
+.form-search .radio,
+.form-search .checkbox,
+.form-inline .radio,
+.form-inline .checkbox {
+  padding-left: 0;
+  margin-bottom: 0;
+  vertical-align: middle;
+}
+// Remove float and margin, set to inline-block
+.form-search .radio input[type="radio"],
+.form-search .checkbox input[type="checkbox"],
+.form-inline .radio input[type="radio"],
+.form-inline .checkbox input[type="checkbox"] {
+  float: left;
+  margin-left: 0;
+  margin-right: 3px;
+}
+
+
+// Margin to space out fieldsets
+.control-group {
+  margin-bottom: @baseLineHeight / 2;
+}
+
+// Legend collapses margin, so next element is responsible for spacing
+legend + .control-group {
+  margin-top: @baseLineHeight;
+  -webkit-margin-top-collapse: separate;
+}
+
+// Horizontal-specific styles
+// --------------------------
+
+.form-horizontal {
+  // Increase spacing between groups
+  .control-group {
+    margin-bottom: @baseLineHeight;
+    .clearfix();
+  }
+  // Float the labels left
+  .control-label {
+    float: left;
+    width: 140px;
+    padding-top: 5px;
+    text-align: right;
+  }
+  // Move over all input controls and content
+  .controls {
+    margin-left: 160px;
+    /* Super jank IE7 fix to ensure the inputs in .input-append and input-prepend don't inherit the margin of the parent, in this case .controls */
+    *display: inline-block;
+    *margin-left: 0;
+    *padding-left: 20px;
+  }
+  // Remove bottom margin on block level help text since that's accounted for on .control-group
+  .help-block {
+    margin-top: @baseLineHeight / 2;
+    margin-bottom: 0;
+  }
+  // Move over buttons in .form-actions to align with .controls
+  .form-actions {
+    padding-left: 160px;
+  }
+}

File client/less/grid.less

View file
+// Fixed (940px)
+#grid > .core(@gridColumnWidth, @gridGutterWidth);
+
+// Fluid (940px)
+#grid > .fluid(@fluidGridColumnWidth, @fluidGridGutterWidth);

File client/less/hero-unit.less