From 77723a91d54253ddc154322e47331338575586d8 Mon Sep 17 00:00:00 2001 From: Andrew Cantino Date: Wed, 10 Sep 2014 00:23:14 -0700 Subject: [PATCH] tables can be sorted; optimized Agents load slightly --- .../stylesheets/application.css.scss.erb | 9 --- app/assets/stylesheets/tables.css.scss | 31 ++++++++++ app/controllers/agents_controller.rb | 5 +- app/controllers/concerns/sortable_table.rb | 53 ++++++++++++++++ app/controllers/scenarios_controller.rb | 9 ++- app/controllers/services_controller.rb | 6 +- .../user_credentials_controller.rb | 6 +- app/helpers/agent_helper.rb | 2 +- app/views/agents/_table.html.erb | 8 +-- app/views/scenarios/index.html.erb | 4 +- app/views/services/index.html.erb | 6 +- app/views/user_credentials/index.html.erb | 4 +- .../concerns/sortable_table_spec.rb | 61 +++++++++++++++++++ spec/spec_helper.rb | 2 + 14 files changed, 180 insertions(+), 26 deletions(-) create mode 100644 app/assets/stylesheets/tables.css.scss create mode 100644 app/controllers/concerns/sortable_table.rb create mode 100644 spec/controllers/concerns/sortable_table_spec.rb diff --git a/app/assets/stylesheets/application.css.scss.erb b/app/assets/stylesheets/application.css.scss.erb index c3fa6113..fcff6585 100644 --- a/app/assets/stylesheets/application.css.scss.erb +++ b/app/assets/stylesheets/application.css.scss.erb @@ -36,15 +36,6 @@ body { padding-top: 60px; } @extend .control-group.error; } -table.events { - .payload { - color: #999; - font-size: 12px; - //text-align: center; - font-family: monospace; - } -} - .select2 { float: none !important; margin-left: 0 !important; diff --git a/app/assets/stylesheets/tables.css.scss b/app/assets/stylesheets/tables.css.scss new file mode 100644 index 00000000..b6c9f2cf --- /dev/null +++ b/app/assets/stylesheets/tables.css.scss @@ -0,0 +1,31 @@ +// Sortable table headers +.table th a.selected { + position: relative; + text-decoration: underline; + + &.asc:after, &.desc:after { + text-decoration: none; + position: absolute; + top: -5px; + right: -12px; + font-size: 1.2em; + } + + &.asc:after { + content: '\2193'; + } + + &.desc:after { + content: '\2191'; + } +} + +table.events { + .payload { + color: #999; + font-size: 12px; + //text-align: center; + font-family: monospace; + } +} + diff --git a/app/controllers/agents_controller.rb b/app/controllers/agents_controller.rb index c5053af6..a459e8b5 100644 --- a/app/controllers/agents_controller.rb +++ b/app/controllers/agents_controller.rb @@ -1,8 +1,11 @@ class AgentsController < ApplicationController include DotHelper + include SortableTable def index - @agents = current_user.agents.page(params[:page]) + set_table_sort sorts: %w[name last_check_at last_event_at last_receive_at], default: { name: :asc } + + @agents = current_user.agents.preload(:scenarios, :controllers).reorder(table_sort).page(params[:page]) respond_to do |format| format.html diff --git a/app/controllers/concerns/sortable_table.rb b/app/controllers/concerns/sortable_table.rb new file mode 100644 index 00000000..5a856d6c --- /dev/null +++ b/app/controllers/concerns/sortable_table.rb @@ -0,0 +1,53 @@ +require 'active_support/concern' + +module SortableTable + extend ActiveSupport::Concern + + included do + helper SortableTableHelper + end + + protected + + def table_sort + raise("You must call set_table_sort in any action using table_sort.") unless @table_sort_info.present? + @table_sort_info[:order] + end + + def set_table_sort(sort_options) + valid_sorts = sort_options[:sorts] || raise("You must specify :sorts as an array of valid sort attributes.") + default = sort_options[:default] || { valid_sorts.first.to_sym => :desc } + + if params[:sort].present? + attribute, direction = params[:sort].downcase.split('.') + unless valid_sorts.include?(attribute) + attribute, direction = default.to_a.first + end + else + attribute, direction = default.to_a.first + end + + direction = direction.to_s == 'desc' ? 'desc' : 'asc' + + @table_sort_info = { + order: { attribute.to_sym => direction.to_sym }, + attribute: attribute, + direction: direction + } + end + + module SortableTableHelper + def sortable_column(attribute, name = attribute.humanize, default_direction = 'desc') + selected = @table_sort_info[:attribute].to_s == attribute + if selected + direction = @table_sort_info[:direction] + new_direction = direction.to_s == 'desc' ? 'asc' : 'desc' + classes = "selected #{direction}" + else + classes = '' + new_direction = default_direction + end + link_to(name, url_for(sort: "#{attribute}.#{new_direction}"), class: classes) + end + end +end \ No newline at end of file diff --git a/app/controllers/scenarios_controller.rb b/app/controllers/scenarios_controller.rb index f4c355f7..9f974bc5 100644 --- a/app/controllers/scenarios_controller.rb +++ b/app/controllers/scenarios_controller.rb @@ -1,8 +1,11 @@ class ScenariosController < ApplicationController + include SortableTable skip_before_filter :authenticate_user!, :only => :export def index - @scenarios = current_user.scenarios.page(params[:page]) + set_table_sort sorts: %w[name public], default: { name: :asc } + + @scenarios = current_user.scenarios.reorder(table_sort).page(params[:page]) respond_to do |format| format.html @@ -21,7 +24,9 @@ class ScenariosController < ApplicationController def show @scenario = current_user.scenarios.find(params[:id]) - @agents = @scenario.agents.preload(:scenarios).page(params[:page]) + + set_table_sort sorts: %w[name last_check_at last_event_at last_receive_at], default: { name: :asc } + @agents = @scenario.agents.preload(:scenarios, :controllers).reorder(table_sort).page(params[:page]) respond_to do |format| format.html diff --git a/app/controllers/services_controller.rb b/app/controllers/services_controller.rb index 29fee5a4..d98cb5db 100644 --- a/app/controllers/services_controller.rb +++ b/app/controllers/services_controller.rb @@ -1,8 +1,12 @@ class ServicesController < ApplicationController + include SortableTable + before_filter :upgrade_warning, only: :index def index - @services = current_user.services.page(params[:page]) + set_table_sort sorts: %w[provider name global], default: { provider: :asc } + + @services = current_user.services.reorder(table_sort).page(params[:page]) respond_to do |format| format.html diff --git a/app/controllers/user_credentials_controller.rb b/app/controllers/user_credentials_controller.rb index 86b2f74f..d988f257 100644 --- a/app/controllers/user_credentials_controller.rb +++ b/app/controllers/user_credentials_controller.rb @@ -1,6 +1,10 @@ class UserCredentialsController < ApplicationController + include SortableTable + def index - @user_credentials = current_user.user_credentials.page(params[:page]) + set_table_sort sorts: %w[credential_name credential_value], default: { credential_name: :asc } + + @user_credentials = current_user.user_credentials.reorder(table_sort).page(params[:page]) respond_to do |format| format.html diff --git a/app/helpers/agent_helper.rb b/app/helpers/agent_helper.rb index b994922d..5753612d 100644 --- a/app/helpers/agent_helper.rb +++ b/app/helpers/agent_helper.rb @@ -31,7 +31,7 @@ module AgentHelper end def agent_controllers(agent, delimiter = ', ') - unless agent.controllers.empty? + if agent.controllers.present? agent.controllers.map { |agent| link_to(agent.name, agent_path(agent)) }.join(delimiter).html_safe diff --git a/app/views/agents/_table.html.erb b/app/views/agents/_table.html.erb index 5bdea3f5..627cfb9b 100644 --- a/app/views/agents/_table.html.erb +++ b/app/views/agents/_table.html.erb @@ -1,11 +1,11 @@
- + - - - + + + diff --git a/app/views/scenarios/index.html.erb b/app/views/scenarios/index.html.erb index e04283d9..0a368f11 100644 --- a/app/views/scenarios/index.html.erb +++ b/app/views/scenarios/index.html.erb @@ -12,9 +12,9 @@
Name<%= sortable_column 'name', 'Name', 'asc' %> ScheduleLast CheckLast Event OutLast Event In<%= sortable_column 'last_check_at', 'Last Check' %><%= sortable_column 'last_event_at', 'Last Event Out' %><%= sortable_column 'last_receive_at', 'Last Event In' %> Events Created Working?
- + - + diff --git a/app/views/services/index.html.erb b/app/views/services/index.html.erb index 1dd31115..9b61561f 100644 --- a/app/views/services/index.html.erb +++ b/app/views/services/index.html.erb @@ -25,9 +25,9 @@
Name<%= sortable_column 'name', 'Name', 'asc' %> AgentsPublic<%= sortable_column 'public' %>
- - - + + + diff --git a/app/views/user_credentials/index.html.erb b/app/views/user_credentials/index.html.erb index 3c027158..d18ab41c 100644 --- a/app/views/user_credentials/index.html.erb +++ b/app/views/user_credentials/index.html.erb @@ -14,8 +14,8 @@
ProviderUsernameGlobal?<%= sortable_column 'provider', 'Provider', 'asc' %><%= sortable_column 'name', 'Name', 'asc' %><%= sortable_column 'global', 'Global?' %>
- - + + <% @user_credentials.each do |user_credential| %> diff --git a/spec/controllers/concerns/sortable_table_spec.rb b/spec/controllers/concerns/sortable_table_spec.rb new file mode 100644 index 00000000..bf2b0f36 --- /dev/null +++ b/spec/controllers/concerns/sortable_table_spec.rb @@ -0,0 +1,61 @@ +require 'spec_helper' + +describe SortableTable do + class SortableTestController + attr_accessor :params + + def self.helper(foo) + end + + include SortableTable + + public :set_table_sort + public :table_sort + end + + describe "#set_table_sort" do + let(:controller) { SortableTestController.new } + let(:default) { { column2: :asc }} + let(:options) { { sorts: %w[column1 column2], default: default } } + + it "uses a default when no sort is given" do + controller.params = {} + controller.set_table_sort options + controller.table_sort.should == default + end + + it "applies the given sort when one is passed in" do + controller.params = { sort: "column1.desc" } + controller.set_table_sort options + controller.table_sort.should == { column1: :desc } + + controller.params = { sort: "column1.asc" } + controller.set_table_sort options + controller.table_sort.should == { column1: :asc } + + controller.params = { sort: "column2.desc" } + controller.set_table_sort options + controller.table_sort.should == { column2: :desc } + end + + it "ignores unknown directions" do + controller.params = { sort: "column1.foo" } + controller.set_table_sort options + controller.table_sort.should == { column1: :asc } + + controller.params = { sort: "column1.foo drop tables" } + controller.set_table_sort options + controller.table_sort.should == { column1: :asc } + end + + it "ignores unknown columns" do + controller.params = { sort: "foo.asc" } + controller.set_table_sort options + controller.table_sort.should == default + + controller.params = { sort: ";drop table;.asc" } + controller.set_table_sort options + controller.table_sort.should == default + end + end +end \ No newline at end of file diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index e3a31ef0..b4a5a03a 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -55,6 +55,8 @@ RSpec.configure do |config| config.global_fixtures = :all config.treat_symbols_as_metadata_keys_with_true_values = true + config.render_views + config.include Devise::TestHelpers, :type => :controller config.include SpecHelpers config.include Delorean
NameValue<%= sortable_column 'credential_name', 'Name', 'asc' %><%= sortable_column 'credential_value', 'Value', 'asc' %>