padrino-admin 0.17.0 → 0.18.1
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/README.rdoc +1 -1
- data/Rakefile +0 -21
- data/lib/padrino-admin/access_control.rb +3 -2
- data/lib/padrino-admin/generators/actions.rb +1 -1
- data/lib/padrino-admin/generators/admin_app.rb +1 -2
- data/lib/padrino-admin/generators/admin_page.rb +5 -0
- data/lib/padrino-admin/generators/orm.rb +15 -26
- data/lib/padrino-admin/generators/templates/account/mongoid.rb.tt +1 -1
- data/lib/padrino-admin/generators/templates/app/controllers/sessions.rb.tt +0 -8
- data/lib/padrino-admin/generators/templates/app.rb.tt +4 -2
- data/lib/padrino-admin/generators/templates/assets/javascripts/bootstrap/affix.js +63 -36
- data/lib/padrino-admin/generators/templates/assets/javascripts/bootstrap/alert.js +18 -11
- data/lib/padrino-admin/generators/templates/assets/javascripts/bootstrap/bootstrap.min.js +4 -4
- data/lib/padrino-admin/generators/templates/assets/javascripts/bootstrap/button.js +41 -23
- data/lib/padrino-admin/generators/templates/assets/javascripts/bootstrap/carousel.js +90 -49
- data/lib/padrino-admin/generators/templates/assets/javascripts/bootstrap/collapse.js +86 -44
- data/lib/padrino-admin/generators/templates/assets/javascripts/bootstrap/dropdown.js +66 -48
- data/lib/padrino-admin/generators/templates/assets/javascripts/bootstrap/modal.js +167 -52
- data/lib/padrino-admin/generators/templates/assets/javascripts/bootstrap/popover.js +33 -20
- data/lib/padrino-admin/generators/templates/assets/javascripts/bootstrap/scrollspy.js +58 -39
- data/lib/padrino-admin/generators/templates/assets/javascripts/bootstrap/tab.js +55 -25
- data/lib/padrino-admin/generators/templates/assets/javascripts/bootstrap/tooltip.js +370 -92
- data/lib/padrino-admin/generators/templates/assets/javascripts/bootstrap/transition.js +22 -11
- data/lib/padrino-admin/generators/templates/assets/stylesheets/application.css +14 -0
- data/lib/padrino-admin/generators/templates/assets/stylesheets/bootstrap.css +6 -4
- data/lib/padrino-admin/generators/templates/erb/app/base/index.erb.tt +1 -1
- data/lib/padrino-admin/generators/templates/erb/app/sessions/new.erb.tt +0 -6
- data/lib/padrino-admin/generators/templates/erb/page/index.erb.tt +2 -2
- data/lib/padrino-admin/generators/templates/haml/app/base/index.haml.tt +1 -1
- data/lib/padrino-admin/generators/templates/haml/app/sessions/new.haml.tt +0 -6
- data/lib/padrino-admin/generators/templates/slim/app/base/index.slim.tt +1 -1
- data/lib/padrino-admin/generators/templates/slim/app/sessions/new.slim.tt +0 -6
- data/lib/padrino-admin/generators/templates/slim/page/index.slim.tt +2 -2
- data/lib/padrino-admin/helpers/authentication_helpers.rb +1 -1
- data/lib/padrino-admin/helpers/view_helpers.rb +3 -3
- data/lib/padrino-admin/locale/orm/pl.yml +0 -11
- data/lib/padrino-admin.rb +1 -1
- data/padrino-admin.gemspec +0 -2
- data/test/generators/test_account_model_generator.rb +0 -24
- data/test/generators/test_admin_app_generator.rb +13 -10
- data/test/generators/test_admin_page_generator.rb +86 -8
- data/test/test_admin_application.rb +22 -0
- metadata +8 -120
- data/lib/padrino-admin/bootstrap-less/alerts.less +0 -67
- data/lib/padrino-admin/bootstrap-less/badges.less +0 -55
- data/lib/padrino-admin/bootstrap-less/bootstrap.less +0 -49
- data/lib/padrino-admin/bootstrap-less/breadcrumbs.less +0 -26
- data/lib/padrino-admin/bootstrap-less/button-groups.less +0 -226
- data/lib/padrino-admin/bootstrap-less/buttons.less +0 -155
- data/lib/padrino-admin/bootstrap-less/carousel.less +0 -232
- data/lib/padrino-admin/bootstrap-less/close.less +0 -33
- data/lib/padrino-admin/bootstrap-less/code.less +0 -63
- data/lib/padrino-admin/bootstrap-less/component-animations.less +0 -29
- data/lib/padrino-admin/bootstrap-less/dropdowns.less +0 -213
- data/lib/padrino-admin/bootstrap-less/font-awesome/bordered-pulled.less +0 -16
- data/lib/padrino-admin/bootstrap-less/font-awesome/core.less +0 -12
- data/lib/padrino-admin/bootstrap-less/font-awesome/fixed-width.less +0 -6
- data/lib/padrino-admin/bootstrap-less/font-awesome/font-awesome.less +0 -17
- data/lib/padrino-admin/bootstrap-less/font-awesome/icons.less +0 -412
- data/lib/padrino-admin/bootstrap-less/font-awesome/larger.less +0 -13
- data/lib/padrino-admin/bootstrap-less/font-awesome/list.less +0 -19
- data/lib/padrino-admin/bootstrap-less/font-awesome/mixins.less +0 -20
- data/lib/padrino-admin/bootstrap-less/font-awesome/path.less +0 -14
- data/lib/padrino-admin/bootstrap-less/font-awesome/rotated-flipped.less +0 -9
- data/lib/padrino-admin/bootstrap-less/font-awesome/spinning.less +0 -30
- data/lib/padrino-admin/bootstrap-less/font-awesome/stacked.less +0 -20
- data/lib/padrino-admin/bootstrap-less/font-awesome/variables.less +0 -381
- data/lib/padrino-admin/bootstrap-less/forms.less +0 -419
- data/lib/padrino-admin/bootstrap-less/glyphicons.less +0 -233
- data/lib/padrino-admin/bootstrap-less/grid.less +0 -100
- data/lib/padrino-admin/bootstrap-less/input-groups.less +0 -157
- data/lib/padrino-admin/bootstrap-less/jumbotron.less +0 -44
- data/lib/padrino-admin/bootstrap-less/labels.less +0 -64
- data/lib/padrino-admin/bootstrap-less/list-group.less +0 -110
- data/lib/padrino-admin/bootstrap-less/media.less +0 -56
- data/lib/padrino-admin/bootstrap-less/mixins.less +0 -926
- data/lib/padrino-admin/bootstrap-less/modals.less +0 -138
- data/lib/padrino-admin/bootstrap-less/navbar.less +0 -616
- data/lib/padrino-admin/bootstrap-less/navs.less +0 -242
- data/lib/padrino-admin/bootstrap-less/normalize.less +0 -423
- data/lib/padrino-admin/bootstrap-less/padrino-admin.less +0 -18
- data/lib/padrino-admin/bootstrap-less/pager.less +0 -55
- data/lib/padrino-admin/bootstrap-less/pagination.less +0 -88
- data/lib/padrino-admin/bootstrap-less/panels.less +0 -230
- data/lib/padrino-admin/bootstrap-less/popovers.less +0 -133
- data/lib/padrino-admin/bootstrap-less/print.less +0 -101
- data/lib/padrino-admin/bootstrap-less/progress-bars.less +0 -80
- data/lib/padrino-admin/bootstrap-less/responsive-utilities.less +0 -93
- data/lib/padrino-admin/bootstrap-less/scaffolding.less +0 -134
- data/lib/padrino-admin/bootstrap-less/tables.less +0 -233
- data/lib/padrino-admin/bootstrap-less/theme.less +0 -247
- data/lib/padrino-admin/bootstrap-less/thumbnails.less +0 -36
- data/lib/padrino-admin/bootstrap-less/tooltip.less +0 -95
- data/lib/padrino-admin/bootstrap-less/type.less +0 -296
- data/lib/padrino-admin/bootstrap-less/utilities.less +0 -56
- data/lib/padrino-admin/bootstrap-less/variables.less +0 -827
- data/lib/padrino-admin/bootstrap-less/wells.less +0 -29
- data/lib/padrino-admin/generators/templates/account/dynamoid.rb.tt +0 -55
- data/lib/padrino-admin/generators/templates/account/minirecord.rb.tt +0 -44
- data/lib/padrino-admin/generators/templates/account/ohm.rb.tt +0 -70
- data/lib/padrino-admin/locale/orm/cs.yml +0 -12
- data/lib/padrino-admin/locale/orm/da.yml +0 -12
- data/lib/padrino-admin/locale/orm/de.yml +0 -12
- data/lib/padrino-admin/locale/orm/en.yml +0 -12
- data/lib/padrino-admin/locale/orm/es.yml +0 -12
- data/lib/padrino-admin/locale/orm/fr.yml +0 -12
- data/lib/padrino-admin/locale/orm/hu.yml +0 -12
- data/lib/padrino-admin/locale/orm/it.yml +0 -12
- data/lib/padrino-admin/locale/orm/ja.yml +0 -12
- data/lib/padrino-admin/locale/orm/lv.yml +0 -12
- data/lib/padrino-admin/locale/orm/nl.yml +0 -12
- data/lib/padrino-admin/locale/orm/no.yml +0 -12
- data/lib/padrino-admin/locale/orm/pt_br.yml +0 -12
- data/lib/padrino-admin/locale/orm/ro.yml +0 -12
- data/lib/padrino-admin/locale/orm/ru.yml +0 -12
- data/lib/padrino-admin/locale/orm/sv.yml +0 -12
- data/lib/padrino-admin/locale/orm/tr.yml +0 -12
- data/lib/padrino-admin/locale/orm/uk.yml +0 -12
- data/lib/padrino-admin/locale/orm/zh_cn.yml +0 -12
- data/lib/padrino-admin/locale/orm/zh_tw.yml +0 -12
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 281388666c8cb872b46f3ce068940e8718006d27375c7a81b5281e09e8a250de
|
|
4
|
+
data.tar.gz: e3b4d990cc8c9d48954531eeb3234efadc0d46ab2a63fdf34cce3f1e8ce218ac
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7c2b5c039a5c8716aaeb1f4e6a1aad7bf61aeee5994cb567e425a3580050d282e473e033037a603ceb85feeef1a84fcb8d0f3d056e5916d97bd2bcec54398e79
|
|
7
|
+
data.tar.gz: e58b0d302e3d6ff10a2ae6866e55640819512d6309e06a595138a91ee61e3ff1789abd898dfe233245d97a49dcf366d6014d5d5b8f5ba9d1723c6aa0ebbebb97
|
data/README.rdoc
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
Padrino has a beautiful Admin management dashboard with these features:
|
|
6
6
|
|
|
7
|
-
Orm Agnostic:: Data Adapters for Activerecord,
|
|
7
|
+
Orm Agnostic:: Data Adapters for Activerecord, Sequel, Mongoid
|
|
8
8
|
Template Agnostic:: Erb, Erubis and Haml Renderer
|
|
9
9
|
Authentication:: Support for Account authentication, Account Permission management
|
|
10
10
|
Scaffold:: You can simply create a new "admin interface" by providing a Model
|
data/Rakefile
CHANGED
|
@@ -1,22 +1 @@
|
|
|
1
1
|
require_relative '../gem_rake_helper'
|
|
2
|
-
|
|
3
|
-
namespace :bootstrap do
|
|
4
|
-
desc 'Compile bootstrap assets'
|
|
5
|
-
task :compile do
|
|
6
|
-
puts 'Implement'
|
|
7
|
-
end
|
|
8
|
-
|
|
9
|
-
desc 'Compile css'
|
|
10
|
-
task :css do
|
|
11
|
-
require 'less'
|
|
12
|
-
src = File.join(__dir__, 'lib', 'padrino-admin', 'bootstrap-less', 'padrino-admin.less')
|
|
13
|
-
out = File.join(__dir__, 'lib', 'padrino-admin', 'generators', 'templates', 'assets', 'stylesheets', 'bootstrap.css')
|
|
14
|
-
css = Less::Parser.new(paths: [File.dirname(src)]).parse(File.read(src)).to_css(compress: true)
|
|
15
|
-
File.open(out, 'w') { |file| file.write css }
|
|
16
|
-
puts "Generated #{out}"
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
desc 'Compile js'
|
|
20
|
-
task :js do
|
|
21
|
-
end
|
|
22
|
-
end
|
|
@@ -104,7 +104,8 @@ module Padrino
|
|
|
104
104
|
#
|
|
105
105
|
def allowed?(account = nil, path = nil)
|
|
106
106
|
path = '/' if path.nil? || path.empty?
|
|
107
|
-
path
|
|
107
|
+
# Compare the decoded path; scrub invalid UTF-8 ('/%ff') so Regexp rules can match it.
|
|
108
|
+
path = Rack::Utils.unescape_path(path.b).force_encoding(Encoding::UTF_8).scrub
|
|
108
109
|
role = account.role.to_sym rescue nil
|
|
109
110
|
authorizations = @authorizations.find_all { |auth| auth.roles.include?(:any) }
|
|
110
111
|
allowed_paths = authorizations.map(&:allowed).flatten.uniq
|
|
@@ -187,7 +188,7 @@ module Padrino
|
|
|
187
188
|
# Returns the name of the project module humanize them for you.
|
|
188
189
|
#
|
|
189
190
|
def human_name
|
|
190
|
-
@name
|
|
191
|
+
Padrino::Inflections.humanize(@name)
|
|
191
192
|
end
|
|
192
193
|
|
|
193
194
|
##
|
|
@@ -76,7 +76,7 @@ module Padrino
|
|
|
76
76
|
RUBY
|
|
77
77
|
|
|
78
78
|
unless options[:destroy]
|
|
79
|
-
insert_middleware 'ConnectionPoolManagement', @admin_path if
|
|
79
|
+
insert_middleware 'ConnectionPoolManagement', @admin_path if orm == :activerecord
|
|
80
80
|
end
|
|
81
81
|
|
|
82
82
|
params = [
|
|
@@ -150,7 +150,6 @@ module Padrino
|
|
|
150
150
|
instructions << "Run 'bundle exec rake db:create' if you have not created a database yet"
|
|
151
151
|
instructions << "Run 'bundle exec rake db:migrate'"
|
|
152
152
|
end
|
|
153
|
-
instructions << "Now repeat after me... 'ohm mani padme hum', 'ohm mani padme hum'... :)" if orm == :ohm
|
|
154
153
|
instructions << "Run 'bundle exec rake db:seed'"
|
|
155
154
|
instructions << "Visit the admin panel in the browser at '/#{@admin_path}'"
|
|
156
155
|
instructions.map! { |i| " #{instructions.index(i) + 1}) #{i}" }
|
|
@@ -41,6 +41,11 @@ module Padrino
|
|
|
41
41
|
def create_controller
|
|
42
42
|
self.destination_root = options[:root]
|
|
43
43
|
if in_app_root?
|
|
44
|
+
unless supported_orm.include?(orm)
|
|
45
|
+
say "<= At the moment, Padrino only supports #{supported_orm.join(' or ')}. Sorry!", :yellow
|
|
46
|
+
exit 1
|
|
47
|
+
end
|
|
48
|
+
|
|
44
49
|
@app_name = fetch_app_name
|
|
45
50
|
@admin_name = options[:admin_name].classify
|
|
46
51
|
@admin_path = options[:admin_name].underscore
|
|
@@ -4,19 +4,17 @@ module Padrino
|
|
|
4
4
|
# Contains all admin related generator functionality.
|
|
5
5
|
#
|
|
6
6
|
module Generators
|
|
7
|
-
# Defines a generic exception for the admin ORM handler.
|
|
8
|
-
|
|
7
|
+
# Defines a generic exception for the admin ORM handler. A Thor::Error, so the
|
|
8
|
+
# generators print its message without a backtrace and exit with status 1.
|
|
9
|
+
class OrmError < Thor::Error; end
|
|
9
10
|
|
|
10
11
|
##
|
|
11
12
|
# Defines the generic ORM management functions used to manipulate data for admin.
|
|
12
13
|
class Orm
|
|
13
14
|
MODEL_BASES = {
|
|
14
15
|
activerecord: 'ActiveRecord::Base',
|
|
15
|
-
minirecord: 'ActiveRecord::Base',
|
|
16
16
|
mongoid: 'Mongoid::Document',
|
|
17
|
-
sequel: 'Sequel::Model'
|
|
18
|
-
ohm: 'Ohm::Model',
|
|
19
|
-
dynamoid: 'Dynamoid::Document'
|
|
17
|
+
sequel: 'Sequel::Model'
|
|
20
18
|
}.freeze
|
|
21
19
|
|
|
22
20
|
attr_reader :klass_name, :klass, :name_plural, :name_singular, :orm, :name_param
|
|
@@ -31,13 +29,13 @@ module Padrino
|
|
|
31
29
|
@orm = orm.to_sym
|
|
32
30
|
@columns = columns
|
|
33
31
|
@column_fields = column_fields
|
|
34
|
-
raise OrmError, "Model '#{klass_name}' could not be found!\nPerhaps you would like to run 'bundle exec padrino g model #{klass_name}' to create it first?" if @columns.nil? && @klass.nil?
|
|
35
32
|
end
|
|
36
33
|
|
|
37
|
-
# Raises OrmError when the model does not belong to the project's orm. Only
|
|
38
|
-
# reading the model's columns to generate a page, so destroying a page skips it.
|
|
34
|
+
# Raises OrmError when the model is missing or does not belong to the project's orm. Only
|
|
35
|
+
# needed when reading the model's columns to generate a page, so destroying a page skips it.
|
|
39
36
|
def check_model_orm
|
|
40
37
|
return unless @columns.nil?
|
|
38
|
+
raise OrmError, "Model '#{klass_name}' could not be found!\nPerhaps you would like to run 'bundle exec padrino g model #{klass_name}' to create it first?" if @klass.nil?
|
|
41
39
|
|
|
42
40
|
base = MODEL_BASES[orm]
|
|
43
41
|
return if base.nil? || @klass.ancestors.any? { |mod| mod.name == base }
|
|
@@ -46,10 +44,7 @@ module Padrino
|
|
|
46
44
|
end
|
|
47
45
|
|
|
48
46
|
def activerecord?
|
|
49
|
-
|
|
50
|
-
when :activerecord, :minirecord then true
|
|
51
|
-
else false
|
|
52
|
-
end
|
|
47
|
+
orm == :activerecord
|
|
53
48
|
end
|
|
54
49
|
|
|
55
50
|
def field_type(type)
|
|
@@ -71,11 +66,8 @@ module Padrino
|
|
|
71
66
|
@columns ||=
|
|
72
67
|
case orm
|
|
73
68
|
when :activerecord then @klass.columns
|
|
74
|
-
when :minirecord then @klass.columns
|
|
75
69
|
when :mongoid then @klass.fields.values.reject { |col| %w[_id _type].include?(col.name) }
|
|
76
70
|
when :sequel then @klass.db_schema.map { |k, v| v[:type] = :text if v[:db_type] =~ /^text/i; Column.new(k, v[:type]) }
|
|
77
|
-
when :ohm then @klass.attributes.map { |a| Column.new(a.to_s, :string) } # ohm has strings
|
|
78
|
-
when :dynamoid then @klass.attributes.map { |k, v| Column.new(k.to_s, v[:type]) }
|
|
79
71
|
else raise OrmError, "Adapter #{orm} is not yet supported!"
|
|
80
72
|
end
|
|
81
73
|
end
|
|
@@ -95,8 +87,8 @@ module Padrino
|
|
|
95
87
|
|
|
96
88
|
def find(params = nil)
|
|
97
89
|
case orm
|
|
98
|
-
when :activerecord, :
|
|
99
|
-
when :sequel
|
|
90
|
+
when :activerecord, :mongoid then "#{klass_name}.find(#{params})"
|
|
91
|
+
when :sequel then "#{klass_name}[#{params}]"
|
|
100
92
|
else raise OrmError, "Adapter #{orm} is not yet supported!"
|
|
101
93
|
end
|
|
102
94
|
end
|
|
@@ -115,39 +107,36 @@ module Padrino
|
|
|
115
107
|
|
|
116
108
|
def update_attributes(params = nil)
|
|
117
109
|
case orm
|
|
118
|
-
when :mongoid
|
|
119
|
-
when :activerecord
|
|
110
|
+
when :mongoid then "@#{name_singular}.update_attributes(#{params})"
|
|
111
|
+
when :activerecord then "@#{name_singular}.update(#{params})"
|
|
120
112
|
when :sequel then "@#{name_singular}.modified! && @#{name_singular}.update(#{params})"
|
|
121
113
|
else raise OrmError, "Adapter #{orm} is not yet supported!"
|
|
122
114
|
end
|
|
123
115
|
end
|
|
124
116
|
|
|
125
117
|
def destroy
|
|
126
|
-
|
|
118
|
+
"#{name_singular}.destroy"
|
|
127
119
|
end
|
|
128
120
|
|
|
129
121
|
def find_by_ids(params = nil)
|
|
130
122
|
case orm
|
|
131
|
-
when :ohm then "#{klass_name}.fetch(#{params})"
|
|
132
123
|
when :sequel then "#{klass_name}.where(id: #{params})"
|
|
133
124
|
when :mongoid then "#{klass_name}.find(#{params})"
|
|
134
|
-
when :dynamoid then "#{klass_name}.find(#{params})"
|
|
135
125
|
else find(params)
|
|
136
126
|
end
|
|
137
127
|
end
|
|
138
128
|
|
|
139
129
|
def multiple_destroy(params = nil)
|
|
140
130
|
case orm
|
|
141
|
-
when :ohm then "#{params}.each(&:delete)"
|
|
142
131
|
when :sequel then "#{params}.destroy"
|
|
143
|
-
when :mongoid
|
|
132
|
+
when :mongoid then "#{params}.each(&:destroy)"
|
|
144
133
|
else "#{klass_name}.destroy #{params}"
|
|
145
134
|
end
|
|
146
135
|
end
|
|
147
136
|
|
|
148
137
|
def has_error(field)
|
|
149
138
|
case orm
|
|
150
|
-
when :
|
|
139
|
+
when :sequel then "@#{name_singular}.errors.key?(:#{field}) && @#{name_singular}.errors[:#{field}].count > 0"
|
|
151
140
|
else "@#{name_singular}.errors.include?(:#{field})"
|
|
152
141
|
end
|
|
153
142
|
end
|
|
@@ -27,7 +27,7 @@ class <%= @model_name %>
|
|
|
27
27
|
# This method is for authentication purpose.
|
|
28
28
|
#
|
|
29
29
|
def self.authenticate(email, password)
|
|
30
|
-
account = where(email:
|
|
30
|
+
account = where(email: /\A#{Object::Regexp.escape(email)}\z/i).first if email.present?
|
|
31
31
|
account if account&.has_password?(password)
|
|
32
32
|
end
|
|
33
33
|
|
|
@@ -7,14 +7,6 @@
|
|
|
7
7
|
if account = <%= @model_name %>.authenticate(params[:email], params[:password])
|
|
8
8
|
set_current_account(account)
|
|
9
9
|
redirect url(:base, :index)
|
|
10
|
-
elsif Padrino.env == :development && params[:bypass]
|
|
11
|
-
<%- if @orm == :ohm -%>
|
|
12
|
-
account = <%= @model_name %>.all.first
|
|
13
|
-
<%- else -%>
|
|
14
|
-
account = <%= @model_name %>.first
|
|
15
|
-
<%- end -%>
|
|
16
|
-
set_current_account(account)
|
|
17
|
-
redirect url(:base, :index)
|
|
18
10
|
else
|
|
19
11
|
params[:email] = h(params[:email])
|
|
20
12
|
flash.now[:error] = pat('login.error')
|
|
@@ -26,8 +26,10 @@ module <%= @app_name %>
|
|
|
26
26
|
set :admin_model, '<%= @model_name %>'
|
|
27
27
|
set :login_page, '/sessions/new'
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
#
|
|
29
|
+
# The session cookie is Secure (sent over HTTPS only) in production. Over plain HTTP
|
|
30
|
+
# the app then sends no session cookie, so logins and CSRF-protected forms fail. Behind
|
|
31
|
+
# a proxy that terminates TLS, have it send X-Forwarded-Proto: https, or set secure: false.
|
|
32
|
+
set :sessions, same_site: :lax, secure: Padrino.env == :production
|
|
31
33
|
disable :store_location
|
|
32
34
|
|
|
33
35
|
access_control.roles_for :any do |role|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/* ========================================================================
|
|
2
|
-
* Bootstrap: affix.js v3.1
|
|
3
|
-
*
|
|
2
|
+
* Bootstrap: affix.js v3.4.1
|
|
3
|
+
* https://getbootstrap.com/docs/3.4/javascript/#affix
|
|
4
4
|
* ========================================================================
|
|
5
|
-
* Copyright 2011-
|
|
5
|
+
* Copyright 2011-2019 Twitter, Inc.
|
|
6
6
|
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
|
7
7
|
* ======================================================================== */
|
|
8
8
|
|
|
@@ -15,28 +15,56 @@
|
|
|
15
15
|
|
|
16
16
|
var Affix = function (element, options) {
|
|
17
17
|
this.options = $.extend({}, Affix.DEFAULTS, options)
|
|
18
|
-
|
|
18
|
+
|
|
19
|
+
var target = this.options.target === Affix.DEFAULTS.target ? $(this.options.target) : $(document).find(this.options.target)
|
|
20
|
+
|
|
21
|
+
this.$target = target
|
|
19
22
|
.on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))
|
|
20
23
|
.on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this))
|
|
21
24
|
|
|
22
25
|
this.$element = $(element)
|
|
23
|
-
this.affixed =
|
|
24
|
-
this.unpin =
|
|
26
|
+
this.affixed = null
|
|
27
|
+
this.unpin = null
|
|
25
28
|
this.pinnedOffset = null
|
|
26
29
|
|
|
27
30
|
this.checkPosition()
|
|
28
31
|
}
|
|
29
32
|
|
|
30
|
-
Affix.
|
|
33
|
+
Affix.VERSION = '3.4.1'
|
|
34
|
+
|
|
35
|
+
Affix.RESET = 'affix affix-top affix-bottom'
|
|
31
36
|
|
|
32
37
|
Affix.DEFAULTS = {
|
|
33
|
-
offset: 0
|
|
38
|
+
offset: 0,
|
|
39
|
+
target: window
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) {
|
|
43
|
+
var scrollTop = this.$target.scrollTop()
|
|
44
|
+
var position = this.$element.offset()
|
|
45
|
+
var targetHeight = this.$target.height()
|
|
46
|
+
|
|
47
|
+
if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false
|
|
48
|
+
|
|
49
|
+
if (this.affixed == 'bottom') {
|
|
50
|
+
if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom'
|
|
51
|
+
return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom'
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
var initializing = this.affixed == null
|
|
55
|
+
var colliderTop = initializing ? scrollTop : position.top
|
|
56
|
+
var colliderHeight = initializing ? targetHeight : height
|
|
57
|
+
|
|
58
|
+
if (offsetTop != null && scrollTop <= offsetTop) return 'top'
|
|
59
|
+
if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom'
|
|
60
|
+
|
|
61
|
+
return false
|
|
34
62
|
}
|
|
35
63
|
|
|
36
64
|
Affix.prototype.getPinnedOffset = function () {
|
|
37
65
|
if (this.pinnedOffset) return this.pinnedOffset
|
|
38
66
|
this.$element.removeClass(Affix.RESET).addClass('affix')
|
|
39
|
-
var scrollTop = this.$
|
|
67
|
+
var scrollTop = this.$target.scrollTop()
|
|
40
68
|
var position = this.$element.offset()
|
|
41
69
|
return (this.pinnedOffset = position.top - scrollTop)
|
|
42
70
|
}
|
|
@@ -48,43 +76,41 @@
|
|
|
48
76
|
Affix.prototype.checkPosition = function () {
|
|
49
77
|
if (!this.$element.is(':visible')) return
|
|
50
78
|
|
|
51
|
-
var
|
|
52
|
-
var scrollTop = this.$window.scrollTop()
|
|
53
|
-
var position = this.$element.offset()
|
|
79
|
+
var height = this.$element.height()
|
|
54
80
|
var offset = this.options.offset
|
|
55
81
|
var offsetTop = offset.top
|
|
56
82
|
var offsetBottom = offset.bottom
|
|
57
|
-
|
|
58
|
-
if (this.affixed == 'top') position.top += scrollTop
|
|
83
|
+
var scrollHeight = Math.max($(document).height(), $(document.body).height())
|
|
59
84
|
|
|
60
85
|
if (typeof offset != 'object') offsetBottom = offsetTop = offset
|
|
61
86
|
if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element)
|
|
62
87
|
if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element)
|
|
63
88
|
|
|
64
|
-
var affix = this.
|
|
65
|
-
offsetBottom != null && (position.top + this.$element.height() >= scrollHeight - offsetBottom) ? 'bottom' :
|
|
66
|
-
offsetTop != null && (scrollTop <= offsetTop) ? 'top' : false
|
|
89
|
+
var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom)
|
|
67
90
|
|
|
68
|
-
if (this.affixed
|
|
69
|
-
|
|
91
|
+
if (this.affixed != affix) {
|
|
92
|
+
if (this.unpin != null) this.$element.css('top', '')
|
|
70
93
|
|
|
71
|
-
|
|
72
|
-
|
|
94
|
+
var affixType = 'affix' + (affix ? '-' + affix : '')
|
|
95
|
+
var e = $.Event(affixType + '.bs.affix')
|
|
73
96
|
|
|
74
|
-
|
|
97
|
+
this.$element.trigger(e)
|
|
75
98
|
|
|
76
|
-
|
|
99
|
+
if (e.isDefaultPrevented()) return
|
|
77
100
|
|
|
78
|
-
|
|
79
|
-
|
|
101
|
+
this.affixed = affix
|
|
102
|
+
this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null
|
|
80
103
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
104
|
+
this.$element
|
|
105
|
+
.removeClass(Affix.RESET)
|
|
106
|
+
.addClass(affixType)
|
|
107
|
+
.trigger(affixType.replace('affix', 'affixed') + '.bs.affix')
|
|
108
|
+
}
|
|
85
109
|
|
|
86
110
|
if (affix == 'bottom') {
|
|
87
|
-
this.$element.offset({
|
|
111
|
+
this.$element.offset({
|
|
112
|
+
top: scrollHeight - height - offsetBottom
|
|
113
|
+
})
|
|
88
114
|
}
|
|
89
115
|
}
|
|
90
116
|
|
|
@@ -92,9 +118,7 @@
|
|
|
92
118
|
// AFFIX PLUGIN DEFINITION
|
|
93
119
|
// =======================
|
|
94
120
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
$.fn.affix = function (option) {
|
|
121
|
+
function Plugin(option) {
|
|
98
122
|
return this.each(function () {
|
|
99
123
|
var $this = $(this)
|
|
100
124
|
var data = $this.data('bs.affix')
|
|
@@ -105,6 +129,9 @@
|
|
|
105
129
|
})
|
|
106
130
|
}
|
|
107
131
|
|
|
132
|
+
var old = $.fn.affix
|
|
133
|
+
|
|
134
|
+
$.fn.affix = Plugin
|
|
108
135
|
$.fn.affix.Constructor = Affix
|
|
109
136
|
|
|
110
137
|
|
|
@@ -127,10 +154,10 @@
|
|
|
127
154
|
|
|
128
155
|
data.offset = data.offset || {}
|
|
129
156
|
|
|
130
|
-
if (data.offsetBottom) data.offset.bottom = data.offsetBottom
|
|
131
|
-
if (data.offsetTop)
|
|
157
|
+
if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom
|
|
158
|
+
if (data.offsetTop != null) data.offset.top = data.offsetTop
|
|
132
159
|
|
|
133
|
-
$spy
|
|
160
|
+
Plugin.call($spy, data)
|
|
134
161
|
})
|
|
135
162
|
})
|
|
136
163
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/* ========================================================================
|
|
2
|
-
* Bootstrap: alert.js v3.1
|
|
3
|
-
*
|
|
2
|
+
* Bootstrap: alert.js v3.4.1
|
|
3
|
+
* https://getbootstrap.com/docs/3.4/javascript/#alerts
|
|
4
4
|
* ========================================================================
|
|
5
|
-
* Copyright 2011-
|
|
5
|
+
* Copyright 2011-2019 Twitter, Inc.
|
|
6
6
|
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
|
7
7
|
* ======================================================================== */
|
|
8
8
|
|
|
@@ -18,6 +18,10 @@
|
|
|
18
18
|
$(el).on('click', dismiss, this.close)
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
Alert.VERSION = '3.4.1'
|
|
22
|
+
|
|
23
|
+
Alert.TRANSITION_DURATION = 150
|
|
24
|
+
|
|
21
25
|
Alert.prototype.close = function (e) {
|
|
22
26
|
var $this = $(this)
|
|
23
27
|
var selector = $this.attr('data-target')
|
|
@@ -27,12 +31,13 @@
|
|
|
27
31
|
selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
|
|
28
32
|
}
|
|
29
33
|
|
|
30
|
-
|
|
34
|
+
selector = selector === '#' ? [] : selector
|
|
35
|
+
var $parent = $(document).find(selector)
|
|
31
36
|
|
|
32
37
|
if (e) e.preventDefault()
|
|
33
38
|
|
|
34
39
|
if (!$parent.length) {
|
|
35
|
-
$parent = $this.
|
|
40
|
+
$parent = $this.closest('.alert')
|
|
36
41
|
}
|
|
37
42
|
|
|
38
43
|
$parent.trigger(e = $.Event('close.bs.alert'))
|
|
@@ -42,13 +47,14 @@
|
|
|
42
47
|
$parent.removeClass('in')
|
|
43
48
|
|
|
44
49
|
function removeElement() {
|
|
45
|
-
|
|
50
|
+
// detach from parent, fire event then clean up data
|
|
51
|
+
$parent.detach().trigger('closed.bs.alert').remove()
|
|
46
52
|
}
|
|
47
53
|
|
|
48
54
|
$.support.transition && $parent.hasClass('fade') ?
|
|
49
55
|
$parent
|
|
50
|
-
.one(
|
|
51
|
-
.emulateTransitionEnd(
|
|
56
|
+
.one('bsTransitionEnd', removeElement)
|
|
57
|
+
.emulateTransitionEnd(Alert.TRANSITION_DURATION) :
|
|
52
58
|
removeElement()
|
|
53
59
|
}
|
|
54
60
|
|
|
@@ -56,9 +62,7 @@
|
|
|
56
62
|
// ALERT PLUGIN DEFINITION
|
|
57
63
|
// =======================
|
|
58
64
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
$.fn.alert = function (option) {
|
|
65
|
+
function Plugin(option) {
|
|
62
66
|
return this.each(function () {
|
|
63
67
|
var $this = $(this)
|
|
64
68
|
var data = $this.data('bs.alert')
|
|
@@ -68,6 +72,9 @@
|
|
|
68
72
|
})
|
|
69
73
|
}
|
|
70
74
|
|
|
75
|
+
var old = $.fn.alert
|
|
76
|
+
|
|
77
|
+
$.fn.alert = Plugin
|
|
71
78
|
$.fn.alert.Constructor = Alert
|
|
72
79
|
|
|
73
80
|
|