From 9361293af334636e4563c0ed4d42e396db74d997 Mon Sep 17 00:00:00 2001 From: Sacha Chua Date: Mon, 16 Jan 2012 17:43:40 -0500 Subject: [PATCH] Context-related changes --- app/assets/stylesheets/style.css.sass | 6 ++ app/controllers/application_controller.rb | 9 ++- app/controllers/clothing_controller.rb | 13 ++++ app/controllers/contexts_controller.rb | 56 +++++++++------ app/controllers/stuff_controller.rb | 21 +++--- app/controllers/users_controller.rb | 11 ++- app/helpers/application_helper.rb | 7 +- app/helpers/stuff_helper.rb | 28 ++++++++ app/models/ability.rb | 20 +++--- app/models/clothing.rb | 2 +- app/models/context.rb | 25 ++----- app/models/context_rule.rb | 7 ++ app/models/location_history.rb | 2 +- app/models/memory.rb | 4 ++ app/models/stuff.rb | 17 ++--- app/models/user.rb | 14 ++-- app/views/application/_footer.html.haml | 17 +++++ app/views/application/_main_nav.html.haml | 13 ++-- app/views/contexts/_form.html.haml | 26 ++++--- app/views/contexts/edit.html.haml | 3 +- app/views/contexts/index.html.haml | 34 +++++---- app/views/contexts/start.html.haml | 21 +++--- app/views/layouts/application.html.haml | 15 +--- app/views/records/index.html.haml | 4 +- app/views/registrations/_form.html.haml | 2 +- app/views/stuff/_form.html.haml | 7 +- app/views/stuff/_nav.html.haml | 5 ++ app/views/stuff/_quicklog.html.haml | 4 +- app/views/stuff/edit.html.haml | 2 +- app/views/stuff/index.html.haml | 21 +++--- app/views/stuff/show.html.haml | 67 ++++++++---------- app/views/users/_form.html.haml | 15 ++-- config/initializers/paperclip.rb | 3 + config/routes.rb | 5 +- ...1056_add_stuff_type_and_merge_locations.rb | 22 ++++++ ...20115171633_drop_polymorphic_from_stuff.rb | 10 +++ ...0120115184226_change_location_histories.rb | 9 +++ .../20120115193034_create_context_rules.rb | 10 +++ ...20115215056_change_context_to_serialize.rb | 21 ++++++ db/schema.rb | 16 +++-- public/stylesheets/style.css.css | 69 +++++++++++-------- spec/factories/context_rules.rb | 9 +++ spec/models/context_rule_spec.rb | 5 ++ 43 files changed, 447 insertions(+), 230 deletions(-) create mode 100644 app/models/context_rule.rb create mode 100644 app/views/application/_footer.html.haml create mode 100644 app/views/stuff/_nav.html.haml create mode 100644 config/initializers/paperclip.rb create mode 100644 db/migrate/20120115051056_add_stuff_type_and_merge_locations.rb create mode 100644 db/migrate/20120115171633_drop_polymorphic_from_stuff.rb create mode 100644 db/migrate/20120115184226_change_location_histories.rb create mode 100644 db/migrate/20120115193034_create_context_rules.rb create mode 100644 db/migrate/20120115215056_change_context_to_serialize.rb create mode 100644 spec/factories/context_rules.rb create mode 100644 spec/models/context_rule_spec.rb diff --git a/app/assets/stylesheets/style.css.sass b/app/assets/stylesheets/style.css.sass index c75a918..3952f5a 100644 --- a/app/assets/stylesheets/style.css.sass +++ b/app/assets/stylesheets/style.css.sass @@ -32,6 +32,8 @@ li.input form .clear-fix margin-bottom: 10px zoom: 1 +.row + margin-left: 0px .actions .btn margin-right: 10px .category @@ -123,3 +125,7 @@ input.imagebtn color: #BFBFBF a[data-method].btn color: #000 +a[data-method].btn.primary + color: #fff +.input table + width: auto diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index b4c1c59..5704a85 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -23,6 +23,9 @@ class ApplicationController < ActionController::Base def before_awesome notice_layout! @account = current_account + # Set the timezone + Time.zone = @account.settings.timezone if @account.settings.timezone + true end def notice_layout! @@ -45,7 +48,11 @@ def current_account end def after_sign_in_path_for(resource) - params[:destination] || stored_location_for(resource) || root_path + if !params[:destination].blank? + params[:destination] + else + stored_location_for(resource) || root_path + end end def filter_sortable_column_order(list) diff --git a/app/controllers/clothing_controller.rb b/app/controllers/clothing_controller.rb index e959952..3a993ce 100644 --- a/app/controllers/clothing_controller.rb +++ b/app/controllers/clothing_controller.rb @@ -271,4 +271,17 @@ def save_color end + + def download_thumbnail + @clothing = current_account.clothing.find(params[:id]) + authorize! :view, @clothing + response.headers['X-Accel-Redirect'] = '/protected/' + @clothing.image.url + response.headers['Content-Type'] = @clothing.image_content_type + response.headers['Content-Disposition'] = "inline; filename=#{@clothing.image_file_name}" + #Make sure we don't render anything + render :nothing => true +# send_file @clothing.image.path, :type => @clothing.image_content_type, :disposition => 'inline' + + end + end diff --git a/app/controllers/contexts_controller.rb b/app/controllers/contexts_controller.rb index ff76bd9..7d31489 100644 --- a/app/controllers/contexts_controller.rb +++ b/app/controllers/contexts_controller.rb @@ -25,6 +25,7 @@ def show def new authorize! :create, Context @context = Context.new + 5.times do @context.context_rules.build end respond_to do |format| format.html # new.html.erb format.xml { render :xml => @context } @@ -34,6 +35,7 @@ def new # GET /contexts/1/edit def edit @context = current_account.contexts.find(params[:id]) + 5.times do @context.context_rules.build end authorize! :update, @context end @@ -41,8 +43,17 @@ def edit # POST /contexts.xml def create authorize! :create, Context - @context = Context.new(params[:context]) - @context.user = current_account + # Change context_rules_attributes to stuff and locations + rules = params[:context].delete :context_rules_attributes if params[:context] + @context = current_account.contexts.new(params[:context]) + if rules + rules.each do |k, v| + next if v['stuff'].blank? or v['location'].blank? + stuff = @account.stuff.find_or_create_by_name(v['stuff']) + location = @account.get_location(v['location']) + @context.context_rules.build(:stuff => stuff, :location => location) + end + end respond_to do |format| if @context.save format.html { redirect_to(@context, :notice => 'Context was successfully created.') } @@ -59,6 +70,23 @@ def create def update @context = current_account.contexts.find(params[:id]) authorize! :update, @context + rules = params[:context][:context_rules_attributes] if params[:context] + if rules + rules.each do |k, v| + if v['stuff'].blank? or v['location'].blank? + params[:context][:context_rules_attributes][k]['_destroy'] = 1 + else + location = @account.get_location(v['location']) + stuff = @account.stuff.find_by_name(v['stuff']) + if stuff.nil? + stuff = @account.stuff.create(:name => v['stuff'], :location => location, :home_location => location, :status => 'active', :stuff_type => 'stuff') + end + params[:context][:context_rules_attributes][k]['stuff'] = stuff + params[:context][:context_rules_attributes][k]['location'] = location + end + end + end + logger.info "New context rules attributes " + params[:context][:context_rules_attributes].inspect respond_to do |format| if @context.update_attributes(params[:context]) format.html { redirect_to(@context, :notice => 'Context was successfully updated.') } @@ -87,28 +115,16 @@ def start # Parse the list of items in this context @context = current_account.contexts.find(params[:id]) authorize! :start, @context - @stuff = @context.stuff_rules - @in_place = Array.new - @out_of_place = Array.new - @stuff.each do |name, val| - if val[:in_place] - @in_place << name - else - @out_of_place << name - end - end + @in_place = @context.context_rules.in_place + @out_of_place = @context.context_rules.out_of_place end def complete + authorize! :manage_account, current_account @context = current_account.contexts.find(params[:id]) - authorize! :start, @context - @stuff = @context.stuff_rules - @stuff.each do |key, stuff| - unless stuff[:in_place] - stuff[:stuff].location = current_account.get_location(stuff[:destination]) - stuff[:stuff].save! - end + @context.context_rules.out_of_place.each do |r| + r.stuff.update_attributes(:location => r.location) end - redirect_to start_context_path(@context) + go_to stuff_index_path, :notice => "Context marked complete." end end diff --git a/app/controllers/stuff_controller.rb b/app/controllers/stuff_controller.rb index d650309..48fc74a 100644 --- a/app/controllers/stuff_controller.rb +++ b/app/controllers/stuff_controller.rb @@ -1,4 +1,6 @@ class StuffController < ApplicationController + autocomplete :stuff, :name, :full => true + skip_authorization_check :only => [:autocomplete_stuff_name] load_and_authorize_resource handles_sortable_columns # GET /stuff @@ -15,7 +17,7 @@ def index "name DESC" end end - @stuff = current_account.stuff.order(order).includes(:location) + @stuff = current_account.stuff.order(order).includes(:location).where(:stuff_type => 'stuff') if params[:status] and params[:status] != 'all' @stuff = @stuff.where('status=?', 'stuff') else @@ -30,17 +32,13 @@ def index end def log - @stuff = Stuff.find(:first, :conditions => [ 'lower(name) = ?', params[:stuff_name].strip.downcase ]) + @stuff = current_account.stuff.find(:first, :conditions => [ 'lower(name) = ?', params[:stuff_name].strip.downcase ]) unless @stuff - @stuff = Stuff.new(:name => params[:stuff_name].strip, :status => 'active') + @stuff = current_account.stuff.new(:name => params[:stuff_name].strip, :status => 'active', :stuff_type => 'stuff', :location => @location) @stuff.user = current_account end @location = current_account.get_location(params[:location_name]) @stuff.location = @location - logger.info "Stuff: #{@stuff.id}" - logger.info "Location: #{@location.id}" - logger.info "New location: #{@stuff.location.id}" - logger.info "New location: #{@stuff.location.id}" result = @stuff.save! redirect_to params[:destination] || stuff_index_path, :notice => (result ? 'Logged' : 'Problem?') and return end @@ -58,7 +56,7 @@ def show # GET /stuff/new # GET /stuff/new.xml def new - @stuff = Stuff.new + @stuff = current_account.stuff.new respond_to do |format| format.html # new.html.erb @@ -79,7 +77,7 @@ def create loc = current_account.get_location(params[:stuff][:home_location_id]) params[:stuff].delete(:home_location_id) end - @stuff = Stuff.new(params[:stuff]) + @stuff = current_account.stuff.new(params[:stuff]) @stuff.home_location = loc @stuff.location = @stuff.home_location @stuff.user = current_account @@ -131,4 +129,9 @@ def destroy format.xml { head :ok } end end + + def get_autocomplete_items(parameters) + super(parameters).where(:user_id => current_account.id) + end + end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index f478305..70c94e3 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -65,9 +65,18 @@ def update params[:user].delete(:password) params[:user].delete(:password_confirmation) end + if params[:user][:settings] + settings = params[:user][:settings] + @user.settings.timezone = settings['time_zone'] + logger.info "Trying to set timezone? " + @user.settings.timezone + params[:user].delete(:settings) + end respond_to do |format| if @user.update_attributes(params[:user]) - format.html { redirect_to(@user, :notice => 'User was successfully updated.') } + format.html { + logger.info "Did we keep the timezone? " + @user.settings.timezone + + redirect_to(root_path, :notice => 'User was successfully updated.') } format.xml { head :ok } else format.html { render :action => "edit" } diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 8fe6e5f..019b73c 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -135,7 +135,12 @@ def actions(o) if can? :manage_account, current_account actions << link_to('Edit', edit_record_path(o)) actions << link_to('Clone', clone_record_path(o), :method => :post) - actions << link_to('Destroy', o, :confirm => 'Are you sure?', :method => :delete) + actions << link_to('Delete', o, :confirm => 'Are you sure?', :method => :delete) + end + elsif o.is_a? Context + if managing? + actions << link_to('Edit', edit_context_path(o)) + actions << link_to('Start', start_context_path(o)) end end actions diff --git a/app/helpers/stuff_helper.rb b/app/helpers/stuff_helper.rb index 0db8e4f..7ecad47 100644 --- a/app/helpers/stuff_helper.rb +++ b/app/helpers/stuff_helper.rb @@ -1,2 +1,30 @@ module StuffHelper + def name_and_location(stuff) + s = stuff.name + if stuff.location + s += ' < ' + stuff.hierarchy.map {|l| link_to h(l.name), l}.join(h(' < ')).html_safe + end + if managing? + if stuff.stuff_type == 'stuff' and stuff.home_location and stuff.location != stuff.home_location + s += ' ' + link_to("(return to #{stuff.home_location.name})", log_stuff_path(:stuff_name => stuff.name, :location_name => stuff.home_location.name), :method => :post) + end + end + s + end + + def move_link_to(stuff, location) + if managing? + s = link_to location.name, log_stuff_path(:stuff_name => stuff.name, :location_name => location.name), :method => :post + s += ' (' + s += link_to 'view', location + s += ')' + s + else + link_to location.name, location + end + end + + def location_list(stuff, list) + list.map { |location| move_link_to(stuff, location) }.join(', ').html_safe + end end diff --git a/app/models/ability.rb b/app/models/ability.rb index b530136..468497a 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -6,30 +6,26 @@ def initialize(user) if user.role == 'admin' can :manage, :all elsif !user.id.blank? - [Clothing, ClothingLog, ClothingMatch, CsaFood, Day, DecisionLog, Decision, Food, LibraryItem, LocationHistory, Location, MeasurementLog, Measurement, Stuff, TimeRecord, TorontoLibrary, Context, Memory, TapLogRecord, RecordCategory].each do |item| + [Clothing, ClothingLog, Context, ClothingMatch, CsaFood, Day, DecisionLog, Decision, Food, LibraryItem, LocationHistory, Location, MeasurementLog, Measurement, Stuff, TimeRecord, TorontoLibrary, Memory, TapLogRecord, RecordCategory].each do |item| can :manage, item, :user_id => user.id can :create, item end can :manage_account, User, :id => user.id - can :view_library_items, User - can :view_contexts, User can :view_tap_log_records, User, :id => user.id can :view_time, User can :send_feedback, User - else # Not logged in - can :view, LibraryItem, :public => true - can :view, Memory, :access => 'public' - can :view_contexts, User end - [:view_locations, :view_dashboard, :view_clothing, :view_time, :view_library_items, :view_memories, :view_tap_log_records].each do |sym| + can :view, LibraryItem do |o| o.public? and o.user.demo? end + can :view, Memory do |o| o.public? and o.user.demo? end + [:view_contexts, :view_locations, :view_dashboard, :view_clothing, :view_time, :view_library_items, :view_memories, :view_tap_log_records].each do |sym| can sym, User do |u| u.id == 1 || u.id == user.id end end - can :view, Clothing - can :view, TapLogRecord - can :view_note, TapLogRecord do |u| - (u.user_id == 1 && !u.private?) || u.user_id = user.id + can :view, Clothing do |o| o.user.demo? end + can :view, TapLogRecord do |o| o.user.demo? end + can :view_note, TapLogRecord do |o| + (!o.private? and o.user.demo?) || (o.user_id == user.id) end can :view_site, User can :send_feedback, User diff --git a/app/models/clothing.rb b/app/models/clothing.rb index bbf2507..81571d5 100644 --- a/app/models/clothing.rb +++ b/app/models/clothing.rb @@ -3,7 +3,7 @@ class Clothing < ActiveRecord::Base acts_as_taggable_on :tags has_many :clothing_logs has_many :clothing_matches, :foreign_key => :clothing_a_id - has_attached_file :image, :styles => { :large => "400x400", :medium => "x90", :small => "x40" }, :default_url => '/images/clothing/:style/missing.jpg' + has_attached_file :image, :styles => { :large => "400x400", :medium => "x90", :small => "x40" }, :default_url => '/images/clothing/:style/missing.jpg', :path => ':rails_root/files/clothing/:user_id/:id/:style/:basename.:extension', :url => '/files/clothing/:user_id/:id/:style/:basename.:extension' before_save :update_hsl def autocomplete_view diff --git a/app/models/context.rb b/app/models/context.rb index 97bad7a..22db108 100644 --- a/app/models/context.rb +++ b/app/models/context.rb @@ -1,24 +1,11 @@ class Context < ActiveRecord::Base belongs_to :user - def rules_array - self.rules.split /[\r\n]+/ - end + has_many :context_rules + accepts_nested_attributes_for :context_rules, :allow_destroy => true + validates_presence_of :name + before_save :update_rules - def stuff_rules - rules = self.rules_array - stuff = Hash.new { |h,k| h[k] = Hash.new } - rules.each do |r| - matches = r.match(/^stuff:[ \t]*([^,]+),[ \t]*(.*)/) - if matches - stuff[matches[1]][:destination] = matches[2] - end - end - stuff_hash = self.user.stuff.includes(:location).where('name in (?)', stuff.keys) - stuff_hash.each do |s| - stuff[s.name][:stuff] = s - stuff[s.name][:in_place] = (s.location and s.location.name == stuff[s.name][:destination]) - end - stuff + def update_rules + self.rules = self.context_rules.includes(:stuff).order('LOWER(stuff.name)').map { |x| x.stuff.name }.join(', ') end - end diff --git a/app/models/context_rule.rb b/app/models/context_rule.rb new file mode 100644 index 0000000..080e9a5 --- /dev/null +++ b/app/models/context_rule.rb @@ -0,0 +1,7 @@ +class ContextRule < ActiveRecord::Base + belongs_to :stuff + belongs_to :location, :class_name => 'Stuff' + belongs_to :context + scope :out_of_place, includes(:stuff).where('(stuff.location_id IS NULL OR stuff.location_id != context_rules.location_id)') + scope :in_place, includes(:stuff).where('stuff.location_id = context_rules.location_id') +end diff --git a/app/models/location_history.rb b/app/models/location_history.rb index 84517f1..d41d6de 100644 --- a/app/models/location_history.rb +++ b/app/models/location_history.rb @@ -1,5 +1,5 @@ class LocationHistory < ActiveRecord::Base belongs_to :user - belongs_to :location, :polymorphic => true + belongs_to :location, :class_name => 'Stuff' belongs_to :stuff end diff --git a/app/models/memory.rb b/app/models/memory.rb index 766a700..3e1d6e0 100644 --- a/app/models/memory.rb +++ b/app/models/memory.rb @@ -7,4 +7,8 @@ class Memory < ActiveRecord::Base def private? self.access != 'public' end + + def public? + self.access == 'public' + end end diff --git a/app/models/stuff.rb b/app/models/stuff.rb index 45bb397..2b91367 100644 --- a/app/models/stuff.rb +++ b/app/models/stuff.rb @@ -3,18 +3,22 @@ class Stuff < ActiveRecord::Base delegate :url_helpers, :to => 'Rails.application.routes' has_many :location_histories - belongs_to :location, :polymorphic => true - belongs_to :home_location, :polymorphic => true - has_many :stuff, :through => :stuff, :foreign_key => :location_id + belongs_to :location, :class_name => 'Stuff' + belongs_to :home_location, :class_name => 'Stuff' + has_many :context_rules + has_many :contexts, :through => :context_rules + has_many :contained_stuff, :class_name => 'Stuff', :foreign_key => :location_id before_save :update_in_place + scope :locations, where(:stuff_type => 'location') + scope :out_of_place, where('location_id != home_location_id') def update_in_place self.in_place = (self.location and self.home_location and self.location == self.home_location) true end def distinct_locations - LocationHistory.where('stuff_id=?', self.id).group('location_id, location_type') + self.location_histories.group('location_id') end def set_location(sym, val) @@ -43,8 +47,5 @@ def hierarchy list end - def self.out_of_place - Stuff.where('status="active" AND (location_id != home_location_id OR location_type != home_location_type)') - end - + end diff --git a/app/models/user.rb b/app/models/user.rb index 54d0e17..ce790de 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -75,14 +75,11 @@ def memento_mori def get_location(val) if val.is_a? String - if match = val.match(/^([0-9]+)-(Stuff|Location)/) - id = match[1] - model = match[2] - model.classify.constantize.find(id) + if match = val.match(/^([0-9]+)/) + self.stuff.find_by_id(val) else loc = self.stuff.find(:first, :conditions => ['lower(name)=?', val.downcase.strip]) - loc ||= self.locations.find(:first, :conditions => ['lower(name)=?', val.downcase.strip]) - loc ||= self.locations.create(:name => val.strip) + loc ||= self.stuff.create(:name => val.strip, :stuff_type => 'location') end else val @@ -115,6 +112,10 @@ def admin? # end # end + def demo? + self.id == 1 + end + protected # Attempt to find a user by email. If a record is found, send new @@ -158,5 +159,4 @@ def self.find_for_database_authentication(warden_conditions) login = conditions.delete(:login) where(conditions).where(["lower(username) = :value OR lower(email) = :value", { :value => login.downcase }]).first end - end diff --git a/app/views/application/_footer.html.haml b/app/views/application/_footer.html.haml new file mode 100644 index 0000000..0050867 --- /dev/null +++ b/app/views/application/_footer.html.haml @@ -0,0 +1,17 @@ +%footer + .block + %p + Copyright © #{Time.now.year} Sacha Chua - + - if session + - if mobile? + = link_to I18n.t('app.layout.full'), params.merge(:layout => 'full') + - else + = link_to I18n.t('app.layout.mobile'), params.merge(:layout => 'mobile') + \- + = feedback_link "Send feedback" + \- Current timezone: + = @account.settings.timezone + = link_to '(Change?)', edit_user_path(@account) +- if Rails.env.development? + .alert-message.warning This is the development site. +- flash.discard diff --git a/app/views/application/_main_nav.html.haml b/app/views/application/_main_nav.html.haml index 3d6a79e..c406a7e 100644 --- a/app/views/application/_main_nav.html.haml +++ b/app/views/application/_main_nav.html.haml @@ -2,20 +2,21 @@ .fill .container - if current_account - = link_to "quantified awesome: #{current_account.username}", root_path, :class => 'brand' + = link_to "#{current_account.username || current_account.email}", root_path, :class => 'brand' - else = link_to "quantified awesome",root_path, :class => 'brand' %ul.nav %li{:class => active_menu('/stuff')}= link_to 'stuff', stuff_index_path %li{:class => active_menu('/clothing')}= link_to 'clothing', clothing_index_path - %li{:class => active_menu(['/library', '/toronto_library'])}= link_to 'library', library_items_path - %li{:class => active_menu(['/food', '/csa_food'])}= link_to 'food', csa_foods_path - %li{:class => active_menu('/memories')}= link_to 'memories', memories_path - %li{:class => active_menu(['/time', '/tap_log_records'])}= link_to 'time', time_path + - if current_account.demo? + %li{:class => active_menu(['/library', '/toronto_library'])}= link_to 'library', library_items_path + %li{:class => active_menu(['/food', '/csa_food'])}= link_to 'food', csa_foods_path + %li{:class => active_menu('/memories')}= link_to 'memories', memories_path + %li{:class => active_menu(['/time', '/tap_log_records', '/records', '/record_categories'])}= link_to 'time', time_path - if user_signed_in? %li{:class => active_menu('/user')}= link_to 'account', edit_user_path(current_account.id) %li= link_to t("web-app-theme.logout", :default => "log out"), destroy_user_session_path, :method => "delete" - else %li.track= link_to t('app.user.login'), new_user_session_path %li.feedback{:class => active_menu('/feedback')}= feedback_link - \ No newline at end of file + diff --git a/app/views/contexts/_form.html.haml b/app/views/contexts/_form.html.haml index 5156b7e..94a6853 100644 --- a/app/views/contexts/_form.html.haml +++ b/app/views/contexts/_form.html.haml @@ -1,16 +1,24 @@ -= form_for @context do |f| += semantic_form_for @context do |f| -if @context.errors.any? #error_explanation %h2= "#{pluralize(@context.errors.count, "error")} prohibited this context from being saved:" %ul - @context.errors.full_messages.each do |msg| %li= msg - - .field - = f.label :name - = f.text_field :name - .field - = f.label :rules - = f.text_area :rules + = f.inputs do + = f.input :name, :input_html => {:autofocus => true} + .clear-fix + %label Stuff + .input + %table + %tr + %th Stuff + %th Location + = f.fields_for :context_rules do |r| + %tr + %td= r.autocomplete_field :stuff, autocomplete_stuff_path, :value => r.object.stuff ? r.object.stuff.name : '' + %td= r.autocomplete_field :location, autocomplete_stuff_path, :value => r.object.location ? r.object.location.name : '' .actions - = f.submit 'Save' + = f.submit 'Save', :class => 'btn primary' + - unless @context.new_record? + = link_to 'Delete', context_path(@context), :method => :delete, :class => 'btn' diff --git a/app/views/contexts/edit.html.haml b/app/views/contexts/edit.html.haml index c7c523d..398dc46 100644 --- a/app/views/contexts/edit.html.haml +++ b/app/views/contexts/edit.html.haml @@ -1,5 +1,4 @@ -%h1 Editing context - += setup_page "context#{@context.id}", @context.name, 'stuff/nav' = render 'form' = link_to 'Show', @context diff --git a/app/views/contexts/index.html.haml b/app/views/contexts/index.html.haml index a6fee9a..5824af5 100644 --- a/app/views/contexts/index.html.haml +++ b/app/views/contexts/index.html.haml @@ -1,17 +1,25 @@ -%h1 Contexts += setup_page 'contexts', nil, 'stuff/nav' -%table - %tr - %th Name - %th Rules - %th - %th - %th +Sometimes stuff belongs in different places, depending on the context. +For example, you might have a context for going to work, or a context +for when you're home. Defining contexts lets you focus on just the +stuff that you need to take out or return. - - @contexts.each do |context| +- if managing? + %p= link_to 'Create context', new_context_path, :class => 'btn' + +- if @contexts.length > 0 + %table %tr - %td= link_to context.name, context - %td= context.rules + - if managing? + %th Actions + %th Name + %th Rules + + - @contexts.each do |context| + %tr + - if managing? + %td= action_list context + %td= link_to context.name, context + %td= context.rules -- if can? :create, Context - = link_to 'New Context', new_context_path diff --git a/app/views/contexts/start.html.haml b/app/views/contexts/start.html.haml index a94afa3..281ff07 100644 --- a/app/views/contexts/start.html.haml +++ b/app/views/contexts/start.html.haml @@ -1,5 +1,6 @@ -= link_to 'Contexts', contexts_path -= title @context.name += setup_page "context#{@context.id}", @context.name, 'stuff/nav' +- if managing? + %p= link_to 'Edit', edit_context_path(@context) - if @out_of_place.length > 0 %h3 Stuff out of place @@ -11,16 +12,19 @@ %th Current location %tbody - @out_of_place.each do |o| - - stuff = @stuff[o][:stuff] + - stuff = o.stuff %tr{:class => 'stuff_' + stuff.id.to_s} %td= link_to stuff.name, stuff %td - - if can? :update, stuff - = move_stuff_link(stuff, @stuff[o][:destination], request.fullpath).html_safe + - if managing? + = move_stuff_link(stuff, o.location, request.fullpath).html_safe - else = link_to stuff.name, stuff %td= stuff.location ? stuff.location.name : '' - + - if managing? + = link_to 'Complete', complete_context_path(@context.id), :method => :put, :class => 'btn primary', :title => 'Updates all the out-of-place items with their home locations' +- elsif @in_place.length > 0 + Hooray! Everything in its place. - if @in_place.length > 0 %h3 Stuff in place %table.stuff_in_place.lined @@ -30,10 +34,7 @@ %th Current location %tbody - @in_place.each do |o| - - stuff = @stuff[o][:stuff] + - stuff = o.stuff %tr{:class => 'stuff_' + stuff.id.to_s} %td= link_to stuff.name, stuff %td= stuff.location ? stuff.location.name : '' - -- if can? :start, @context - = link_to 'Complete', complete_context_path(@context.id), :method => :put diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index ac58d8e..c99edc3 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -40,17 +40,4 @@ - if content_for? :after_title = yield :after_title = yield - %footer - .block - %p - Copyright © #{Time.now.year} Sacha Chua - - - if session - - if mobile? - = link_to I18n.t('app.layout.full'), params.merge(:layout => 'full') - - else - = link_to I18n.t('app.layout.mobile'), params.merge(:layout => 'mobile') - \- - = feedback_link "Send feedback" - - if Rails.env.development? - .alert-message.warning This is the development site. -- flash.discard + = render 'footer' diff --git a/app/views/records/index.html.haml b/app/views/records/index.html.haml index 3adb3eb..b55f9f4 100644 --- a/app/views/records/index.html.haml +++ b/app/views/records/index.html.haml @@ -1,7 +1,7 @@ = setup_page 'records', nil, 'time/nav' = render 'quick_record' .filters.collapsible.collapsed - %legend Filters [+] + %legend Options [+] .details = form_tag records_path, :method => :get do .clearfix @@ -19,4 +19,4 @@ = submit_tag t('.recalculate_durations'), :class => 'btn' = download_as_spreadsheet = render 'summary', :records => @records, :show_duration => true -= will_paginate @records, :renderer => PaginationListLinkRenderer \ No newline at end of file += will_paginate @records, :renderer => PaginationListLinkRenderer diff --git a/app/views/registrations/_form.html.haml b/app/views/registrations/_form.html.haml index bd918ca..8d3320c 100644 --- a/app/views/registrations/_form.html.haml +++ b/app/views/registrations/_form.html.haml @@ -9,6 +9,6 @@ = link_to image_tag('google_32.png', :size => "32x32", :alt => "Google"), oauth_url(:google, :subdomain => false), :class => 'service' = link_to image_tag('facebook_32.png', :size => "32x32", :alt => "Facebook"), oauth_url(:facebook, :subdomain => false), :class => 'service' or fill in the form below - = f.input :email + = f.input :email, :autocomplete => 'off' .actions = f.submit t('user.sign_up'), :class => 'btn primary' diff --git a/app/views/stuff/_form.html.haml b/app/views/stuff/_form.html.haml index 9bc0487..decfda9 100644 --- a/app/views/stuff/_form.html.haml +++ b/app/views/stuff/_form.html.haml @@ -7,8 +7,9 @@ %li= msg = f.inputs do = f.input :name + = f.input :stuff_type, :as => :radio, :collection => [['Stuff: Things that you move around. Stuff can contain other stuff.', 'stuff'], ['Location: Places that contain stuff. Locations generally don\'t move.', 'location']] = f.input :status - = f.input :home_location, :collection => (Location.all + Stuff.all).sort_by(&:name).collect { |x| [x.name, "#{x.id}-#{x.class.name}"] } - = f.input :notes + = f.input :home_location, :collection => current_account.stuff.order('name') + = f.input :notes, :input_html => { :rows => 5 } .actions - = f.submit 'Save' + = f.submit 'Save', :class => 'btn primary' diff --git a/app/views/stuff/_nav.html.haml b/app/views/stuff/_nav.html.haml new file mode 100644 index 0000000..a247e46 --- /dev/null +++ b/app/views/stuff/_nav.html.haml @@ -0,0 +1,5 @@ +%ul.tabs + %li{:class => active_class(active, 'stuff')}= link_to 'Stuff', stuff_index_path + %li{:class => active_class(active, 'contexts')}= link_to 'Contexts', contexts_path + - @account.contexts.each do |c| + %li{:class => active_class(active, "context#{c.id}")}= link_to c.name, c diff --git a/app/views/stuff/_quicklog.html.haml b/app/views/stuff/_quicklog.html.haml index 019b40c..5c534a3 100644 --- a/app/views/stuff/_quicklog.html.haml +++ b/app/views/stuff/_quicklog.html.haml @@ -3,7 +3,7 @@ %p = form_tag log_stuff_path do Quick entry: - = text_field_tag :stuff_name, stuff_name, :autofocus => stuff_name.blank?, :placeholder => 'Stuff name' - = text_field_tag :location_name, location_name, :autofocus => !stuff_name.blank?, :placeholder => 'Stuff location' + = autocomplete_field_tag :stuff_name, stuff_name, autocomplete_stuff_path, :autofocus => stuff_name.blank?, :placeholder => 'Stuff name' + = autocomplete_field_tag :location_name, location_name, autocomplete_stuff_path, :autofocus => !stuff_name.blank?, :placeholder => 'Stuff location' = submit_tag 'Update' diff --git a/app/views/stuff/edit.html.haml b/app/views/stuff/edit.html.haml index 2fb7533..cd5d0ef 100644 --- a/app/views/stuff/edit.html.haml +++ b/app/views/stuff/edit.html.haml @@ -1,4 +1,4 @@ -%h1 Editing stuff += setup_page 'edit', @stuff.name = render 'form' diff --git a/app/views/stuff/index.html.haml b/app/views/stuff/index.html.haml index 52ffa26..6a01d20 100644 --- a/app/views/stuff/index.html.haml +++ b/app/views/stuff/index.html.haml @@ -1,9 +1,5 @@ -%h1 Where's my stuff? += setup_page 'stuff' -%ul.pills - %li.active= link_to 'Index', stuff_index_path - - @contexts.each do |c| - %li= link_to c.name, c %p Status: = link_to 'all', stuff_index_path(:status => 'all') @@ -12,8 +8,13 @@ - if s and !s.status.blank? = link_to s.status, stuff_index_path(:status => s.status) - -= render :partial => 'quicklog' +To create or update an item, enter the item's name and its location below. += render 'quicklog' + +- if @account.stuff.locations.length > 0 + Locations: + = @account.stuff.locations.order('name').map { |x| link_to x.name, x }.join(', ').html_safe + %table.lined %tr %th= sortable_column "Name", :column => "name" @@ -39,14 +40,14 @@ = link_to "Return to #{stuff.home_location.name}", log_stuff_path(:stuff_name => stuff.name, :location_name => stuff.home_location.name), :method => :post - if stuff.location \- - = link_to 'Set current', stuff_path(stuff.id, :destination => request.url, :stuff => {:home_location_id => "#{stuff.location_id}-#{stuff.location_type}"}), :method => :put + = link_to 'Set current', stuff_path(stuff.id, :destination => request.url, :stuff => {:home_location_id => stuff.location_id}), :method => :put - else Home: = stuff.home.location.name - else No home? - - if stuff.location and can? :update, @stuff - = link_to 'Set current', stuff_path(stuff.id, :destination => request.url, :stuff => {:home_location_id => "#{stuff.location_id}-#{stuff.location_type}"}), :method => :put + - if stuff.location and can? :update, stuff + = link_to 'Set current', stuff_path(stuff.id, :destination => request.url, :stuff => {:home_location_id => stuff.location_id}), :method => :put, :title => "Set this item's home location to its current location" %td= l stuff.updated_at, :format => :short - if can? :update, stuff %td diff --git a/app/views/stuff/show.html.haml b/app/views/stuff/show.html.haml index 38d6d29..f779a9a 100644 --- a/app/views/stuff/show.html.haml +++ b/app/views/stuff/show.html.haml @@ -1,58 +1,47 @@ -= render :partial => 'quicklog', :locals => { :stuff_name => @stuff.name } - -%h1 - = @stuff.name - - if @stuff.location - = h('<') - = @stuff.hierarchy.map {|l| link_to h(l.name), l}.join(h(' < ')).html_safe - - - if can? :update, @stuff - - if @stuff.home_location and @stuff.location != @stuff.home_location - = link_to "(return to #{@stuff.home_location.name})", log_stuff_path(:stuff_name => @stuff.name, :location_name => @stuff.home_location.name), :method => :post += setup_page 'stuff', name_and_location(@stuff).html_safe %p - - if can? :update, @stuff + - if managing? = link_to 'Edit', edit_stuff_path(@stuff) \| = link_to 'Back', stuff_index_path += render :partial => 'quicklog', :locals => { :stuff_name => @stuff.name } + - if @stuff.location Current: = link_to @stuff.location.name, @stuff.location according to the system - - if @stuff.home_location and can? :update, @stuff + - if @stuff.home_location and @stuff.home_location != @stuff.location and managing? \- - = link_to 'Set home', stuff_path(@stuff.id, :destination => request.url, :stuff => {:home_location_id => "#{@stuff.location_id}-#{@stuff.location_type}"}), :method => :put - %br -- if @stuff.home_location - Home: - = link_to @stuff.home_location.name, @stuff.home_location - - if @stuff.location == @stuff.home_location - .in_place - (Hooray! A place for everything, and everything in its place) - + = link_to 'Set home', stuff_path(@stuff.id, :destination => request.url, :stuff => {:home_location_id => @stuff.location_id}), :method => :put + +- if @stuff.context_rules.length > 0 + %h2 Contexts + %table + %tr + %th Context + %th Location + - @stuff.context_rules.includes(:context, :location).each do |c| + %tr + %td= link_to c.context.name, c.context + %td= move_link_to(@stuff, c.location) %h2 Locations +%p Click on a link below to mark this item as moved to that location. + +- if @stuff.distinct_locations.length > 0 + Past locations: + = location_list @stuff, @stuff.distinct_locations.map(&:location) -%ul.locations - - loc = @stuff.distinct_locations - - loc.each do |l| - - if l and l.location - %li - - if can? :update, @stuff - = link_to l.location.name, log_stuff_path(:stuff_name => @stuff.name, :location_name => l.location.name), :method => :post - - else - = link_to l.location.name, l - -- if can? :update, @stuff +- if managing? %p - Other locations: - = Location.order('lower(name)').map { |l| link_to h(l.name), log_stuff_path(:stuff_name => @stuff.name, :location_name => l.name), :method => :post unless loc.include? l }.compact.join(', ').html_safe + Move to any location: + = location_list(@stuff, current_account.stuff.locations.order('lower(name)')) %br - Other stuff: - = Stuff.order('lower(name)').map { |l| link_to h(l.name), log_stuff_path(:stuff_name => @stuff.name, :location_name => l.name), :method => :post unless loc.include? l }.compact.join(', ').html_safe - + Move inside other stuff: + = location_list(@stuff, current_account.stuff.where('stuff_type != ? and id != ?', 'location', @stuff.id).order('lower(name)')) -- within = Stuff.where('location_id=? AND location_type=?', @stuff.id, 'Stuff').order('name') +- within = @stuff.contained_stuff.order('LOWER(name)') - if within.length > 0 %h2 What's in or on this? %p= render :partial => 'list', :locals => { :stuff => within } diff --git a/app/views/users/_form.html.haml b/app/views/users/_form.html.haml index 8d27696..06aeaa2 100644 --- a/app/views/users/_form.html.haml +++ b/app/views/users/_form.html.haml @@ -6,9 +6,16 @@ - @user.errors.full_messages.each do |msg| %li= msg = f.inputs do - = f.input :username - = f.input :email - = f.input :password, :required => false - = f.input :password_confirmation + = f.input :email, :input_html => { :autocomplete => 'off' } + = f.input :username, :input_html => { :autocomplete => 'off' } + .clear-fix + %label Timezone + .input= select_tag 'user[settings][time_zone]', time_zone_options_for_select(@user.settings.timezone) + + .clear-fix + .input If you'd like to change your password, enter your new password below: + = f.input :password, :required => false, :autocomplete => 'off' + = f.input :password_confirmation, :autocomplete => 'off' + .actions = f.submit 'Save', :class => 'btn primary' diff --git a/config/initializers/paperclip.rb b/config/initializers/paperclip.rb new file mode 100644 index 0000000..fc97337 --- /dev/null +++ b/config/initializers/paperclip.rb @@ -0,0 +1,3 @@ +Paperclip::Attachment.interpolations[:user_id] = proc do |attachment, style| + attachment.instance.user_id +end diff --git a/config/routes.rb b/config/routes.rb index a9fc397..3bc9533 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -21,14 +21,14 @@ end match '/offline.manifest' => offline - resources :records do member do post :clone end end - match 'record_categories/autocomplete_record_category_full_name', :as => :autocomplete_record_category + match 'record_categories/autocomplete' => 'record_categories#autocomplete_record_category_full_name', :as => :autocomplete_record_category + match 'stuff/autocomplete' => 'stuff#autocomplete_stuff_name', :as => :autocomplete_stuff resources :record_categories do member do post :track @@ -112,6 +112,7 @@ match 'clothing/tag/:id' => 'clothing#tag', :as => :clothing_by_tag match 'clothing/status/:status' => 'clothing#by_status', :as => :clothing_by_status match 'clothing/analyze(/:start(/:end))' => 'clothing#analyze', :as => :clothing_analyze + match 'files/clothing/:user_id/:id/:style/:filename' => 'clothing#download_thumbnail' match 'library/update' => 'library#update', :as => :library_refresh match 'summary' => 'home#summary', :as => :summary # The priority is based upon order of creation: diff --git a/db/migrate/20120115051056_add_stuff_type_and_merge_locations.rb b/db/migrate/20120115051056_add_stuff_type_and_merge_locations.rb new file mode 100644 index 0000000..dbbf077 --- /dev/null +++ b/db/migrate/20120115051056_add_stuff_type_and_merge_locations.rb @@ -0,0 +1,22 @@ +class AddStuffTypeAndMergeLocations < ActiveRecord::Migration + def up + # Merge stuff and locations + unless column_exists? :stuff, :stuff_type + add_column :stuff, :stuff_type, :string, :default => 'stuff' + end + # Copy locations into stuff + Location.all.each do |l| + new_location = Stuff.create(:stuff_type => 'location', :name => l.name, :notes => l.notes, :user => l.user) + # Move everything associated with that location + LocationHistory.where(:location_id => l.id, :location_type => 'Location').update_all({:location_id => new_location.id, :location_type => 'Stuff'}) + Stuff.where(:location_id => l.id, :location_type => 'Location').update_all({:location_id => new_location.id, :location_type => 'Stuff'}) + Stuff.where(:home_location_id => l.id, :home_location_type => 'Location').update_all({:home_location_id => new_location.id, :home_location_type => 'Stuff +'}) + l.destroy + end + end + + def down + raise ActiveRecord::IrreversibleMigration + end +end diff --git a/db/migrate/20120115171633_drop_polymorphic_from_stuff.rb b/db/migrate/20120115171633_drop_polymorphic_from_stuff.rb new file mode 100644 index 0000000..f8ec00e --- /dev/null +++ b/db/migrate/20120115171633_drop_polymorphic_from_stuff.rb @@ -0,0 +1,10 @@ +class DropPolymorphicFromStuff < ActiveRecord::Migration + def up + remove_column :stuff, :home_location_type + remove_column :stuff, :location_type + end + + def down + raise ActiveRecord::IrreversibleMigration + end +end diff --git a/db/migrate/20120115184226_change_location_histories.rb b/db/migrate/20120115184226_change_location_histories.rb new file mode 100644 index 0000000..3a017f0 --- /dev/null +++ b/db/migrate/20120115184226_change_location_histories.rb @@ -0,0 +1,9 @@ +class ChangeLocationHistories < ActiveRecord::Migration + def up + remove_column :location_histories, :location_type + end + + def down + raise ActiveRecord::IrreversibleMigration + end +end diff --git a/db/migrate/20120115193034_create_context_rules.rb b/db/migrate/20120115193034_create_context_rules.rb new file mode 100644 index 0000000..cd69295 --- /dev/null +++ b/db/migrate/20120115193034_create_context_rules.rb @@ -0,0 +1,10 @@ +class CreateContextRules < ActiveRecord::Migration + def change + create_table :context_rules do |t| + t.integer :stuff_id + t.integer :location_id + t.integer :context_id + t.timestamps + end + end +end diff --git a/db/migrate/20120115215056_change_context_to_serialize.rb b/db/migrate/20120115215056_change_context_to_serialize.rb new file mode 100644 index 0000000..10e5492 --- /dev/null +++ b/db/migrate/20120115215056_change_context_to_serialize.rb @@ -0,0 +1,21 @@ +class ChangeContextToSerialize < ActiveRecord::Migration + def up + # Convert string-based context rule definitions to model-based rule definitions + Context.all.each do |c| + rules = c.rules_array + rules.each do |r| + matches = r.match(/^stuff:[ \t]*([^,]+),[ \t]*(.*)/) + if matches + stuff = c.user.stuff.find_by_name matches[1] + location = c.user.stuff.find_by_name matches[2] + c.context_rules << ContextRule.new(:stuff => stuff, :location => location) + end + end + c.save! + end + end + + def down + raise ActiveRecord::IrreversibleMigration + end +end diff --git a/db/schema.rb b/db/schema.rb index 1972958..23d131c 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20120113184311) do +ActiveRecord::Schema.define(:version => 20120115215056) do create_table "clothing", :force => true do |t| t.string "name" @@ -58,6 +58,14 @@ add_index "clothing_matches", ["user_id"], :name => "index_clothing_matches_on_user_id" + create_table "context_rules", :force => true do |t| + t.integer "stuff_id" + t.integer "location_id" + t.integer "context_id" + t.datetime "created_at" + t.datetime "updated_at" + end + create_table "contexts", :force => true do |t| t.string "name" t.text "rules" @@ -182,7 +190,6 @@ create_table "location_histories", :force => true do |t| t.integer "stuff_id" t.integer "location_id" - t.string "location_type" t.datetime "datetime" t.text "notes" t.datetime "created_at" @@ -306,18 +313,17 @@ create_table "stuff", :force => true do |t| t.string "name" t.string "status" - t.decimal "price", :precision => 10, :scale => 0 + t.decimal "price", :precision => 10, :scale => 0 t.date "purchase_date" t.text "notes" t.string "long_name" t.datetime "created_at" t.datetime "updated_at" t.integer "location_id" - t.string "location_type" t.integer "home_location_id" - t.string "home_location_type" t.boolean "in_place" t.integer "user_id" + t.string "stuff_type", :default => "stuff" end add_index "stuff", ["location_id"], :name => "index_stuff_on_location_id" diff --git a/public/stylesheets/style.css.css b/public/stylesheets/style.css.css index 12b8f0a..ecc7b8a 100644 --- a/public/stylesheets/style.css.css +++ b/public/stylesheets/style.css.css @@ -3025,83 +3025,88 @@ form .clear-fix { } /* line 35, ../../app/assets/stylesheets/style.css.sass */ +.row, .category { + margin-left: 0px; +} + +/* line 37, ../../app/assets/stylesheets/style.css.sass */ .actions .btn { margin-right: 10px; } -/* line 39, ../../app/assets/stylesheets/style.css.sass */ +/* line 41, ../../app/assets/stylesheets/style.css.sass */ .category_label { text-align: right; display: block; float: left; } -/* line 44, ../../app/assets/stylesheets/style.css.sass */ +/* line 46, ../../app/assets/stylesheets/style.css.sass */ .category_detail { padding-top: 13px; margin-left: 170px; } -/* line 48, ../../app/assets/stylesheets/style.css.sass */ +/* line 50, ../../app/assets/stylesheets/style.css.sass */ .contexts .category_detail, .time .category_detail { padding-top: 0; } -/* line 50, ../../app/assets/stylesheets/style.css.sass */ +/* line 52, ../../app/assets/stylesheets/style.css.sass */ .category_detail .pills { margin-bottom: 0px; } -/* line 52, ../../app/assets/stylesheets/style.css.sass */ +/* line 54, ../../app/assets/stylesheets/style.css.sass */ a[data-method] { color: green; font-weight: bold; } -/* line 55, ../../app/assets/stylesheets/style.css.sass */ +/* line 57, ../../app/assets/stylesheets/style.css.sass */ .radio legend.label, .radio legend.status, .radio legend.private { float: left; } -/* line 58, ../../app/assets/stylesheets/style.css.sass */ +/* line 60, ../../app/assets/stylesheets/style.css.sass */ .tap_log_record .timestamp { width: 150px; text-align: right; } -/* line 61, ../../app/assets/stylesheets/style.css.sass */ +/* line 63, ../../app/assets/stylesheets/style.css.sass */ .tap_log_record .categories { width: 200px; } -/* line 63, ../../app/assets/stylesheets/style.css.sass */ +/* line 65, ../../app/assets/stylesheets/style.css.sass */ .status { font-weight: normal; display: inline; } -/* line 67, ../../app/assets/stylesheets/style.css.sass */ +/* line 69, ../../app/assets/stylesheets/style.css.sass */ .private { font-weight: normal; display: inline; } -/* line 71, ../../app/assets/stylesheets/style.css.sass */ +/* line 73, ../../app/assets/stylesheets/style.css.sass */ .collapsible > legend { font-weight: bold; margin-bottom: 10px; } -/* line 74, ../../app/assets/stylesheets/style.css.sass */ +/* line 76, ../../app/assets/stylesheets/style.css.sass */ td.h { font-weight: bold; } -/* line 76, ../../app/assets/stylesheets/style.css.sass */ +/* line 78, ../../app/assets/stylesheets/style.css.sass */ .login, .sign_up { padding-right: 10px; } -/* line 78, ../../app/assets/stylesheets/style.css.sass */ +/* line 80, ../../app/assets/stylesheets/style.css.sass */ .radio legend.label, .radio legend.status, .radio legend.private { padding-top: 6px; font-size: 13px; @@ -3115,7 +3120,7 @@ td.h { text-transform: none; } -/* line 89, ../../app/assets/stylesheets/style.css.sass */ +/* line 91, ../../app/assets/stylesheets/style.css.sass */ label.inline, .inline label { padding-top: 0px; width: auto; @@ -3124,64 +3129,74 @@ label.inline, .inline label { float: none; } -/* line 95, ../../app/assets/stylesheets/style.css.sass */ +/* line 97, ../../app/assets/stylesheets/style.css.sass */ .inline .input { display: inline-block; margin-left: 0; } -/* line 98, ../../app/assets/stylesheets/style.css.sass */ +/* line 100, ../../app/assets/stylesheets/style.css.sass */ .condensed-table { font-size: smaller; } -/* line 100, ../../app/assets/stylesheets/style.css.sass */ +/* line 102, ../../app/assets/stylesheets/style.css.sass */ .right { text-align: right; } -/* line 102, ../../app/assets/stylesheets/style.css.sass */ +/* line 104, ../../app/assets/stylesheets/style.css.sass */ .clearfix { clear: both; } -/* line 104, ../../app/assets/stylesheets/style.css.sass */ +/* line 106, ../../app/assets/stylesheets/style.css.sass */ .full .login, .full .sign_up { display: table-cell; } -/* line 107, ../../app/assets/stylesheets/style.css.sass */ +/* line 109, ../../app/assets/stylesheets/style.css.sass */ input.imagebtn { height: auto; width: auto; } -/* line 111, ../../app/assets/stylesheets/style.css.sass */ +/* line 113, ../../app/assets/stylesheets/style.css.sass */ .time .category_detail, .time .start { padding-top: 7px; } -/* line 113, ../../app/assets/stylesheets/style.css.sass */ +/* line 115, ../../app/assets/stylesheets/style.css.sass */ .spreadsheet { float: right; } -/* line 116, ../../app/assets/stylesheets/style.css.sass */ +/* line 118, ../../app/assets/stylesheets/style.css.sass */ .topbar .feedback, .topbar .track { font-size: 120%; font-weight: bold; } -/* line 119, ../../app/assets/stylesheets/style.css.sass */ +/* line 121, ../../app/assets/stylesheets/style.css.sass */ .topbar .feedback a, .topbar .track a { color: white; text-decoration: underline; } -/* line 122, ../../app/assets/stylesheets/style.css.sass */ +/* line 124, ../../app/assets/stylesheets/style.css.sass */ .topbar a[data-method] { color: #bfbfbf; } -/* line 124, ../../app/assets/stylesheets/style.css.sass */ +/* line 126, ../../app/assets/stylesheets/style.css.sass */ a[data-method].btn { color: black; } + +/* line 128, ../../app/assets/stylesheets/style.css.sass */ +a[data-method].btn.primary { + color: white; +} + +/* line 130, ../../app/assets/stylesheets/style.css.sass */ +.input table { + width: auto; +} diff --git a/spec/factories/context_rules.rb b/spec/factories/context_rules.rb new file mode 100644 index 0000000..933710d --- /dev/null +++ b/spec/factories/context_rules.rb @@ -0,0 +1,9 @@ +# Read about factories at http://github.com/thoughtbot/factory_girl + +FactoryGirl.define do + factory :context_rule do + stuff_id 1 + location_id 1 + context_id 1 + end +end diff --git a/spec/models/context_rule_spec.rb b/spec/models/context_rule_spec.rb new file mode 100644 index 0000000..895a360 --- /dev/null +++ b/spec/models/context_rule_spec.rb @@ -0,0 +1,5 @@ +require 'spec_helper' + +describe ContextRule do + pending "add some examples to (or delete) #{__FILE__}" +end