tb_core 1.3.4 → 1.3.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cf2f47767b015951d5eca3a7af3055b5c20101d6
4
- data.tar.gz: 3869ef7c61f21fbef83d92303d81bbd819081abc
3
+ metadata.gz: 06f0ab03560e57efe477e7fb0f9ae6f72a8a042c
4
+ data.tar.gz: e8d702fe0332d78ae18bc9d0605db1d89ec3cb26
5
5
  SHA512:
6
- metadata.gz: d4e8a3d18f3768dd7bdc4c4c58bed5ce6d412203cda91e86b324e7a36af44e672a1ee7722e9ded0b869590a975210ad5d9789d1ec5a5230e7a2c5d1e71528619
7
- data.tar.gz: c084bff092e94de06d53b90d8253e041be1d4e338dce48d83c95d00563579bc7f326b90648c8e70defbd2f50f5f1110117afd171e2f7bd721a422c51aabaf616
6
+ metadata.gz: 6b6d73ea8d50f6930b71df507147e5644128cd2a04024522984aed28fe1832dcc1e9e37059945c34e22a31b41747d9a914868af5eead68d5a466917bdd3b0a46
7
+ data.tar.gz: 778f7e4d4a48508249c54cff93cdda5334a0beddf158e4a5b68eaab544e9cc6539a53b18fc8aa64480267b549a436cf2713f4d7b7344380a6a232ae815071a40
@@ -1,9 +1,7 @@
1
1
  //= require jquery
2
2
  //= require jquery_ujs
3
- //= require jquery-ui
4
3
  //= require tinymce-jquery
5
4
  //= require bootstrap-sprockets
6
-
7
5
  //= require ../../tb_core
8
6
  //= require_self
9
7
  //= require_tree .
@@ -6,6 +6,7 @@ spud.admin.dashboard = {
6
6
  init:function(){
7
7
  badgeInterval = setInterval(updateBadges, 30000);
8
8
  updateBadges();
9
+ sortableIcons();
9
10
  }
10
11
  };
11
12
 
@@ -44,4 +45,28 @@ var updateBadge = function(badge_id, count) {
44
45
  }
45
46
  };
46
47
 
48
+ var sortableIcons = function(){
49
+ $(".sortable").sortable({
50
+ update : function(e, ui) {
51
+ var sortArr = [];
52
+ var index = 0;
53
+ $(".sortable > div > a").each(function() {
54
+ sortArr.push($(this).attr('href'));
55
+ });
56
+ //save the order to userSettings
57
+ $.ajax('/admin/change_sort', {
58
+ method: 'PUT',
59
+ data: {order:sortArr},
60
+ dataType: "json",
61
+ success: function(data, status, jqXHR) {
62
+
63
+ },
64
+ error: function(XMLHttpRequest, textStatus, errorThrown) {
65
+ alert("Status: " + textStatus); alert("Error: " + errorThrown);
66
+ }
67
+ });
68
+ }
69
+ });
70
+ };
71
+
47
72
  })();
@@ -0,0 +1,22 @@
1
+ // Use this file to customize which jQuery UI JavaScript modules we include in the admin.
2
+ //
3
+ // https://github.com/joliss/jquery-ui-rails
4
+ //
5
+ // We primarily use UI for some interaction utilties and to fill in gaps
6
+ // left by Bootstrap. As a general rule, we should try to use a Bootstrap
7
+ // equivalent FIRST and then fall back to jQuery UI if necessary.
8
+ //
9
+ // For example, we prefer bootstrap-datepicker over jQuery UI Datepicker
10
+ //
11
+ // To see a full list of available modules (and their dependencies), see here:
12
+ // http://jqueryui.com/download
13
+ //
14
+ // NOTE: Don't forget to also add the corresponding modules to jquery_ui.scss!
15
+ //
16
+ //= require jquery-ui/core
17
+ //= require jquery-ui/widget
18
+ //= require jquery-ui/mouse
19
+ //= require jquery-ui/draggable
20
+ //= require jquery-ui/droppable
21
+ //= require jquery-ui/sortable
22
+ //
@@ -13,11 +13,13 @@
13
13
  */
