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,74 @@
|
|
1
|
+
Tolaria.configure do |config|
|
2
|
+
|
3
|
+
# The name of the company or group using this admin interface.
|
4
|
+
# Used in system navigation and HTML page titles.
|
5
|
+
config.company_name = "Company Name"
|
6
|
+
|
7
|
+
# Redirect the users to this route by default when logging in.
|
8
|
+
config.default_redirect = :admin_administrators
|
9
|
+
|
10
|
+
# Tolaria sends authentication emails. Set the value of the From header here.
|
11
|
+
config.from_address = "Rails <tolaria@example.org>"
|
12
|
+
|
13
|
+
# You can assign models to a category group them on the nav menu.
|
14
|
+
# Add/modify categories by changing the array below.
|
15
|
+
# Categories first in the array will be first on the menu.
|
16
|
+
config.menu_categories = ["Settings"]
|
17
|
+
|
18
|
+
# The cost factor for bcrypt.
|
19
|
+
# It is VERY DANGEROUS to set this below 10 for production.
|
20
|
+
# Use 1 in test mode to speed up your test suite.
|
21
|
+
config.bcrypt_cost = Rails.env.test?? 1 : 13
|
22
|
+
|
23
|
+
# The length of time that emailed passcodes should be valid.
|
24
|
+
# It is STRONGLY RECOMMENDED that you keep this under 30 minutes.
|
25
|
+
config.passcode_lifespan = 10.minutes
|
26
|
+
|
27
|
+
# The number of times an administrator can flunk their passcode
|
28
|
+
# challenge or request a token before Tolaria disables their account.
|
29
|
+
config.lockout_threshold = 10
|
30
|
+
|
31
|
+
# The length of time that an administrator’s account is disabled
|
32
|
+
# after they trip the lockout threshold.
|
33
|
+
config.lockout_duration = 1.hour
|
34
|
+
|
35
|
+
# An array of hashes used to construct HelpLinks
|
36
|
+
config.help_links = []
|
37
|
+
|
38
|
+
# Tolaria does not come bundled with a Markdown processing strategy.
|
39
|
+
# You must provide a string that names a Ruby constant that can process Markdown.
|
40
|
+
# The constant must respond to render(document), returning a string of HTML.
|
41
|
+
# For example: if you provide "MyMarkDownRenderer", Tolaria will
|
42
|
+
# call MyMarkdownRenderer.render(document).
|
43
|
+
config.markdown_renderer = nil
|
44
|
+
|
45
|
+
# Tolaria attempts to convert models to a pretty “display”
|
46
|
+
# string for presenting in forms and listings.
|
47
|
+
# The methods below are tried in order on models until one responds.
|
48
|
+
# Must be an array of symbols.
|
49
|
+
config.display_name_methods = %i[
|
50
|
+
admin_name
|
51
|
+
display_name
|
52
|
+
title
|
53
|
+
name
|
54
|
+
label
|
55
|
+
username
|
56
|
+
login
|
57
|
+
email
|
58
|
+
to_s
|
59
|
+
id
|
60
|
+
]
|
61
|
+
|
62
|
+
# The number of items on each page when paginating models.
|
63
|
+
config.page_size = 15
|
64
|
+
|
65
|
+
# Default permitted_params for all forms.
|
66
|
+
# End-developers probably shouldn’t change this.
|
67
|
+
config.permitted_params = %i[
|
68
|
+
_method
|
69
|
+
authenticity_token
|
70
|
+
id
|
71
|
+
utf8
|
72
|
+
]
|
73
|
+
|
74
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Tolaria
|
2
|
+
class Engine < ::Rails::Engine
|
3
|
+
|
4
|
+
# Add Tolaria’s assets to config.assets.precompile
|
5
|
+
initializer "tolaria.assets.precompile", group: :all do |app|
|
6
|
+
app.config.assets.precompile += %w[
|
7
|
+
admin/admin.css
|
8
|
+
admin/admin.js
|
9
|
+
admin/lib/no.js
|
10
|
+
]
|
11
|
+
end
|
12
|
+
|
13
|
+
# Reference ApplicationController and set Tolaria.safe_management
|
14
|
+
# to indicate that the application has finished booting
|
15
|
+
initializer "tolaria.safe_management", group: :all do |app|
|
16
|
+
app.config.after_initialize do
|
17
|
+
"ApplicationController".safe_constantize
|
18
|
+
Tolaria.safe_management = true
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,203 @@
|
|
1
|
+
module Tolaria
|
2
|
+
module FormBuildable
|
3
|
+
|
4
|
+
# Returns a `p.hint` used to explain a nearby form field containing
|
5
|
+
# the given +hint_text+.
|
6
|
+
def hint(hint_text)
|
7
|
+
content_tag(:p, content_tag(:span, hint_text.chomp), class:"hint")
|
8
|
+
end
|
9
|
+
|
10
|
+
# Creates a `<select>` list that can be filtered by typing word fragments.
|
11
|
+
# Uses the jQuery Chosen plugin internally to power the user interface.
|
12
|
+
# Parameters are the same as Rails’s `collection_select`.
|
13
|
+
#
|
14
|
+
# #### Special Options
|
15
|
+
#
|
16
|
+
# - `:multiple` - if set to `true`, the select allows more than one choice.
|
17
|
+
# The default is `false`.
|
18
|
+
def searchable_select(method, collection, value_method, text_method, options = {})
|
19
|
+
render(partial:"admin/shared/forms/searchable_select", locals: {
|
20
|
+
f: self,
|
21
|
+
method: method,
|
22
|
+
collection: collection,
|
23
|
+
value_method: value_method,
|
24
|
+
text_method: text_method,
|
25
|
+
options: options,
|
26
|
+
html_options: options,
|
27
|
+
})
|
28
|
+
end
|
29
|
+
|
30
|
+
# Creates a `searchable_select` that also shows a dynamic image preview of the selected record.
|
31
|
+
# Useful for previewing images or avatars chosen by name.
|
32
|
+
# +preview_url_method+ should be a method name to call on the associated model instance
|
33
|
+
# that returns a fully-qualified URL to the image preview.
|
34
|
+
def image_association_select(method, collection, value_method, text_method, preview_url_method, options = {})
|
35
|
+
render(partial:"admin/shared/forms/image_association_select", locals: {
|
36
|
+
f: self,
|
37
|
+
method: method,
|
38
|
+
collection: collection,
|
39
|
+
value_method: value_method,
|
40
|
+
text_method: text_method,
|
41
|
+
preview_url_method: preview_url_method,
|
42
|
+
options: options,
|
43
|
+
html_options: options,
|
44
|
+
})
|
45
|
+
end
|
46
|
+
|
47
|
+
# Renders a Markdown composer element for editing +method+,
|
48
|
+
# with fullscreen previewing and some text assistance tools.
|
49
|
+
# Requires that you set `Tolaria.config.markdown_renderer`.
|
50
|
+
# Options are forwarded to `text_area`.
|
51
|
+
def markdown_composer(method, options = {})
|
52
|
+
render(partial:"admin/shared/forms/markdown_composer", locals: {
|
53
|
+
f: self,
|
54
|
+
method: method,
|
55
|
+
options: options,
|
56
|
+
})
|
57
|
+
end
|
58
|
+
|
59
|
+
# Returns a file upload field with a more pleasant interface than browser
|
60
|
+
# file inputs. Changes messaging if the +method+ already exists.
|
61
|
+
# Options are forwarded to the hidden `file_field`.
|
62
|
+
def attachment_field(method, options = {})
|
63
|
+
render(partial:"admin/shared/forms/attachment_field", locals: {
|
64
|
+
f: self,
|
65
|
+
method: method,
|
66
|
+
options: options,
|
67
|
+
})
|
68
|
+
end
|
69
|
+
|
70
|
+
# Returns an image upload field with a more pleasant interface than browser
|
71
|
+
# file inputs. Changes messaging if the +method+ already exists.
|
72
|
+
#
|
73
|
+
# #### Special Options
|
74
|
+
#
|
75
|
+
# - `:preview_url` If the file already exists, provide a URL to a 42×42px
|
76
|
+
# version of the image, and it will be displayed to the user in a preview
|
77
|
+
# box to better communicate which file they are replacing.
|
78
|
+
#
|
79
|
+
# Other options are forwarded to the hidden `file_field`.
|
80
|
+
def image_field(method, options = {})
|
81
|
+
render(partial:"admin/shared/forms/image_field", locals: {
|
82
|
+
f: self,
|
83
|
+
method: method,
|
84
|
+
options: options,
|
85
|
+
preview_url: options[:preview_url]
|
86
|
+
})
|
87
|
+
end
|
88
|
+
|
89
|
+
# Returns a text field that allows the user to input a date and time.
|
90
|
+
# Automatically validates itself and recovers to a template if blanked out.
|
91
|
+
# This field uses moment.js to parse the date and set the values on a
|
92
|
+
# set of hidden Rails `datetime_select` fields.
|
93
|
+
# Options are forwarded to the hidden `datetime_select` group.
|
94
|
+
def timestamp_field(method, options = {})
|
95
|
+
render(partial:"admin/shared/forms/timestamp_field", locals: {
|
96
|
+
f: self,
|
97
|
+
method: method,
|
98
|
+
options: options,
|
99
|
+
})
|
100
|
+
end
|
101
|
+
|
102
|
+
# Returns a text field that parameterizes its input as users type
|
103
|
+
# and renders it into the given preview template. Useful for
|
104
|
+
# demonstrating the value of a URL or other sluggified text.
|
105
|
+
#
|
106
|
+
# #### Special Options
|
107
|
+
#
|
108
|
+
# - `:pattern` - Should be a string that includes an asterisk (`*`)
|
109
|
+
# character. As the user types, the asterisk will be replaced with
|
110
|
+
# a parameterized version of the text in the text box and shown
|
111
|
+
# in a preview area below the field.
|
112
|
+
# The default is `"/blog-example/*"`.
|
113
|
+
#
|
114
|
+
# Other options are forwarded to `text_field`.
|
115
|
+
def slug_field(method, options = {})
|
116
|
+
pattern = options.delete(:pattern)
|
117
|
+
preview_value = self.object.send(method).try(:parameterize).presence || "*"
|
118
|
+
render(partial:"admin/shared/forms/slug_field", locals: {
|
119
|
+
f: self,
|
120
|
+
method: method,
|
121
|
+
options: options,
|
122
|
+
preview_value: preview_value,
|
123
|
+
pattern: (pattern || "/blog-example/*")
|
124
|
+
})
|
125
|
+
end
|
126
|
+
|
127
|
+
# Returns a text field that expects to be given a 3 or 6-digit
|
128
|
+
# hexadecimal color value. A preview block near the field
|
129
|
+
# demonstrates the provided color to the user.
|
130
|
+
# Options are forwarded to `text_field`.
|
131
|
+
def swatch_field(method, options = {})
|
132
|
+
render(partial:"admin/shared/forms/swatch_field", locals: {
|
133
|
+
f: self,
|
134
|
+
method: method,
|
135
|
+
options: options,
|
136
|
+
})
|
137
|
+
end
|
138
|
+
|
139
|
+
# Opens an ERB block for UI to manage a `has_many` + `accepts_nested_attributes_for`
|
140
|
+
# association in the current form. The block will look similar to this:
|
141
|
+
#
|
142
|
+
# <%= f.has_many :footnotes do |ff| %>
|
143
|
+
# <%= ff.has_many_header allow_destroy:true %>
|
144
|
+
# <% # Your nested model fields for footnote here %>
|
145
|
+
# <% end %>
|
146
|
+
#
|
147
|
+
# You must use `f.has_many_header` inside the block to create headers.
|
148
|
+
#
|
149
|
+
# If you need to pass an ordered collection or otherwise not allow automatically
|
150
|
+
# determining the association objects from the +association+ symbol you can
|
151
|
+
# pass the collection manually as +association_objects+.
|
152
|
+
#
|
153
|
+
# If +allow_create+ is `false` then the button to append a new model
|
154
|
+
# instance will be disabled. The default is `true`.
|
155
|
+
def has_many(association, association_objects = nil, allow_create:true, &block)
|
156
|
+
|
157
|
+
new_object = self.object.send(association).klass.new
|
158
|
+
|
159
|
+
view_template = self.fields_for(association, new_object, child_index:new_object.object_id) do |builder|
|
160
|
+
yield(builder)
|
161
|
+
end
|
162
|
+
|
163
|
+
existing_fields = self.fields_for(association, association_objects) do |builder|
|
164
|
+
yield(builder)
|
165
|
+
end
|
166
|
+
|
167
|
+
render(partial:"admin/shared/forms/has_many", locals: {
|
168
|
+
association: association,
|
169
|
+
button_label: association.to_s.humanize.singularize.titleize,
|
170
|
+
new_object: new_object,
|
171
|
+
existing_fields: existing_fields,
|
172
|
+
allow_create: allow_create,
|
173
|
+
f: self,
|
174
|
+
data: {
|
175
|
+
template: view_template.tr("\n"," "),
|
176
|
+
id: new_object.object_id,
|
177
|
+
}
|
178
|
+
})
|
179
|
+
|
180
|
+
end
|
181
|
+
|
182
|
+
# Creates a header suitable for use inside `has_many` for separating
|
183
|
+
# form elements. If +allow_destroy+ is `true`, controls will be exposed that allow
|
184
|
+
# removing nested instances of the model. The default is `false` to match Rails’.
|
185
|
+
def has_many_header(allow_destroy:false)
|
186
|
+
render(partial:"admin/shared/forms/has_many_header", locals: {
|
187
|
+
allow_destroy: allow_destroy,
|
188
|
+
f: self,
|
189
|
+
})
|
190
|
+
end
|
191
|
+
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
class Admin::FormBuilder < ActionView::Helpers::FormBuilder
|
196
|
+
include Tolaria::FormBuildable
|
197
|
+
delegate :content_tag, :tag, :render, to: :@template
|
198
|
+
end
|
199
|
+
|
200
|
+
class Ransack::Helpers::FormBuilder
|
201
|
+
include Tolaria::FormBuildable
|
202
|
+
delegate :content_tag, :tag, :render, to: :@template
|
203
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module Tolaria
|
2
|
+
|
3
|
+
@help_links = []
|
4
|
+
|
5
|
+
def self.initialize_help_links!
|
6
|
+
@help_links = []
|
7
|
+
self.config.help_links.each do |hashy|
|
8
|
+
@help_links << Tolaria::HelpLink.new(**hashy)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.help_links
|
13
|
+
@help_links ||= []
|
14
|
+
end
|
15
|
+
|
16
|
+
class HelpLink
|
17
|
+
|
18
|
+
# The title of the link
|
19
|
+
attr_reader :title
|
20
|
+
# Part part of the link at `/admin/help/:slug` when rendering a Markdown file
|
21
|
+
attr_reader :slug
|
22
|
+
# The file path to the Markdown file
|
23
|
+
attr_reader :markdown_file
|
24
|
+
# The path to link to when not rendering a Markdown file
|
25
|
+
attr_reader :link_to
|
26
|
+
|
27
|
+
# Create a new HelpLink with the passed settings.
|
28
|
+
# You must provide +title+, the title of the link.
|
29
|
+
# To configure automatic rendering of a Markdown file, provide
|
30
|
+
# a string +slug+ and the path to a +markdown_file+.
|
31
|
+
# A route to view the file will be constructed for you at `/admin/help/:slug`.
|
32
|
+
# To link to an arbirary path or URI, provide it as +link_to+.
|
33
|
+
def initialize(title:, slug:nil, markdown_file:nil, link_to:nil)
|
34
|
+
@title = title.to_s.freeze
|
35
|
+
@slug = slug.to_s.freeze
|
36
|
+
@markdown_file = markdown_file.to_s.freeze
|
37
|
+
@link_to = link_to.to_s.freeze
|
38
|
+
validate!
|
39
|
+
end
|
40
|
+
|
41
|
+
# True if this HelpLink is a link to an arbirary path
|
42
|
+
def link_type?
|
43
|
+
link_to.present?
|
44
|
+
end
|
45
|
+
|
46
|
+
# True if this HelpLink is a Markdown file
|
47
|
+
def markdown_type?
|
48
|
+
markdown_file.present?
|
49
|
+
end
|
50
|
+
|
51
|
+
# Quack like an ActiveRecord::Base model
|
52
|
+
def to_param
|
53
|
+
slug
|
54
|
+
end
|
55
|
+
|
56
|
+
# Raises RuntimeError if this HelpLink is incorrectly configured
|
57
|
+
def validate!
|
58
|
+
|
59
|
+
if title.blank?
|
60
|
+
raise RuntimeError, "HelpLinks must provide a string title"
|
61
|
+
end
|
62
|
+
|
63
|
+
file_configured = (slug.present? && markdown_file.present?)
|
64
|
+
link_configured = link_to.present?
|
65
|
+
|
66
|
+
unless file_configured || link_configured
|
67
|
+
raise RuntimeError, "Incomplete HelpLink config. You must provide link_to, or both slug and markdown_file."
|
68
|
+
end
|
69
|
+
|
70
|
+
if file_configured && link_configured
|
71
|
+
raise RuntimeError, "Ambiguous HelpLink config. You must provide link_to, or both slug and markdown_file, but not all three."
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Tolaria
|
2
|
+
|
3
|
+
# Using this method, you can attempt to get a pretty “display”
|
4
|
+
# string for presenting the passed +resource+ as a label.
|
5
|
+
def self.display_name(resource)
|
6
|
+
Tolaria.config.display_name_methods.each do |method_name|
|
7
|
+
if resource.respond_to?(method_name)
|
8
|
+
return resource.send(method_name).to_s.truncate(40, omission:"…")
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Tolaria
|
2
|
+
|
3
|
+
@safe_mangagment = false
|
4
|
+
@managed_classes = []
|
5
|
+
|
6
|
+
# True if the application has actually booted
|
7
|
+
# and Tolaria is safe to start referencing models
|
8
|
+
def self.safe_management
|
9
|
+
@safe_mangagment
|
10
|
+
end
|
11
|
+
|
12
|
+
# Set the value of Tolaria.safe_management. +bool+ should be truthy.
|
13
|
+
# Don't call this method directly.
|
14
|
+
def self.safe_management=(bool)
|
15
|
+
@safe_mangagment = !!bool
|
16
|
+
end
|
17
|
+
|
18
|
+
# Tolaria keeps a list of all managed classes and the controllers
|
19
|
+
# for those classes internally so that other parts of the system
|
20
|
+
# can iterate over them. Return the list.
|
21
|
+
def self.managed_classes
|
22
|
+
@managed_classes
|
23
|
+
end
|
24
|
+
|
25
|
+
# Internal factory for adding managed classes. Developers should
|
26
|
+
# use ActiveRecord::Base#manage_with_tolaria.
|
27
|
+
def self.manage(klass, options = {})
|
28
|
+
|
29
|
+
# If we already have a class of this name, discard it
|
30
|
+
discard_managed_class(klass)
|
31
|
+
|
32
|
+
# Wrap the Rails model inside a Tolaria::ManagedClass
|
33
|
+
managed_klass = Tolaria::ManagedClass.create(klass, options)
|
34
|
+
|
35
|
+
# Add class to the internal tracker
|
36
|
+
@managed_classes.push(managed_klass)
|
37
|
+
|
38
|
+
# Check if there is already a correctly named controller because
|
39
|
+
# this means the end-developer made one and we don't want to unseat it.
|
40
|
+
# Otherwise create a controller for the model to use in the admin namespace.
|
41
|
+
unless "Admin::#{managed_klass.controller_name}".safe_constantize
|
42
|
+
managed_controller = Class.new(Tolaria::ResourceController)
|
43
|
+
::Admin.const_set(managed_klass.controller_name, managed_controller)
|
44
|
+
end
|
45
|
+
|
46
|
+
return managed_klass
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
# Discard a managed class instance for the given ActiveRecord::Base
|
51
|
+
def self.discard_managed_class(klass)
|
52
|
+
@managed_classes.delete_if do |managed_class|
|
53
|
+
klass.to_s == managed_class.klass.to_s
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|