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