14
14
  tb.remote = {
15
15
  init: function(){
16
- $('body').on('ajax:before', 'form', onRemoteFormBefore);
17
- $('body').on('ajax:complete', 'form', onRemoteFormComplete);
18
- $('body').on('ajax:success', 'form[data-success]', onRemoteFormSuccess);
19
- $('body').on('ajax:error', 'form[data-errors]', onRemoteFormErrors);
20
- $('body').on('ajax:success', 'tr a[data-method=delete][data-remote=true]', onRemoteDeleteTableRow);
16
+ var $document = $(document);
17
+ $document.on('ajax:before', 'form', onRemoteFormBefore);
18
+ $document.on('ajax:complete', 'form', onRemoteFormComplete);
19
+ $document.on('ajax:success', 'form[data-success]', onRemoteFormSuccess);
20
+ $document.on('ajax:error', 'form[data-errors]', onRemoteFormErrors);
21
+ $document.on('ajax:success', 'tr a[data-method=delete][data-remote=true]', onRemoteDeleteTableRow);
22
+ $document.on('ajax:aborted:file', 'form', onRemoteAbortedFile);
21
23
  }
22
24
  };
23
25
 
@@ -50,14 +52,32 @@ var onRemoteFormComplete = function(event, jqXHR, textStatus){
50
52
  var onRemoteFormSuccess = function(event, json, textStatus, jqXHR){
51
53
  var successPath = $(this).data('success');
52
54
  if(successPath == 'reload'){
53
- window.location.reload();
55
+ window.location.reload(true);
54
56
  }
55
57
  else{
56
- if(json && json.id){
57
- successPath = successPath.replace(':id', json.id);
58
- }
59
- window.location = successPath;
58
+ window.location = buildSuccessPath(successPath, json);
59
+ }
60
+ };
61
+
62
+ /*
63
+ * Build a path for redirection.
64
+ *
65
+ * - Adds a timestamp GET param for cache busting
66
+ * - Inserts an ID attribute if necessary
67
+ *
68
+ */
69
+ var buildSuccessPath = function(path, json){
70
+ var timestamp = (new Date()).valueOf();
71
+ if(path.indexOf('?') > -1){
72
+ path += ('&t=' + timestamp);
73
+ }
74
+ else{
75
+ path += ('?t=' + timestamp);
76
+ }
77
+ if(json && json.id){
78
+ path = path.replace(':id', json.id);
60
79
  }
80
+ return path;
61
81
  };
62
82
 
63
83
  /*
@@ -104,16 +124,21 @@ var displayErrorsInline = function($form, errors){
104
124
 
105
125
  keyArr = key.split('.');
106
126
 
107
- if (keyArr.length === 2) {
127
+ if(keyArr.length === 2){
108
128
  keyArr[0] += '_attributes';
109
129
  $input = $form.find("[name$='[" + keyArr.join('][') + "]']");
110
- } else {
130
+ }
131
+ else{
111
132
  $input = $form.find("[name$='[" + key + "]']");
133
+
134
+ if($input.length === 0 && !key.match(/_id$/)){
135
+ $input = $form.find("[name$='[" + key + "_id]']");
136
+ }
112
137
  }
113
138
 
114
139
  if($input.length > 0){
115
140
  var message = errors[key][0];
116
- $input.after('<p class="form-error form-error-inline">'+message+'</p>');
141
+ $input.parent().append('<p class="form-error form-error-inline">'+message+'</p>');
117
142
  }
118
143
  else{
119
144
  console.warn('Missing input field for key:', key);
@@ -154,6 +179,30 @@ var onRemoteDeleteTableRow = function(){
154
179
  });
155
180
  };
156
181
 
182
+ /*
183
+ * Attach an authenticity_token input field when a remote form aborts due to a file input field
184
+ *
185
+ * When a form is configured with remote:true, the authenticity_token hidden input you would normally see is not included. Then what
186
+ * can happen is the form can fall back to a non-remote action for some reason, possibly due to the presence of a file input field. The
187
+ * net result is that the server responds with a "Can't verify CSRF token authenticity" error because none was sent.
188
+ *
189
+ * This function handles that case by injecting the missing authenticity_token input just before the form is posted.
190
+ *
191
+ */
192
+ var onRemoteAbortedFile = function(event, inputs){
193
+ var $form = $(this);
194
+ var csrfParam = $.rails.csrfParam();
195
+ if($form.find('input[name='+csrfParam+']').length === 0){
196
+ var csrfToken = $.rails.csrfToken();
197
+ var $input = $('<input/>', {
198
+ type: 'hidden',
199
+ name: csrfParam,
200
+ value: csrfToken
201
+ });
202
+ $form.prepend($input);
203
+ }
204
+ };
205
+
157
206
  /*
158
207
  * Monkeypatch the base $.rails.enableFormElement function to add a
159
208
  * delay and a success text value to the button before returning to
@@ -1,8 +1,6 @@
1
1
  //= require_self
2
2
  //= require_directory
3
3
 
4
- //= require jquery-ui
5
-
6
4
  @import "bootstrap-sprockets";
7
5
  @import "bootstrap";
8
6
 
@@ -0,0 +1,19 @@
1
+ // Use this file to customize which jQuery UI CSS modules we include in the admin.
2
+ //
3
+ // https://github.com/joliss/jquery-ui-rails
4
+ //
5
+ // We primarily use UI for some interaction utilties and to fill in gaps
6
+ // left by Bootstrap. As a general rule, we should try to use a Bootstrap
7
+ // equivalent FIRST and then fall back to jQuery UI if necessary.
8
+ //
9
+ // For example, we prefer bootstrap-datepicker over jQuery UI Datepicker
10
+ //
11
+ // To see a full list of available modules (and their dependencies), see here:
12
+ // http://jqueryui.com/download
13
+ //
14
+ // NOTE: Don't forget to also add the corresponding modules to jquery_ui.js!
15
+ //
16
+ //= require jquery-ui/core
17
+ //= require jquery-ui/draggable
18
+ //= require jquery-ui/sortable
19
+ //
@@ -1,13 +1,30 @@
1
1
  class Admin::DashboardController < Admin::ApplicationController
2
2
 
3
+ respond_to :html, :json
3
4
  layout 'admin/application'
4
5
 
5
6
  def index
6
- @admin_applications = Spud::Core.admin_applications.select do |admin_application|
7
+ @setting = SpudUserSetting.find_by(:spud_user_id => current_user.id, :key => "dash_icon_order")
8
+ apps = Spud::Core.admin_applications
9
+ if @setting.nil? == false
10
+ apps = arrange_apps(apps)
11
+ end
12
+ @admin_applications = apps.select do |admin_application|
7
13
  current_user.can_view_app?(admin_application)
8
14
  end
9
15
  end
10
16
 
17
+ def change_sort
18
+ @order = params[:order]
19
+ @setting = SpudUserSetting.find_or_initialize_by(:spud_user_id => current_user.id, :key => "dash_icon_order")
20
+ @setting.value = @order
21
+ if @setting.save
22
+ respond_to do |format|
23
+ format.json { head :no_content }
24
+ end
25
+ end
26
+ end
27
+
11
28
  def badges
12
29
  data = []
13
30
  @admin_applications = Spud::Core.admin_applications.select do |admin_application|
@@ -20,4 +37,25 @@ class Admin::DashboardController < Admin::ApplicationController
20
37
  render :json => {:data => data}
21
38
  end
22
39
 
40
+ private
41
+
42
+ def arrange_apps(applications)
43
+ begin
44
+ order = JSON.parse(@setting.value)
45
+ rescue JSON::ParserError
46
+ return applications
47
+ end
48
+
49
+ return applications.sort do |a, b|
50
+ index_a = order.index(a[:url])
51
+ index_b = order.index(b[:url])
52
+ if index_a.nil?
53
+ 1
54
+ elsif index_b.nil?
55
+ -1
56
+ else
57
+ index_a <=> index_b
58
+ end
59
+ end
60
+ end
23
61
  end
data/config/routes.rb CHANGED
@@ -9,6 +9,7 @@ Rails.application.routes.draw do
9
9
 
10
10
  get 'settings' => 'settings#edit', :as => 'settings'
11
11
  put 'settings' => 'settings#update'
12
+ put 'change_sort' => 'dashboard#change_sort'
12
13
 
13
14
  root :to => "dashboard#index"
14
15
  resources :users, :controller
@@ -23,7 +23,7 @@ class CreateSpudUsers < ActiveRecord::Migration
23
23
  t.string :last_login_ip # optional, see Authlogic::Session::MagicColumns
24
24
  t.timestamps
25
25
  end
26
- add_index :spud_users,:login
27
- add_index :spud_users,:email
26
+ add_index :spud_users, :login
27
+ add_index :spud_users, :email
28
28
  end
29
29
  end
@@ -68,6 +68,16 @@ module Spud
68
68
  end
69
69
  end
70
70
 
71
+ initializer 'tb_core.mysql2_extensions' do
72
+ ActiveSupport.on_load(:active_record) do
73
+ if defined?(ActiveRecord::ConnectionAdapters::Mysql2Adapter)
74
+ ActiveRecord::ConnectionAdapters::Mysql2Adapter.class_eval do
75
+ include TbCore::Mysql2Extensions
76
+ end
77
+ end
78
+ end
79
+ end
80
+
71
81
  end
72
82
  end
73
83
  end
@@ -1,5 +1,5 @@
1
1
  module Spud
2
2
  module Core
3
- VERSION = "1.3.4"
3
+ VERSION = "1.3.5"
4
4
  end
5
5
  end
@@ -0,0 +1,36 @@
1
+ module TbCore::Mysql2Extensions
2
+ extend ActiveSupport::Concern
3
+
4
+ # Build a hash of length options for a given table and column name
5
+ #
6
+ # column_name can be either a symbol or an array of symbols
7
+ #
8
+ def length_options_for_utf8mb4_string_index(table_name, column_names)
9
+ length_options = {}
10
+ column_names = [column_names] unless column_names.is_a?(Array)
11
+ column_names.each do |column_name|
12
+ begin
13
+ column = column_for(table_name, column_name)
14
+ if column && column.type == :string
15
+ length_options[column_name] = ActiveRecord::ConnectionAdapters::Mysql2Adapter::MAX_INDEX_LENGTH_FOR_UTF8MB4
16
+ end
17
+ rescue ActiveRecord::ActiveRecordError => e
18
+ logger.info e.message
19
+ end
20
+ end
21
+ return length_options
22
+ end
23
+
24
+ # Adds an index to the table
25
+ #
26
+ # See parent method implementation here:
27
+ # http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html#method-i-add_index
28
+ #
29
+ def add_index(table_name, column_name, options = {})
30
+ if options[:length].nil? && @connection.query_options[:encoding] == 'utf8mb4'
31
+ options[:length] = length_options_for_utf8mb4_string_index(table_name, column_name)
32
+ end
33
+ super(table_name, column_name, options)
34
+ end
35
+
36
+ end
@@ -6,10 +6,13 @@
6
6
  development:
7
7
  adapter: mysql2
8
8
  database: tb_core_development
9
+ encoding: utf8mb4
10
+ collation: utf8mb4_bin
9
11
  username: root
10
-
12
+
11
13
  test:
12
14
  adapter: mysql2
13
15
  database: tb_core_test
16
+ encoding: utf8mb4
17
+ collation: utf8mb4_bin
14
18
  username: root
15
-
@@ -0,0 +1,46 @@
1
+ require 'rails_helper'
2
+
3
+ describe TbCore::Mysql2Extensions do
4
+
5
+ let(:adapter){
6
+ SpudUser.connection
7
+ }
8
+
9
+ describe '#length_options_for_utf8mb4_string_index' do
10
+ it 'should return a hash with a single value' do
11
+ options = adapter.length_options_for_utf8mb4_string_index(:spud_users, :first_name)
12
+ expect(options).to eq({:first_name => 191})
13
+ end
14
+
15
+ it 'should return a hash with multiple values' do
16
+ options = adapter.length_options_for_utf8mb4_string_index(:spud_users, [:first_name, :last_name])
17
+ expect(options[:first_name]).to eq(191)
18
+ expect(options[:last_name]).to eq(191)
19
+ end
20
+
21
+ it 'should not assign a length for a non-string column' do
22
+ options = adapter.length_options_for_utf8mb4_string_index(:spud_users, [:first_name, :last_name, :super_admin])
23
+ expect(options[:super_admin]).to eq(nil)
24
+ end
25
+ end
26
+
27
+ describe '#add_index' do
28
+ before(:each){
29
+ # Mock the add_index method to simply return the options hash rather than adding an index, so that we can inspect the contents of options
30
+ allow_any_instance_of(ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter).to receive(:add_index) do |abstract_adapter, table_name, column_name, options|
31
+ options
32
+ end
33
+ }
34
+
35
+ it 'should pass a length option' do
36
+ options = adapter.add_index(:spud_users, :first_name)
37
+ expect(options[:length]).to eq({:first_name => 191})
38
+ end
39
+
40
+ it 'should not override the given length option' do
41
+ options = adapter.add_index(:spud_users, :first_name, :length => 20)
42
+ expect(options[:length]).to eq(20)
43
+ end
44
+ end
45
+
46
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tb_core
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.4
4
+ version: 1.3.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Greg Woods
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-08-11 00:00:00.000000000 Z
11
+ date: 2015-10-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -196,16 +196,16 @@ dependencies:
196
196
  name: mysql2
197
197
  requirement: !ruby/object:Gem::Requirement
198
198
  requirements:
199
- - - ">="
199
+ - - "<"
200
200
  - !ruby/object:Gem::Version
201
- version: '0'
201
+ version: '0.4'
202
202
  type: :development
203
203
  prerelease: false
204
204
  version_requirements: !ruby/object:Gem::Requirement
205
205
  requirements:
206
- - - ">="
206
+ - - "<"
207
207
  - !ruby/object:Gem::Version
208
- version: '0'
208
+ version: '0.4'
209
209
  - !ruby/object:Gem::Dependency
210
210
  name: rspec-rails
211
211
  requirement: !ruby/object:Gem::Requirement
@@ -295,6 +295,7 @@ files:
295
295
  - app/assets/javascripts/admin/core/dashboard.js
296
296
  - app/assets/javascripts/admin/core/date_picker.js
297
297
  - app/assets/javascripts/admin/core/editor.js
298
+ - app/assets/javascripts/admin/core/jquery_ui.js
298
299
  - app/assets/javascripts/admin/core/modal.js
299
300
  - app/assets/javascripts/admin/core/preinit.js
300
301
  - app/assets/javascripts/admin/core/roles.js
@@ -309,6 +310,7 @@ files:
309
310
  - app/assets/libs/datepicker/less/datepicker.less
310
311
  - app/assets/stylesheets/admin/application.css
311
312
  - app/assets/stylesheets/admin/core/application.scss
313
+ - app/assets/stylesheets/admin/core/jquery_ui.scss
312
314
  - app/assets/stylesheets/admin/core/login.scss
313
315
  - app/assets/stylesheets/admin/core/users.scss
314
316
  - app/controllers/admin/application_controller.rb
@@ -419,6 +421,7 @@ files:
419
421
  - lib/tasks/spud_core_tasks.rake
420
422
  - lib/tb_core.rb
421
423
  - lib/tb_core/form_builder.rb
424
+ - lib/tb_core/mysql2_extensions.rb
422
425
  - lib/tb_core/responder.rb
423
426
  - lib/tb_core/test_helper.rb
424
427
  - spec/controllers/admin/application_controller_spec.rb
@@ -475,6 +478,7 @@ files:
475
478
  - spec/factories/spud_user_factories.rb
476
479
  - spec/helpers/spud/admin/application_helper_spec.rb
477
480
  - spec/lib/spud_core/configuration_spec.rb
481
+ - spec/lib/tb_core/mysql2_extensions_spec.rb
478
482
  - spec/models/spud_role_spec.rb
479
483
  - spec/models/spud_user_spec.rb
480
484
  - spec/rails_helper.rb
@@ -557,6 +561,7 @@ test_files:
557
561
  - spec/factories/spud_user_factories.rb
558
562
  - spec/helpers/spud/admin/application_helper_spec.rb
559
563
  - spec/lib/spud_core/configuration_spec.rb
564
+ - spec/lib/tb_core/mysql2_extensions_spec.rb
560
565
  - spec/models/spud_role_spec.rb
561
566
  - spec/models/spud_user_spec.rb
562
567
  - spec/rails_helper.rb