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 +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
|