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 +4 -4
- data/app/assets/javascripts/admin/core/application.js +0 -2
- data/app/assets/javascripts/admin/core/dashboard.js +25 -0
- data/app/assets/javascripts/admin/core/jquery_ui.js +22 -0
- data/app/assets/javascripts/tb_core/remote.js +62 -13
- data/app/assets/stylesheets/admin/core/application.scss +0 -2
- data/app/assets/stylesheets/admin/core/jquery_ui.scss +19 -0
- data/app/controllers/admin/dashboard_controller.rb +39 -1
- data/config/routes.rb +1 -0
- data/db/migrate/20111214161146_create_spud_users.rb +2 -2
- data/lib/spud_core/engine.rb +10 -0
- data/lib/spud_core/version.rb +1 -1
- data/lib/tb_core/mysql2_extensions.rb +36 -0
- data/spec/dummy/config/database.yml +5 -2
- data/spec/lib/tb_core/mysql2_extensions_spec.rb +46 -0
- metadata +11 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 06f0ab03560e57efe477e7fb0f9ae6f72a8a042c
|
4
|
+
data.tar.gz: e8d702fe0332d78ae18bc9d0605db1d89ec3cb26
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6b6d73ea8d50f6930b71df507147e5644128cd2a04024522984aed28fe1832dcc1e9e37059945c34e22a31b41747d9a914868af5eead68d5a466917bdd3b0a46
|
7
|
+
data.tar.gz: 778f7e4d4a48508249c54cff93cdda5334a0beddf158e4a5b68eaab544e9cc6539a53b18fc8aa64480267b549a436cf2713f4d7b7344380a6a232ae815071a40
|
@@ -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
|
-
$
|
17
|
-
$
|
18
|
-
$
|
19
|
-
$
|
20
|
-
$
|
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
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
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
|
127
|
+
if(keyArr.length === 2){
|
108
128
|
keyArr[0] += '_attributes';
|
109
129
|
$input = $form.find("[name$='[" + keyArr.join('][') + "]']");
|
110
|
-
}
|
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.
|
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
|
@@ -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
|
-
@
|
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
@@ -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
|
27
|
-
add_index :spud_users
|
26
|
+
add_index :spud_users, :login
|
27
|
+
add_index :spud_users, :email
|
28
28
|
end
|
29
29
|
end
|
data/lib/spud_core/engine.rb
CHANGED
@@ -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
|
data/lib/spud_core/version.rb
CHANGED
@@ -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
|
+
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-
|
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
|