tb_core 1.3.4 → 1.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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