tolaria 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +66 -0
- data/.yardopts +4 -0
- data/CNAME +1 -0
- data/CONTRIBUTING.md +32 -0
- data/Gemfile +2 -0
- data/LICENSE.md +9 -0
- data/README.md +538 -0
- data/Rakefile +52 -0
- data/app/assets/fonts/admin/fontawesome.eot +0 -0
- data/app/assets/fonts/admin/fontawesome.svg +565 -0
- data/app/assets/fonts/admin/fontawesome.ttf +0 -0
- data/app/assets/fonts/admin/fontawesome.woff +0 -0
- data/app/assets/fonts/admin/fontawesome.woff2 +0 -0
- data/app/assets/images/admin/columbia_banner.png +0 -0
- data/app/assets/images/admin/favicon.ico +0 -0
- data/app/assets/images/admin/noise.png +0 -0
- data/app/assets/images/admin/select_arrows.svg +1 -0
- data/app/assets/javascripts/admin/admin.js +4 -0
- data/app/assets/javascripts/admin/base.js +12 -0
- data/app/assets/javascripts/admin/lib/backbone.js +1888 -0
- data/app/assets/javascripts/admin/lib/jquery.chosen.js +1272 -0
- data/app/assets/javascripts/admin/lib/jquery.js +10361 -0
- data/app/assets/javascripts/admin/lib/jquery.selection.js +352 -0
- data/app/assets/javascripts/admin/lib/moment.js +3103 -0
- data/app/assets/javascripts/admin/lib/no.js +6 -0
- data/app/assets/javascripts/admin/lib/underscore.js +1570 -0
- data/app/assets/javascripts/admin/models/composer_buttons.js +45 -0
- data/app/assets/javascripts/admin/models/rails_meta.js +4 -0
- data/app/assets/javascripts/admin/views/field_with_errors.js +19 -0
- data/app/assets/javascripts/admin/views/fields/attachment_field.js +32 -0
- data/app/assets/javascripts/admin/views/fields/has_many.js +64 -0
- data/app/assets/javascripts/admin/views/fields/image_association_select.js +31 -0
- data/app/assets/javascripts/admin/views/fields/markdown_composer.js +167 -0
- data/app/assets/javascripts/admin/views/fields/searchable_select.js +70 -0
- data/app/assets/javascripts/admin/views/fields/slug_field.js +38 -0
- data/app/assets/javascripts/admin/views/fields/swatch_field.js +55 -0
- data/app/assets/javascripts/admin/views/fields/timestamp_field.js +80 -0
- data/app/assets/javascripts/admin/views/flash_message.js +18 -0
- data/app/assets/javascripts/admin/views/form_orchestrator.js +41 -0
- data/app/assets/javascripts/admin/views/navigation.js +20 -0
- data/app/assets/javascripts/admin/views/resource_form.js +18 -0
- data/app/assets/javascripts/admin/views/search_form.js +20 -0
- data/app/assets/javascripts/admin/views/sessions.js +109 -0
- data/app/assets/javascripts/admin/views/virtual_form.js +47 -0
- data/app/assets/stylesheets/admin/_base.scss +5 -0
- data/app/assets/stylesheets/admin/_reset.scss +149 -0
- data/app/assets/stylesheets/admin/_root.scss +63 -0
- data/app/assets/stylesheets/admin/admin.scss +4 -0
- data/app/assets/stylesheets/admin/components/_blank_slate.scss +44 -0
- data/app/assets/stylesheets/admin/components/_buttons.scss +82 -0
- data/app/assets/stylesheets/admin/components/_flash_message.scss +64 -0
- data/app/assets/stylesheets/admin/components/_footer.scss +9 -0
- data/app/assets/stylesheets/admin/components/_header.scss +107 -0
- data/app/assets/stylesheets/admin/components/_index_table.scss +120 -0
- data/app/assets/stylesheets/admin/components/_main.scss +68 -0
- data/app/assets/stylesheets/admin/components/_markdown_body.scss +109 -0
- data/app/assets/stylesheets/admin/components/_navigation.scss +110 -0
- data/app/assets/stylesheets/admin/components/_pagination.scss +36 -0
- data/app/assets/stylesheets/admin/components/_pill.scss +11 -0
- data/app/assets/stylesheets/admin/components/_resource_form.scss +222 -0
- data/app/assets/stylesheets/admin/components/_search_form.scss +36 -0
- data/app/assets/stylesheets/admin/components/_sessions.scss +152 -0
- data/app/assets/stylesheets/admin/components/_show_table.scss +67 -0
- data/app/assets/stylesheets/admin/components/forms/_attachment_field.scss +59 -0
- data/app/assets/stylesheets/admin/components/forms/_chosen.scss +478 -0
- data/app/assets/stylesheets/admin/components/forms/_image_association_select.scss +20 -0
- data/app/assets/stylesheets/admin/components/forms/_markdown_composer.scss +149 -0
- data/app/assets/stylesheets/admin/components/forms/_nested_fields.scss +63 -0
- data/app/assets/stylesheets/admin/components/forms/_searchable_select.scss +8 -0
- data/app/assets/stylesheets/admin/components/forms/_slug_field.scss +20 -0
- data/app/assets/stylesheets/admin/components/forms/_swatch_field.scss +47 -0
- data/app/assets/stylesheets/admin/components/forms/_timestamp_field.scss +15 -0
- data/app/assets/stylesheets/admin/components/help_link.scss +6 -0
- data/app/assets/stylesheets/admin/mixins/_clearfix.scss +18 -0
- data/app/assets/stylesheets/admin/mixins/_min_max_width.scss +11 -0
- data/app/assets/stylesheets/admin/mixins/_rgbb.scss +7 -0
- data/app/assets/stylesheets/admin/mixins/_visuallyhidden.scss +33 -0
- data/app/assets/stylesheets/admin/settings/_animations.scss +21 -0
- data/app/assets/stylesheets/admin/settings/_breakpoints.scss +2 -0
- data/app/assets/stylesheets/admin/settings/_colors.scss +32 -0
- data/app/assets/stylesheets/admin/settings/_fonts.scss +31 -0
- data/app/assets/stylesheets/admin/settings/_icons.scss +1658 -0
- data/app/controllers/admin/admin_controller.rb +21 -0
- data/app/controllers/admin/sessions_controller.rb +112 -0
- data/app/controllers/tolaria/resource_controller.rb +132 -0
- data/app/controllers/tolaria/tolaria_controller.rb +40 -0
- data/app/helpers/admin/table_helper.rb +175 -0
- data/app/helpers/admin/view_helper.rb +76 -0
- data/app/mailers/passcode_mailer.rb +11 -0
- data/app/models/administrator.rb +146 -0
- data/app/views/admin/administrators/_form.html.erb +16 -0
- data/app/views/admin/administrators/_index.html.erb +20 -0
- data/app/views/admin/administrators/_search.html.erb +5 -0
- data/app/views/admin/administrators/_show.html.erb +14 -0
- data/app/views/admin/help/help_link.html.erb +16 -0
- data/app/views/admin/session/form.html.erb +52 -0
- data/app/views/admin/shared/_flash_messages.html.erb +42 -0
- data/app/views/admin/shared/_footer.html.erb +8 -0
- data/app/views/admin/shared/_head.html.erb +11 -0
- data/app/views/admin/shared/_header.html.erb +43 -0
- data/app/views/admin/shared/_navigation.html.erb +47 -0
- data/app/views/admin/shared/_skiplinks.html.erb +0 -0
- data/app/views/admin/shared/forms/_attachment_field.html.erb +17 -0
- data/app/views/admin/shared/forms/_has_many.html.erb +14 -0
- data/app/views/admin/shared/forms/_has_many_header.html.erb +19 -0
- data/app/views/admin/shared/forms/_image_association_select.html.erb +6 -0
- data/app/views/admin/shared/forms/_image_field.html.erb +19 -0
- data/app/views/admin/shared/forms/_markdown_composer.html.erb +29 -0
- data/app/views/admin/shared/forms/_searchable_select.html.erb +3 -0
- data/app/views/admin/shared/forms/_slug_field.html.erb +9 -0
- data/app/views/admin/shared/forms/_swatch_field.html.erb +4 -0
- data/app/views/admin/shared/forms/_timestamp_field.html.erb +19 -0
- data/app/views/admin/tolaria_resource/_form_buttons.html.erb +10 -0
- data/app/views/admin/tolaria_resource/_index_table.html.erb +73 -0
- data/app/views/admin/tolaria_resource/_search_form.html.erb +32 -0
- data/app/views/admin/tolaria_resource/_show_buttons.html.erb +13 -0
- data/app/views/admin/tolaria_resource/edit.html.erb +34 -0
- data/app/views/admin/tolaria_resource/index.html.erb +36 -0
- data/app/views/admin/tolaria_resource/new.html.erb +1 -0
- data/app/views/admin/tolaria_resource/show.html.erb +52 -0
- data/app/views/kaminari/admin/_first_page.html.erb +9 -0
- data/app/views/kaminari/admin/_last_page.html.erb +9 -0
- data/app/views/kaminari/admin/_next_page.html.erb +9 -0
- data/app/views/kaminari/admin/_page.html.erb +17 -0
- data/app/views/kaminari/admin/_paginator.html.erb +21 -0
- data/app/views/kaminari/admin/_prev_page.html.erb +9 -0
- data/app/views/layouts/admin/admin.html.erb +21 -0
- data/app/views/layouts/admin/sessions.html.erb +12 -0
- data/app/views/passcode_mailer/passcode.text.erb +5 -0
- data/lib/generators/tolaria/install/install_generator.rb +21 -0
- data/lib/generators/tolaria/install/templates/administrators_migration.rb +31 -0
- data/lib/generators/tolaria/install/templates/tolaria_initializer.rb +93 -0
- data/lib/tasks/admin.rake +32 -0
- data/lib/tolaria.rb +27 -0
- data/lib/tolaria/active_record.rb +55 -0
- data/lib/tolaria/admin.rb +4 -0
- data/lib/tolaria/categories.rb +21 -0
- data/lib/tolaria/config.rb +40 -0
- data/lib/tolaria/default_config.rb +74 -0
- data/lib/tolaria/engine.rb +23 -0
- data/lib/tolaria/form_buildable.rb +203 -0
- data/lib/tolaria/help_links.rb +78 -0
- data/lib/tolaria/introspection.rb +13 -0
- data/lib/tolaria/manage.rb +57 -0
- data/lib/tolaria/managed_class.rb +90 -0
- data/lib/tolaria/markdown.rb +28 -0
- data/lib/tolaria/random_tokens.rb +16 -0
- data/lib/tolaria/reload.rb +21 -0
- data/lib/tolaria/routes.rb +33 -0
- data/lib/tolaria/version.rb +13 -0
- data/test/demo/Rakefile +4 -0
- data/test/demo/app/assets/javascripts/application.js +1 -0
- data/test/demo/app/assets/stylesheets/application.scss +1 -0
- data/test/demo/app/controllers/application_controller.rb +5 -0
- data/test/demo/app/controllers/concerns/.keep +0 -0
- data/test/demo/app/controllers/homepage_controller.rb +4 -0
- data/test/demo/app/helpers/application_helper.rb +2 -0
- data/test/demo/app/mailers/.keep +0 -0
- data/test/demo/app/models/.keep +0 -0
- data/test/demo/app/models/blog_post.rb +43 -0
- data/test/demo/app/models/footnote.rb +5 -0
- data/test/demo/app/models/image.rb +19 -0
- data/test/demo/app/models/legal_page.rb +24 -0
- data/test/demo/app/models/miscellany.rb +12 -0
- data/test/demo/app/models/topic.rb +22 -0
- data/test/demo/app/models/video.rb +16 -0
- data/test/demo/app/views/admin/blog_posts/_form.html.erb +48 -0
- data/test/demo/app/views/admin/blog_posts/_search.html.erb +5 -0
- data/test/demo/app/views/admin/help/markdown-help.md +95 -0
- data/test/demo/app/views/admin/images/_form.html.erb +26 -0
- data/test/demo/app/views/admin/legal_pages/_form.html.erb +15 -0
- data/test/demo/app/views/admin/topics/_form.html.erb +3 -0
- data/test/demo/app/views/admin/videos/_form.html.erb +11 -0
- data/test/demo/app/views/homepage/homepage.html.erb +3 -0
- data/test/demo/app/views/layouts/application.html.erb +14 -0
- data/test/demo/bin/bundle +3 -0
- data/test/demo/bin/rails +4 -0
- data/test/demo/bin/rake +4 -0
- data/test/demo/bin/setup +29 -0
- data/test/demo/config.ru +4 -0
- data/test/demo/config/application.rb +26 -0
- data/test/demo/config/boot.rb +4 -0
- data/test/demo/config/database.yml +18 -0
- data/test/demo/config/environment.rb +3 -0
- data/test/demo/config/environments/development.rb +43 -0
- data/test/demo/config/environments/test.rb +44 -0
- data/test/demo/config/initializers/assets.rb +11 -0
- data/test/demo/config/initializers/cookies_serializer.rb +2 -0
- data/test/demo/config/initializers/filter_parameter_logging.rb +3 -0
- data/test/demo/config/initializers/inflections.rb +17 -0
- data/test/demo/config/initializers/markdown.rb +44 -0
- data/test/demo/config/initializers/secret_token.rb +2 -0
- data/test/demo/config/initializers/session_store.rb +2 -0
- data/test/demo/config/initializers/tolaria.rb +17 -0
- data/test/demo/config/initializers/wrap_parameters.rb +14 -0
- data/test/demo/config/routes.rb +4 -0
- data/test/demo/db/migrate/20150601202901_create_administrators.rb +31 -0
- data/test/demo/db/migrate/20150603204006_add_testing_models.rb +27 -0
- data/test/demo/db/migrate/20150609232013_create_footnotes.rb +10 -0
- data/test/demo/db/migrate/20150610135235_create_additional_demo_objects.rb +50 -0
- data/test/demo/db/schema.rb +112 -0
- data/test/demo/log/.keep +0 -0
- data/test/demo/public/404.html +67 -0
- data/test/demo/public/422.html +67 -0
- data/test/demo/public/500.html +66 -0
- data/test/demo/public/favicon.ico +0 -0
- data/test/integration/help_link_test.rb +73 -0
- data/test/integration/interface_test.rb +63 -0
- data/test/integration/router_test.rb +73 -0
- data/test/integration/session_test.rb +88 -0
- data/test/test_helper.rb +58 -0
- data/test/unit/configuration_test.rb +21 -0
- data/test/unit/managed_classes_test.rb +54 -0
- data/test/unit/markdown_test.rb +12 -0
- data/test/unit/menu_test.rb +32 -0
- data/test/unit/random_tokens_test.rb +13 -0
- data/tolaria.gemspec +35 -0
- metadata +499 -0
@@ -0,0 +1,21 @@
|
|
1
|
+
class Admin::AdminController < Tolaria::TolariaController
|
2
|
+
|
3
|
+
skip_before_filter :authenticate_admin!, only:[:markdown]
|
4
|
+
|
5
|
+
def root
|
6
|
+
redirect_to(Tolaria.config.default_redirect, status:303)
|
7
|
+
end
|
8
|
+
|
9
|
+
def markdown
|
10
|
+
return render(nothing:true, status:404) unless current_administrator.present?
|
11
|
+
return render(inline:Tolaria.render_markdown(request.raw_post))
|
12
|
+
end
|
13
|
+
|
14
|
+
def help_link
|
15
|
+
@help_link = Tolaria.help_links.find do |help_link|
|
16
|
+
help_link.slug == params[:slug]
|
17
|
+
end or raise ActiveRecord::RecordNotFound
|
18
|
+
return render tolaria_template("help/help_link")
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
class Admin::SessionsController < Tolaria::TolariaController
|
2
|
+
|
3
|
+
skip_before_filter :authenticate_admin!
|
4
|
+
|
5
|
+
# Present the signin form
|
6
|
+
|
7
|
+
def new
|
8
|
+
if current_administrator
|
9
|
+
return redirect_to(Tolaria.config.default_redirect, status:303)
|
10
|
+
end
|
11
|
+
@greeting = random_greeting
|
12
|
+
@admin = Administrator.new
|
13
|
+
return render "admin/session/form", layout:"admin/sessions"
|
14
|
+
end
|
15
|
+
|
16
|
+
# Code request: Dispatch an email with the admin’s passcode, or return JSON errors
|
17
|
+
|
18
|
+
def request_code
|
19
|
+
|
20
|
+
email = params[:administrator].try(:[], :email).to_s.downcase.chomp
|
21
|
+
@administrator = Administrator.find_by_email(email)
|
22
|
+
|
23
|
+
unless @administrator
|
24
|
+
response.status = 404
|
25
|
+
return render json: {
|
26
|
+
status: response.status,
|
27
|
+
error: "That email address couldn’t be found. Contact an existing site administrator if you need an account created for you.",
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
31
|
+
if @administrator.locked?
|
32
|
+
response.status = 423
|
33
|
+
return render json: {
|
34
|
+
status: response.status,
|
35
|
+
error: %{
|
36
|
+
Your account has made too many requests and has been locked.
|
37
|
+
Please try again after #{Tolaria.config.lockout_duration/60} minutes.
|
38
|
+
}.squish,
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
if @administrator.send_passcode_email!
|
43
|
+
@administrator.accrue_strike!
|
44
|
+
response.status = 204
|
45
|
+
return render nothing: true
|
46
|
+
else
|
47
|
+
response.status = 500
|
48
|
+
return render json: {
|
49
|
+
status: response.status,
|
50
|
+
error: "An email couldn’t be sent for you. Please try again later."
|
51
|
+
}
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
# Create: Attempt to sign in the admin with the email/passcode combination.
|
57
|
+
|
58
|
+
def create
|
59
|
+
|
60
|
+
email = params[:administrator].try(:[], :email).to_s.downcase.chomp
|
61
|
+
passcode = params[:administrator].try(:[], :passcode).to_s
|
62
|
+
|
63
|
+
@administrator = Administrator.find_by_email(email)
|
64
|
+
|
65
|
+
if @administrator && @administrator.authenticate!(passcode)
|
66
|
+
|
67
|
+
# Auth successful
|
68
|
+
# Set an signed admin cookie with our auth_token
|
69
|
+
cookies.encrypted[:admin_auth_token] = {
|
70
|
+
value: @administrator.auth_token,
|
71
|
+
expires: params[:remember_me].eql?("1") ? 1.year.from_now : nil,
|
72
|
+
secure: Rails.env.production?, # Expect a TLS connection in production
|
73
|
+
httponly: true, # JavaScript should not read this cookie
|
74
|
+
}
|
75
|
+
|
76
|
+
# Redirect to the admin pane
|
77
|
+
return redirect_to(Tolaria.config.default_redirect, status:303)
|
78
|
+
|
79
|
+
else
|
80
|
+
|
81
|
+
# Auth failed
|
82
|
+
flash[:error] = "That passcode wasn’t correct. Please request a new passcode and try again."
|
83
|
+
return redirect_to(admin_new_session_path, status:303)
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
# Destroy: Sign out the admin and reset the session
|
90
|
+
|
91
|
+
def destroy
|
92
|
+
cookies.delete(:admin_auth_token)
|
93
|
+
reset_session
|
94
|
+
flash[:success] = "You have successfully signed out."
|
95
|
+
return redirect_to(admin_new_session_path, status:303)
|
96
|
+
end
|
97
|
+
|
98
|
+
protected
|
99
|
+
|
100
|
+
# Returns a random UI greeting.
|
101
|
+
def random_greeting
|
102
|
+
case [1,2,3].sample
|
103
|
+
when 1
|
104
|
+
return "Have we met before?"
|
105
|
+
when 2
|
106
|
+
return "Happy #{Date.current.strftime('%A')}!"
|
107
|
+
when 3
|
108
|
+
return "Hey there! Welcome back."
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
class Tolaria::ResourceController < Tolaria::TolariaController
|
2
|
+
|
3
|
+
before_filter :load_managed_class!
|
4
|
+
before_filter :strip_invalid_ransack_params!, only:[:index]
|
5
|
+
|
6
|
+
def index
|
7
|
+
@search = @managed_class.klass.ransack(params[:q])
|
8
|
+
@resources = @search.result
|
9
|
+
if @managed_class.paginated?
|
10
|
+
@resources = @resources.page(params[:page]).per(Tolaria.config.page_size)
|
11
|
+
end
|
12
|
+
unless currently_sorting?
|
13
|
+
@resources = @resources.order(@managed_class.default_order)
|
14
|
+
end
|
15
|
+
return render tolaria_template("tolaria_resource/index")
|
16
|
+
end
|
17
|
+
|
18
|
+
def show
|
19
|
+
@resource = @managed_class.klass.find_by_id(params[:id]) or raise ActiveRecord::RecordNotFound
|
20
|
+
return render tolaria_template("tolaria_resource/show")
|
21
|
+
end
|
22
|
+
|
23
|
+
def new
|
24
|
+
@resource = @managed_class.klass.new
|
25
|
+
return render tolaria_template("tolaria_resource/new")
|
26
|
+
end
|
27
|
+
|
28
|
+
def create
|
29
|
+
|
30
|
+
@resource = @managed_class.klass.new
|
31
|
+
@resource.assign_attributes(resource_params[@managed_class.param_key])
|
32
|
+
display_name = Tolaria.display_name(@resource)
|
33
|
+
|
34
|
+
if @resource.save
|
35
|
+
flash[:success] = "#{random_blingword} You created the #{@managed_class.model_name.human} “#{display_name}”."
|
36
|
+
return redirect_to url_for([:admin, @managed_class.klass])
|
37
|
+
else
|
38
|
+
log_validation_errors!
|
39
|
+
flash.now[:error] = "Your changes couldn’t be saved. Please correct the following errors:"
|
40
|
+
return render tolaria_template("tolaria_resource/new")
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
def edit
|
46
|
+
@resource = @managed_class.klass.find_by_id(params[:id]) or raise ActiveRecord::RecordNotFound
|
47
|
+
return render tolaria_template("tolaria_resource/edit")
|
48
|
+
end
|
49
|
+
|
50
|
+
def update
|
51
|
+
|
52
|
+
@resource = @managed_class.klass.find_by_id(params[:id]) or raise ActiveRecord::RecordNotFound
|
53
|
+
@resource.assign_attributes(resource_params[@managed_class.param_key])
|
54
|
+
display_name = Tolaria.display_name(@resource)
|
55
|
+
|
56
|
+
if @resource.save
|
57
|
+
flash[:success] = "#{random_blingword} You updated the #{@managed_class.model_name.human.downcase} “#{display_name}”."
|
58
|
+
return redirect_to url_for([:admin, @managed_class.klass])
|
59
|
+
else
|
60
|
+
log_validation_errors!
|
61
|
+
flash.now[:error] = "Your changes couldn’t be saved. Please correct the following errors:"
|
62
|
+
return render tolaria_template("tolaria_resource/edit")
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
def destroy
|
68
|
+
|
69
|
+
@resource = @managed_class.klass.find_by_id(params[:id]) or raise ActiveRecord::RecordNotFound
|
70
|
+
display_name = Tolaria.display_name(@resource)
|
71
|
+
|
72
|
+
begin
|
73
|
+
@resource.destroy
|
74
|
+
rescue ActiveRecord::DeleteRestrictionError => e
|
75
|
+
flash[:restricted] = "You cannot delete “#{display_name}” because other items are using it."
|
76
|
+
return redirect_to url_for([:admin, @managed_class.klass])
|
77
|
+
end
|
78
|
+
|
79
|
+
flash[:destructive] = "You deleted the #{@managed_class.model_name.human.downcase} “#{display_name}”."
|
80
|
+
return redirect_to url_for([:admin, @managed_class.klass])
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
protected
|
85
|
+
|
86
|
+
# Returns a random positive expression for use in
|
87
|
+
# flash messages
|
88
|
+
def random_blingword
|
89
|
+
["Done!", "Okay!", "Success!"].sample
|
90
|
+
end
|
91
|
+
|
92
|
+
# Load the Tolaria managed class for this controller
|
93
|
+
def load_managed_class!
|
94
|
+
@managed_class ||= Tolaria.managed_classes.find do |managed_class|
|
95
|
+
self.class.to_s == "Admin::#{managed_class.controller_name}"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# Filters params, allows the default params Tolaria needs
|
100
|
+
# and the configured `permitted_params` from the managed class
|
101
|
+
def resource_params
|
102
|
+
params.permit(
|
103
|
+
*Tolaria.config.permitted_params,
|
104
|
+
@managed_class.param_key => @managed_class.permitted_params
|
105
|
+
)
|
106
|
+
end
|
107
|
+
|
108
|
+
# Some Ransack methods raise exceptions if the `q` param is invalid.
|
109
|
+
# Strip `q` params not created by Ransack
|
110
|
+
def strip_invalid_ransack_params!
|
111
|
+
return true if params[:q].blank?
|
112
|
+
unless params[:q].is_a?(Hash)
|
113
|
+
params.delete(:q)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# Returns true if there is a sorting parameter for Ransack
|
118
|
+
def currently_sorting?
|
119
|
+
params[:q].present? && params[:q][:s].present?
|
120
|
+
end
|
121
|
+
|
122
|
+
# Logs all validation errors for the current resource to the Rails console
|
123
|
+
def log_validation_errors!
|
124
|
+
unless Rails.env.test?
|
125
|
+
puts "#{@resource.class} failed validation and was not saved:"
|
126
|
+
@resource.errors.full_messages.each do |message|
|
127
|
+
puts " #{message}"
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
class Tolaria::TolariaController < ::ApplicationController
|
2
|
+
|
3
|
+
protect_from_forgery
|
4
|
+
before_filter :add_admin_headers!
|
5
|
+
before_filter :authenticate_admin!
|
6
|
+
|
7
|
+
protected
|
8
|
+
|
9
|
+
def add_admin_headers!
|
10
|
+
# Don't use old IE rendering modes
|
11
|
+
response.headers["X-UA-Compatible"] = "IE=edge"
|
12
|
+
# Forbid putting the admin in a frameset/iframe
|
13
|
+
response.headers["X-Frame-Options"] = "DENY"
|
14
|
+
# Strict sniffing and XSS modes for browsers that use these flags
|
15
|
+
response.headers["X-Content-Type-Options"] = "nosniff"
|
16
|
+
response.headers["X-XSS-Protection"] = "1; mode=block"
|
17
|
+
end
|
18
|
+
|
19
|
+
def tolaria_template(name)
|
20
|
+
return {
|
21
|
+
template: "admin/#{name}",
|
22
|
+
layout: "admin/admin"
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
def authenticate_admin!
|
27
|
+
unless current_administrator
|
28
|
+
flash[:error] = "You must log in to continue. Request a passcode below."
|
29
|
+
return redirect_to(admin_new_session_path, status:303)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def current_administrator
|
34
|
+
@current_administrator ||= Administrator.find_by_auth_token(cookies.encrypted[:admin_auth_token])
|
35
|
+
end
|
36
|
+
|
37
|
+
helper_method :current_administrator
|
38
|
+
|
39
|
+
end
|
40
|
+
|
@@ -0,0 +1,175 @@
|
|
1
|
+
module Admin::TableHelper
|
2
|
+
|
3
|
+
# Returns a `<table class="index-table">` tag with the appropriate wrapper
|
4
|
+
# and the given +content+ or block content inside it.
|
5
|
+
def index_table(content = nil, &block)
|
6
|
+
content_tag :div, class:"index-table-wrap" do
|
7
|
+
content_tag :table, class:"index-table" do
|
8
|
+
content || yield
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
# Returns a `<table class="show-table">` tag with the given +content+
|
14
|
+
# or block content inside it.
|
15
|
+
def show_table(content = nil, &block)
|
16
|
+
content_tag :table, class:"show-table" do
|
17
|
+
content || yield
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# Returns the following `<tr>`, suitable for use in a `table.show-table`:
|
22
|
+
#
|
23
|
+
# <tr>
|
24
|
+
# <th>Field</th>
|
25
|
+
# <th>Details</th>
|
26
|
+
# </tr>
|
27
|
+
def show_thead_tr
|
28
|
+
%{<tr><th>Field</th><th>Details</th></tr>}.html_safe
|
29
|
+
end
|
30
|
+
|
31
|
+
# Returns a `<tr>` with two `<td>`s suitable for use in a `table.show-table`.
|
32
|
+
# The given +label+ is placed inside the first `<td>`, while the +value+
|
33
|
+
# is placed in the second `<td>`. Options are forwarded to `content_tag`
|
34
|
+
# for the *second* `<td>`.
|
35
|
+
#
|
36
|
+
# If +label+ is a symbol, it is assumed to be a method on a variable named
|
37
|
+
# `@resource` in the current template, and the `<tr>` is constructed
|
38
|
+
# automatically for you by converting the symbol to a human-readable label
|
39
|
+
# and calling the named method on @resource to get the +value+.
|
40
|
+
#
|
41
|
+
# ==== Signatures
|
42
|
+
#
|
43
|
+
# # Set the values yourself, and a class on the second `<td>`
|
44
|
+
# show_tr "Slug", resource.slug, class:"monospace"
|
45
|
+
#
|
46
|
+
# # Attempt to auto-fill the row based on a method name
|
47
|
+
# show_tr :slug
|
48
|
+
def show_tr(label, value = nil, options = nil)
|
49
|
+
|
50
|
+
if label.is_a?(Symbol)
|
51
|
+
options = value
|
52
|
+
value = @resource.send(label)
|
53
|
+
label = label.to_s.titleize
|
54
|
+
end
|
55
|
+
|
56
|
+
content = content_tag(:td, class:"show-td-field") do
|
57
|
+
content_tag :span do
|
58
|
+
label
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
content << content_tag(:td, options) do
|
63
|
+
value.to_s
|
64
|
+
end
|
65
|
+
|
66
|
+
content_tag(:tr) do
|
67
|
+
content
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
# Returns a `<th>` tag, suitable for use inside a `table.index-table`.
|
73
|
+
# +field_or_label+ may be any string, or a symbol naming a model column.
|
74
|
+
# +sort+ may be `true`, `false`, or a symbol. See the signtures below.
|
75
|
+
#
|
76
|
+
# If the column is sortable, the `<th>` will contain a Ransack sort link
|
77
|
+
# that allows the end-user to organize the table by that column.
|
78
|
+
#
|
79
|
+
# ==== Signatures
|
80
|
+
#
|
81
|
+
# # Create a header that sorts a named column
|
82
|
+
# index_th(:title, sort:true)
|
83
|
+
#
|
84
|
+
# # Create a header that sorts a column, with custom label
|
85
|
+
# index_th("Strange Title", sort: :title)
|
86
|
+
#
|
87
|
+
# # Create a header that can't be sorted
|
88
|
+
# index_th("Strange Title", sort:false)
|
89
|
+
def index_th(field_or_label, sort:true)
|
90
|
+
|
91
|
+
case field_or_label
|
92
|
+
when :id
|
93
|
+
display_label = "ID"
|
94
|
+
when Symbol
|
95
|
+
display_label = field_or_label.to_s.humanize.titleize
|
96
|
+
else
|
97
|
+
display_label = field_or_label
|
98
|
+
end
|
99
|
+
|
100
|
+
if sort.is_a?(Symbol)
|
101
|
+
return content_tag(:th, sort_link(@search, sort, display_label), class:"index-th")
|
102
|
+
end
|
103
|
+
|
104
|
+
if sort.eql?(true) && field_or_label.is_a?(Symbol)
|
105
|
+
return content_tag(:th, sort_link(@search, field_or_label, display_label), class:"index-th")
|
106
|
+
end
|
107
|
+
|
108
|
+
return content_tag(:th, display_label, class:"index-th")
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
# Returns a `<td>` tag, suitable for use inside a `table.index-table`.
|
113
|
+
# If +method_or_content+ is a symbol, it will call that method on the
|
114
|
+
# given +resource+ to obtain the content of the `<td>`. Otherwise
|
115
|
+
# it expects +method_or_content+ or a passed block to provide suitable string.
|
116
|
+
#
|
117
|
+
# #### Special Options
|
118
|
+
#
|
119
|
+
# - `:image` - A URL to a square image to use in the <td>, floating to the
|
120
|
+
# left of the content. The image should be a square at least
|
121
|
+
# 14×14px in size.
|
122
|
+
#
|
123
|
+
# Other options are forwarded to `content_tag` for the `<td>`.
|
124
|
+
def index_td(resource, method_or_content, options = {}, &block)
|
125
|
+
|
126
|
+
options = method_or_content if block_given?
|
127
|
+
|
128
|
+
if block_given?
|
129
|
+
content = yield
|
130
|
+
elsif method_or_content.is_a?(Symbol)
|
131
|
+
content = resource.send(method_or_content)
|
132
|
+
else
|
133
|
+
content = method_or_content
|
134
|
+
end
|
135
|
+
|
136
|
+
options[:class] = "index-td #{options[:class]}"
|
137
|
+
|
138
|
+
if image = options.delete(:image)
|
139
|
+
image = image_tag(image, size:"18x18", alt:"")
|
140
|
+
end
|
141
|
+
|
142
|
+
return content_tag(:td, options) do
|
143
|
+
link_to("#{image}#{content}".html_safe, url_for(action:"edit", id:resource.id))
|
144
|
+
end
|
145
|
+
|
146
|
+
end
|
147
|
+
|
148
|
+
# Returns an `index_th` with label `"Actions"` that is not sortable.
|
149
|
+
def actions_th
|
150
|
+
index_th("Actions", sort:false)
|
151
|
+
end
|
152
|
+
|
153
|
+
# Returns a `<td>` tag, suitable for use inside a `table.index-table`.
|
154
|
+
# The tag contains buttons to edit, inspect, and delete the given +resource+.
|
155
|
+
def actions_td(resource)
|
156
|
+
|
157
|
+
links = []
|
158
|
+
|
159
|
+
if @managed_class.allows?(:edit)
|
160
|
+
links << link_to("Edit", url_for(action:"edit", id:resource.id), class:"button -small")
|
161
|
+
end
|
162
|
+
|
163
|
+
if @managed_class.allows?(:show)
|
164
|
+
links << link_to("Inspect", url_for(action:"show", id:resource.id), class:"button -small")
|
165
|
+
end
|
166
|
+
|
167
|
+
if @managed_class.allows?(:destroy)
|
168
|
+
links << link_to("Delete", url_for(action:"destroy", id:resource.id), class: "button -small", method: :delete, :'data-confirm' => deletion_warning(resource))
|
169
|
+
end
|
170
|
+
|
171
|
+
return content_tag(:td, links.join("").html_safe, class:"actions-td")
|
172
|
+
|
173
|
+
end
|
174
|
+
|
175
|
+
end
|