trestle 0.8.4 → 0.8.11
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 +5 -5
- data/.gitignore +4 -0
- data/.travis.yml +14 -1
- data/Gemfile +6 -0
- data/README.md +15 -9
- data/app/assets/javascripts/trestle/admin.js +11 -10
- data/app/assets/javascripts/trestle/components/_confirmation.js +40 -0
- data/app/assets/javascripts/trestle/components/_datepicker.js +37 -0
- data/app/assets/javascripts/trestle/components/_dialog.js +136 -0
- data/app/assets/javascripts/trestle/{_errors.js → components/_errors.js} +2 -2
- data/app/assets/javascripts/trestle/components/_form.js +75 -0
- data/app/assets/javascripts/trestle/{_gallery.js → components/_gallery.js} +3 -3
- data/app/assets/javascripts/trestle/{_select.js → components/_select.js} +2 -2
- data/app/assets/javascripts/trestle/components/_sidebar.js +77 -0
- data/app/assets/javascripts/trestle/{_table.js → components/_table.js} +1 -1
- data/app/assets/javascripts/trestle/components/_tabs.js +25 -0
- data/app/assets/javascripts/trestle/components/_tooltips.js +19 -0
- data/app/assets/javascripts/trestle/core/_contexts.js +13 -0
- data/app/assets/javascripts/trestle/core/_cookies.js +24 -0
- data/app/assets/javascripts/trestle/core/_events.js +39 -0
- data/app/assets/javascripts/trestle/core/_l10n.js +23 -0
- data/app/assets/javascripts/trestle/core/_visit.js +10 -0
- data/app/assets/stylesheets/trestle/components/_alerts.scss +28 -0
- data/app/assets/stylesheets/trestle/components/_avatar.scss +23 -1
- data/app/assets/stylesheets/trestle/components/_breadcrumbs.scss +12 -0
- data/app/assets/stylesheets/trestle/components/_buttons.scss +111 -1
- data/app/assets/stylesheets/trestle/components/_content.scss +53 -21
- data/app/assets/stylesheets/trestle/components/_datepicker.scss +28 -0
- data/app/assets/stylesheets/trestle/components/_fields.scss +17 -0
- data/app/assets/stylesheets/trestle/components/_input-group.scss +26 -1
- data/app/assets/stylesheets/trestle/components/_modal.scss +108 -0
- data/app/assets/stylesheets/trestle/components/_navigation.scss +104 -14
- data/app/assets/stylesheets/trestle/components/_pagination.scss +3 -3
- data/app/assets/stylesheets/trestle/components/_scopes.scss +11 -2
- data/app/assets/stylesheets/trestle/components/_sidebar.scss +3 -2
- data/app/assets/stylesheets/trestle/components/_table.scss +34 -10
- data/app/assets/stylesheets/trestle/components/_tags.scss +9 -0
- data/app/assets/stylesheets/trestle/components/_timestamp.scss +4 -1
- data/app/assets/stylesheets/trestle/components/_toolbars.scss +55 -0
- data/app/assets/stylesheets/trestle/components/_wells.scss +9 -1
- data/app/assets/stylesheets/trestle/core/_defaults.scss +21 -6
- data/app/assets/stylesheets/trestle/core/_layout.scss +8 -0
- data/app/assets/stylesheets/trestle/core/_mixins.scss +11 -0
- data/app/assets/stylesheets/trestle/core/_typography.scss +39 -0
- data/app/controllers/concerns/trestle/controller/breadcrumbs.rb +21 -0
- data/app/controllers/concerns/trestle/controller/callbacks.rb +21 -0
- data/app/controllers/concerns/trestle/controller/dialog.rb +16 -0
- data/app/controllers/concerns/trestle/controller/helpers.rb +18 -0
- data/app/controllers/concerns/trestle/controller/layout.rb +16 -0
- data/app/controllers/concerns/trestle/controller/location.rb +15 -0
- data/app/controllers/trestle/application_controller.rb +6 -30
- data/app/helpers/trestle/avatar_helper.rb +9 -2
- data/app/helpers/trestle/flash_helper.rb +15 -0
- data/app/helpers/trestle/form_helper.rb +8 -5
- data/app/helpers/trestle/format_helper.rb +7 -3
- data/app/helpers/trestle/headings_helper.rb +27 -0
- data/app/helpers/trestle/hook_helper.rb +13 -4
- data/app/helpers/trestle/i18n_helper.rb +14 -0
- data/app/helpers/trestle/panel_helper.rb +24 -0
- data/app/helpers/trestle/tab_helper.rb +2 -2
- data/app/helpers/trestle/table_helper.rb +41 -2
- data/app/helpers/trestle/timestamp_helper.rb +49 -7
- data/app/helpers/trestle/toolbars_helper.rb +34 -0
- data/app/helpers/trestle/url_helper.rb +72 -8
- data/app/views/layouts/trestle/admin.html.erb +3 -5
- data/app/views/trestle/application/_dialog.html.erb +34 -0
- data/app/views/trestle/application/_header.html.erb +22 -20
- data/app/views/trestle/application/_layout.html.erb +1 -1
- data/app/views/trestle/application/_tabs.html.erb +8 -2
- data/app/views/trestle/{application → flash}/_alert.html.erb +7 -2
- data/app/views/trestle/flash/_debug.html.erb +8 -0
- data/app/views/trestle/flash/_flash.html.erb +7 -0
- data/app/views/trestle/resource/_scopes.html.erb +1 -1
- data/app/views/trestle/resource/edit.html.erb +8 -10
- data/app/views/trestle/resource/index.html.erb +16 -4
- data/app/views/trestle/resource/new.html.erb +6 -6
- data/app/views/trestle/resource/show.html.erb +8 -10
- data/app/views/trestle/shared/_sidebar.html.erb +10 -7
- data/app/views/trestle/shared/_title.html.erb +14 -0
- data/app/views/trestle/table/_table.html.erb +4 -6
- data/bower.json +1 -1
- data/config/locales/cs.rb +18 -0
- data/config/locales/cs.yml +95 -0
- data/config/locales/en.yml +65 -36
- data/config/locales/es-MX.yml +94 -0
- data/config/locales/es.yml +94 -0
- data/config/locales/fr.rb +18 -0
- data/config/locales/fr.yml +84 -0
- data/config/locales/lv.rb +18 -0
- data/config/locales/lv.yml +94 -0
- data/config/locales/nl.rb +18 -0
- data/config/locales/nl.yml +82 -0
- data/config/locales/pl.rb +18 -0
- data/config/locales/pl.yml +85 -0
- data/config/locales/pt-BR.rb +18 -0
- data/config/locales/pt-BR.yml +84 -0
- data/config/locales/zh-CN.rb +18 -0
- data/config/locales/zh-CN.yml +94 -0
- data/gemfiles/rails-4.2.gemfile +16 -0
- data/gemfiles/rails-5.0.gemfile +16 -0
- data/gemfiles/rails-5.1.gemfile +16 -0
- data/gemfiles/rails-5.2.gemfile +16 -0
- data/gemfiles/rails-edge.gemfile +17 -0
- data/lib/generators/trestle/install/templates/trestle.rb.erb +18 -2
- data/lib/generators/trestle/resource/templates/admin.rb.erb +2 -2
- data/lib/trestle/adapters/active_record_adapter.rb +2 -6
- data/lib/trestle/adapters/adapter.rb +40 -15
- data/lib/trestle/adapters/sequel_adapter.rb +2 -6
- data/lib/trestle/admin/builder.rb +42 -12
- data/lib/trestle/admin/controller.rb +3 -1
- data/lib/trestle/admin.rb +84 -3
- data/lib/trestle/breadcrumb.rb +16 -1
- data/lib/trestle/configurable.rb +6 -0
- data/lib/trestle/configuration.rb +28 -5
- data/lib/trestle/display.rb +1 -1
- data/lib/trestle/engine.rb +10 -4
- data/lib/trestle/form/automatic.rb +6 -3
- data/lib/trestle/form/builder.rb +5 -1
- data/lib/trestle/form/field.rb +1 -1
- data/lib/trestle/form/fields/date_picker.rb +2 -2
- data/lib/trestle/form/fields/form_control.rb +14 -4
- data/lib/trestle/form/fields/form_group.rb +14 -3
- data/lib/trestle/form/fields/select.rb +5 -1
- data/lib/trestle/form/fields/tag_select.rb +1 -1
- data/lib/trestle/form/renderer.rb +2 -2
- data/lib/trestle/form.rb +7 -3
- data/lib/trestle/hook.rb +27 -0
- data/lib/trestle/model_name.rb +64 -0
- data/lib/trestle/navigation/group.rb +16 -0
- data/lib/trestle/navigation/item.rb +11 -1
- data/lib/trestle/navigation.rb +24 -6
- data/lib/trestle/options.rb +7 -5
- data/lib/trestle/reloader.rb +1 -1
- data/lib/trestle/resource/adapter_methods.rb +62 -0
- data/lib/trestle/resource/builder.rb +43 -17
- data/lib/trestle/resource/collection.rb +68 -0
- data/lib/trestle/resource/controller.rb +70 -33
- data/lib/trestle/resource.rb +97 -105
- data/lib/trestle/scope.rb +13 -3
- data/lib/trestle/tab.rb +4 -0
- data/lib/trestle/table/actions_column.rb +41 -31
- data/lib/trestle/table/automatic.rb +1 -2
- data/lib/trestle/table/builder.rb +2 -2
- data/lib/trestle/table/column.rb +40 -9
- data/lib/trestle/table/row.rb +18 -2
- data/lib/trestle/table.rb +18 -2
- data/lib/trestle/toolbar/builder.rb +52 -0
- data/lib/trestle/toolbar/context.rb +39 -0
- data/lib/trestle/toolbar.rb +43 -0
- data/lib/trestle/version.rb +1 -1
- data/lib/trestle.rb +9 -4
- data/trestle.gemspec +5 -3
- data/vendor/assets/bower_components/trestle/select2/dist/js/select2.full.js +90 -69
- data/vendor/assets/javascripts/trestle/flatpickr.js.erb +2 -0
- data/vendor/assets/stylesheets/trestle/magnific-popup.scss +13 -1
- metadata +99 -22
- data/app/assets/javascripts/trestle/_confirmation.js +0 -23
- data/app/assets/javascripts/trestle/_datepicker.js +0 -22
- data/app/assets/javascripts/trestle/_form.js +0 -6
- data/app/assets/javascripts/trestle/_sidebar.js +0 -52
- data/app/assets/javascripts/trestle/_tabs.js +0 -13
- data/app/assets/javascripts/trestle/_tooltips.js +0 -3
- data/app/helpers/trestle/title_helper.rb +0 -26
- data/app/views/trestle/application/_flash.html.erb +0 -11
|
@@ -1,34 +1,10 @@
|
|
|
1
1
|
class Trestle::ApplicationController < ActionController::Base
|
|
2
2
|
protect_from_forgery
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
# Global callbacks
|
|
12
|
-
Trestle.config.before_actions.each do |action|
|
|
13
|
-
before_action(action.options, &action.block)
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
Trestle.config.after_actions.each do |action|
|
|
17
|
-
after_action(action.options, &action.block)
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
Trestle.config.around_actions.each do |action|
|
|
21
|
-
around_action(action.options, &action.block)
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
protected
|
|
25
|
-
def breadcrumbs
|
|
26
|
-
@breadcrumbs ||= Trestle::Breadcrumb::Trail.new(Trestle.config.root_breadcrumbs)
|
|
27
|
-
end
|
|
28
|
-
helper_method :breadcrumbs
|
|
29
|
-
|
|
30
|
-
def breadcrumb(label, path=nil)
|
|
31
|
-
breadcrumbs.append(label, path)
|
|
32
|
-
end
|
|
33
|
-
helper_method :breadcrumb
|
|
4
|
+
include Trestle::Controller::Breadcrumbs
|
|
5
|
+
include Trestle::Controller::Callbacks
|
|
6
|
+
include Trestle::Controller::Dialog
|
|
7
|
+
include Trestle::Controller::Helpers
|
|
8
|
+
include Trestle::Controller::Layout
|
|
9
|
+
include Trestle::Controller::Location
|
|
34
10
|
end
|
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
module Trestle
|
|
2
2
|
module AvatarHelper
|
|
3
|
-
def avatar(
|
|
4
|
-
|
|
3
|
+
def avatar(options={})
|
|
4
|
+
fallback = options.delete(:fallback) if options[:fallback]
|
|
5
|
+
|
|
6
|
+
content_tag(:div, options.reverse_merge(class: "avatar")) do
|
|
7
|
+
concat content_tag(:span, fallback, class: "avatar-fallback") if fallback
|
|
8
|
+
concat yield if block_given?
|
|
9
|
+
end
|
|
5
10
|
end
|
|
6
11
|
|
|
7
12
|
def gravatar(email, options={})
|
|
13
|
+
options = { d: "mm" }.merge(options)
|
|
14
|
+
|
|
8
15
|
url = "https://www.gravatar.com/avatar/#{Digest::MD5.hexdigest(email.to_s.downcase)}.png"
|
|
9
16
|
url << "?#{options.to_query}" if options.any?
|
|
10
17
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module Trestle
|
|
2
|
+
module FlashHelper
|
|
3
|
+
def normalize_flash_alert(flash)
|
|
4
|
+
flash.is_a?(Hash) ? flash.with_indifferent_access : { message: flash }
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def debug_form_errors?
|
|
8
|
+
Trestle.config.debug_form_errors && instance_has_errors?
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def instance_has_errors?
|
|
12
|
+
instance.errors.any? rescue false
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -2,7 +2,10 @@ module Trestle
|
|
|
2
2
|
module FormHelper
|
|
3
3
|
def trestle_form_for(instance, options={}, &block)
|
|
4
4
|
options[:builder] ||= Form::Builder
|
|
5
|
-
options[:as] ||= admin.
|
|
5
|
+
options[:as] ||= admin.parameter_name
|
|
6
|
+
|
|
7
|
+
options[:data] ||= {}
|
|
8
|
+
options[:data].reverse_merge!(remote: true, type: :html, behavior: "trestle-form", turbolinks: false)
|
|
6
9
|
|
|
7
10
|
form_for(instance, options) do |f|
|
|
8
11
|
with_form(f) { yield f }
|
|
@@ -20,12 +23,12 @@ module Trestle
|
|
|
20
23
|
@_trestle_form
|
|
21
24
|
end
|
|
22
25
|
|
|
23
|
-
def toolbar(name, &block)
|
|
24
|
-
content_for(:"#{name}_toolbar", &block)
|
|
25
|
-
end
|
|
26
|
-
|
|
27
26
|
def sidebar(&block)
|
|
28
27
|
content_for(:sidebar, &block)
|
|
29
28
|
end
|
|
29
|
+
|
|
30
|
+
def render_sidebar_as_tab?
|
|
31
|
+
dialog_request? && content_for?(:sidebar)
|
|
32
|
+
end
|
|
30
33
|
end
|
|
31
34
|
end
|
|
@@ -13,7 +13,7 @@ module Trestle
|
|
|
13
13
|
when :currency
|
|
14
14
|
number_to_currency(value)
|
|
15
15
|
when :tags
|
|
16
|
-
safe_join(value.map { |tag| content_tag(:span, tag, class: "tag") })
|
|
16
|
+
safe_join(Array(value).map { |tag| content_tag(:span, tag, class: "tag") })
|
|
17
17
|
else
|
|
18
18
|
value
|
|
19
19
|
end
|
|
@@ -30,8 +30,12 @@ module Trestle
|
|
|
30
30
|
when TrueClass, FalseClass
|
|
31
31
|
status_tag(icon("fa fa-check"), :success) if value
|
|
32
32
|
when NilClass
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
blank = options.key?(:blank) ? options[:blank] : I18n.t("admin.format.blank")
|
|
34
|
+
if blank.respond_to?(:call)
|
|
35
|
+
instance_exec(&blank)
|
|
36
|
+
else
|
|
37
|
+
content_tag(:span, blank, class: "blank")
|
|
38
|
+
end
|
|
35
39
|
when String
|
|
36
40
|
if value.html_safe? || options[:truncate] == false
|
|
37
41
|
value
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module Trestle
|
|
2
|
+
module HeadingsHelper
|
|
3
|
+
def h1(text, options={})
|
|
4
|
+
content_tag(:h1, text, options)
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def h2(text, options={})
|
|
8
|
+
content_tag(:h2, text, options)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def h3(text, options={})
|
|
12
|
+
content_tag(:h3, text, options)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def h4(text, options={})
|
|
16
|
+
content_tag(:h4, text, options)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def h5(text, options={})
|
|
20
|
+
content_tag(:h5, text, options)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def h6(text, options={})
|
|
24
|
+
content_tag(:h6, text, options)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -1,13 +1,22 @@
|
|
|
1
1
|
module Trestle
|
|
2
2
|
module HookHelper
|
|
3
3
|
def hook(name)
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
if hook?(name)
|
|
5
|
+
safe_join(hooks(name).map { |hook|
|
|
6
|
+
hook.evaluate(self)
|
|
7
|
+
}, "\n")
|
|
8
|
+
elsif block_given?
|
|
9
|
+
yield
|
|
10
|
+
end
|
|
7
11
|
end
|
|
8
12
|
|
|
9
13
|
def hook?(name)
|
|
10
|
-
Trestle.config.hooks
|
|
14
|
+
Trestle.config.hooks.key?(name.to_s) && hooks(name).any?
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
protected
|
|
18
|
+
def hooks(name)
|
|
19
|
+
Trestle.config.hooks[name.to_s].select { |h| h.visible?(self) }
|
|
11
20
|
end
|
|
12
21
|
end
|
|
13
22
|
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
module Trestle
|
|
2
|
+
module I18nHelper
|
|
3
|
+
def i18n_fallbacks(locale=I18n.locale)
|
|
4
|
+
if I18n.respond_to?(:fallbacks)
|
|
5
|
+
I18n.fallbacks[locale]
|
|
6
|
+
elsif locale.to_s.include?("-")
|
|
7
|
+
fallback = locale.to_s.split("-").first
|
|
8
|
+
[locale, fallback]
|
|
9
|
+
else
|
|
10
|
+
[locale]
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module Trestle
|
|
2
|
+
module PanelHelper
|
|
3
|
+
def panel(options={}, &block)
|
|
4
|
+
html_class = options.fetch(:class) { "panel-default" }
|
|
5
|
+
|
|
6
|
+
content_tag(:div, class: ["panel", html_class]) do
|
|
7
|
+
if options[:title]
|
|
8
|
+
concat content_tag(:div, options[:title], class: "panel-heading")
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
concat content_tag(:div, class: "panel-body", &block)
|
|
12
|
+
|
|
13
|
+
if options[:footer]
|
|
14
|
+
concat content_tag(:div, options[:footer], class: "panel-footer")
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def well(options={}, &block)
|
|
20
|
+
html_class = ["well", options[:class]].compact
|
|
21
|
+
content_tag(:div, options.merge(class: html_class), &block)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -5,9 +5,9 @@ module Trestle
|
|
|
5
5
|
end
|
|
6
6
|
|
|
7
7
|
def tab(name, options={})
|
|
8
|
-
tabs[name] = Tab.new(name, options)
|
|
8
|
+
tabs[name] = tab = Tab.new(name, options)
|
|
9
9
|
|
|
10
|
-
content_tag(:div, id:
|
|
10
|
+
content_tag(:div, id: tab.id(("modal" if dialog_request?)), class: ["tab-pane", ('active' if name == tabs.keys.first)], role: "tabpanel") do
|
|
11
11
|
if block_given?
|
|
12
12
|
yield
|
|
13
13
|
elsif options[:partial]
|
|
@@ -1,7 +1,46 @@
|
|
|
1
1
|
module Trestle
|
|
2
2
|
module TableHelper
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
# Renders an existing named table or builds and renders a custom table if a block is provided.
|
|
4
|
+
#
|
|
5
|
+
# name - The (optional) name of the table to render (as a Symbol), or the actual Trestle::Table instance itself.
|
|
6
|
+
# options - Hash of options that will be passed to the table builder (default: {}):
|
|
7
|
+
# :collection - The collection that should be rendered within the table. It should be an
|
|
8
|
+
# Array-like object, but will most likely be an ActiveRecord scope. It can
|
|
9
|
+
# also be a callable object (i.e. a Proc) in which case the result of calling
|
|
10
|
+
# the block will be used as the collection.
|
|
11
|
+
# See Trestle::Table::Builder for additional options.
|
|
12
|
+
# block - An optional block that is passed to Trestle::Table::Builder to define a custom table.
|
|
13
|
+
# One of either the name or block must be provided, but not both.
|
|
14
|
+
#
|
|
15
|
+
# Examples
|
|
16
|
+
#
|
|
17
|
+
# <%= table collection: -> { Account.all }, admin: :accounts do %>
|
|
18
|
+
# <% column(:name) %>
|
|
19
|
+
# <% column(:balance) { |account| account.balance.format } %>
|
|
20
|
+
# <% column(:created_at, align: :center)
|
|
21
|
+
# <% end %>
|
|
22
|
+
#
|
|
23
|
+
# <%= table :accounts %>
|
|
24
|
+
#
|
|
25
|
+
# Returns the HTML representation of the table as a HTML-safe String.
|
|
26
|
+
def table(name=nil, options={}, &block)
|
|
27
|
+
if block_given?
|
|
28
|
+
if name.is_a?(Hash)
|
|
29
|
+
options = name
|
|
30
|
+
else
|
|
31
|
+
collection = name
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
table = Table::Builder.build(options, &block)
|
|
35
|
+
elsif name.is_a?(Trestle::Table)
|
|
36
|
+
table = name
|
|
37
|
+
else
|
|
38
|
+
table = admin.tables.fetch(name) { raise ArgumentError, "Unable to find table named #{name.inspect}" }
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
collection ||= options[:collection] || table.options[:collection]
|
|
42
|
+
collection = collection.call if collection.respond_to?(:call)
|
|
43
|
+
|
|
5
44
|
render "trestle/table/table", table: table, collection: collection
|
|
6
45
|
end
|
|
7
46
|
end
|
|
@@ -1,17 +1,59 @@
|
|
|
1
1
|
module Trestle
|
|
2
2
|
module TimestampHelper
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
# Renders a Time object as a formatted timestamp (using a <time> tag)
|
|
4
|
+
#
|
|
5
|
+
# time - The Time object to format.
|
|
6
|
+
# options - Hash of options (default: {}):
|
|
7
|
+
# :class - Additional HTML classes to add to the <time> tag.
|
|
8
|
+
# :precision - Time precision, either :minutes or :seconds (default: :minutes).
|
|
9
|
+
# :date_format - I18n date format to use for the date (default: :trestle_date).
|
|
10
|
+
# :time_format - I18n time format to use for the time (default: :trestle_time).
|
|
11
|
+
#
|
|
12
|
+
# Examples
|
|
13
|
+
#
|
|
14
|
+
# <%= timestamp(article.created_at) %>
|
|
15
|
+
#
|
|
16
|
+
# <%= timestamp(Time.current, class: "timestamp-inline", precision: :seconds) %>
|
|
17
|
+
#
|
|
18
|
+
# Returns the HTML representation of the given Time.
|
|
19
|
+
def timestamp(time, options={})
|
|
20
|
+
return unless time
|
|
21
|
+
|
|
22
|
+
classes = ["timestamp", options[:class]].compact
|
|
23
|
+
precision = options.fetch(:precision) { Trestle.config.timestamp_precision }
|
|
24
|
+
date_format = options.fetch(:date_format) { :trestle_date }
|
|
25
|
+
time_format = options.fetch(:time_format) { precision == :seconds ? :trestle_time_with_seconds : :trestle_time }
|
|
26
|
+
|
|
27
|
+
time_tag(time, class: classes) do
|
|
5
28
|
safe_join([
|
|
6
|
-
l(time, format:
|
|
7
|
-
content_tag(:small, l(time, format:
|
|
29
|
+
l(time, format: date_format, default: proc { |date| "#{date.day.ordinalize} %b %Y" }),
|
|
30
|
+
content_tag(:small, l(time, format: time_format, default: "%l:%M:%S %p"))
|
|
8
31
|
], "\n")
|
|
9
32
|
end
|
|
10
33
|
end
|
|
11
34
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
35
|
+
# Renders a Date object as formatted datestamp (using a <time> tag)
|
|
36
|
+
#
|
|
37
|
+
# date - The Date object to format.
|
|
38
|
+
# options - Hash of options (default: {}):
|
|
39
|
+
# :class - Additional HTML classes to add to the <time> tag.
|
|
40
|
+
# :format - I18n date format to use (default: :trestle_calendar).
|
|
41
|
+
#
|
|
42
|
+
# Examples
|
|
43
|
+
#
|
|
44
|
+
# <%= datestamp(Date.current) %>
|
|
45
|
+
#
|
|
46
|
+
# <%= datestamp(article.created_at, format: :trestle_date, class: "custom-datestamp") %>
|
|
47
|
+
#
|
|
48
|
+
# Returns the HTML representation of the given Date.
|
|
49
|
+
def datestamp(date, options={})
|
|
50
|
+
return unless date
|
|
51
|
+
|
|
52
|
+
classes = ["datestamp", options[:class]].compact
|
|
53
|
+
format = options.fetch(:format) { :trestle_calendar}
|
|
54
|
+
|
|
55
|
+
time_tag(date, class: classes) do
|
|
56
|
+
l(date, format: format, default: "%-m/%-d/%Y")
|
|
15
57
|
end
|
|
16
58
|
end
|
|
17
59
|
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
module Trestle
|
|
2
|
+
module ToolbarsHelper
|
|
3
|
+
def toolbar(name, &block)
|
|
4
|
+
toolbar = (toolbars[name.to_s] ||= Toolbar.new)
|
|
5
|
+
toolbar.prepend(&block) if block_given?
|
|
6
|
+
toolbar
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def toolbars
|
|
10
|
+
@_toolbars ||= {}
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def render_toolbar(toolbar, *args)
|
|
14
|
+
result = toolbar.groups(self, *args).map do |items|
|
|
15
|
+
if items.many?
|
|
16
|
+
content_tag(:div, class: "btn-group", role: "group") do
|
|
17
|
+
safe_join(items, "\n")
|
|
18
|
+
end
|
|
19
|
+
else
|
|
20
|
+
items.first
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
safe_join(result, "\n")
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def deprecated_toolbar(name)
|
|
28
|
+
if content_for?(:"#{name}_toolbar")
|
|
29
|
+
ActiveSupport::Deprecation.warn("Using content_for(:#{name}_toolbar) is deprecated. Please use toolbar(:#{name}) instead.")
|
|
30
|
+
content_for(:"#{name}_toolbar")
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -1,25 +1,89 @@
|
|
|
1
1
|
module Trestle
|
|
2
2
|
module UrlHelper
|
|
3
|
-
|
|
3
|
+
DIALOG_ACTIONS = [:new, :show, :edit]
|
|
4
|
+
|
|
5
|
+
def admin_link_to(content, instance_or_url=nil, options={}, &block)
|
|
6
|
+
# Block given - ignore content parameter and capture content from block
|
|
4
7
|
if block_given?
|
|
5
|
-
|
|
8
|
+
instance_or_url, options = content, instance_or_url || {}
|
|
6
9
|
content = capture(&block)
|
|
7
10
|
end
|
|
8
11
|
|
|
9
|
-
if
|
|
10
|
-
|
|
12
|
+
if instance_or_url.is_a?(String)
|
|
13
|
+
# Treat string URL as regular link
|
|
14
|
+
link_to(content, instance_or_url, options)
|
|
11
15
|
else
|
|
12
|
-
|
|
16
|
+
# Normalize options if instance is not provided
|
|
17
|
+
if instance_or_url.is_a?(Hash)
|
|
18
|
+
instance, options = nil, instance_or_url
|
|
19
|
+
else
|
|
20
|
+
instance = instance_or_url
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Determine admin
|
|
24
|
+
if options.key?(:admin)
|
|
25
|
+
admin = Trestle.lookup(options.delete(:admin))
|
|
26
|
+
elsif instance
|
|
27
|
+
admin = admin_for(instance)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
admin ||= self.admin if respond_to?(:admin)
|
|
31
|
+
|
|
32
|
+
if admin
|
|
33
|
+
# Ensure admin has controller context
|
|
34
|
+
admin = admin.new(self) if admin.is_a?(Class)
|
|
35
|
+
|
|
36
|
+
# Generate path
|
|
37
|
+
action = options.delete(:action) || :show
|
|
38
|
+
params = options.delete(:params) || {}
|
|
39
|
+
|
|
40
|
+
if admin.respond_to?(:instance_path) && instance
|
|
41
|
+
path = admin.instance_path(instance, params.reverse_merge(action: action))
|
|
42
|
+
else
|
|
43
|
+
params[:id] ||= admin.to_param(instance) if instance
|
|
44
|
+
path = admin.path(action, params)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Determine link data options
|
|
48
|
+
if DIALOG_ACTIONS.include?(action) && admin.form.dialog?
|
|
49
|
+
options[:data] ||= {}
|
|
50
|
+
options[:data][:behavior] ||= "dialog"
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
link_to(content, path, options)
|
|
54
|
+
else
|
|
55
|
+
raise ActionController::UrlGenerationError, "An admin could not be inferred. Please specify an admin using the :admin option."
|
|
56
|
+
end
|
|
13
57
|
end
|
|
14
58
|
end
|
|
15
59
|
|
|
16
60
|
def admin_url_for(instance, options={})
|
|
17
|
-
admin = options.
|
|
18
|
-
admin
|
|
61
|
+
admin = Trestle.lookup(options.delete(:admin)) if options.key?(:admin)
|
|
62
|
+
admin ||= admin_for(instance)
|
|
63
|
+
return unless admin
|
|
64
|
+
|
|
65
|
+
# Ensure admin has controller context
|
|
66
|
+
admin = admin.new(self) if admin.is_a?(Class)
|
|
67
|
+
|
|
68
|
+
if admin.respond_to?(:instance_path)
|
|
69
|
+
admin.instance_path(instance, options)
|
|
70
|
+
else
|
|
71
|
+
admin.path(options[:action] || :show, id: admin.to_param(instance))
|
|
72
|
+
end
|
|
19
73
|
end
|
|
20
74
|
|
|
21
75
|
def admin_for(instance)
|
|
22
|
-
|
|
76
|
+
klass = instance.class
|
|
77
|
+
|
|
78
|
+
while klass
|
|
79
|
+
admin = Trestle.admins[klass.name.underscore.pluralize]
|
|
80
|
+
return admin if admin
|
|
81
|
+
|
|
82
|
+
klass = klass.superclass
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# No admin found
|
|
86
|
+
nil
|
|
23
87
|
end
|
|
24
88
|
end
|
|
25
89
|
end
|
|
@@ -26,9 +26,7 @@
|
|
|
26
26
|
Trestle.i18n['<%= key %>'] = "<%= escape_javascript(t(key, default: t(key, locale: :en))) %>";
|
|
27
27
|
<% end %>
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
flatpickr.localize(flatpickr.l10ns['<%= I18n.locale %>']);
|
|
31
|
-
}
|
|
29
|
+
Trestle.localize(<%= i18n_fallbacks.map { |l| "'#{l}'" }.join(", ").html_safe %>);
|
|
32
30
|
</script>
|
|
33
31
|
|
|
34
32
|
<%= hook :javascripts %>
|
|
@@ -38,14 +36,14 @@
|
|
|
38
36
|
<%= hook :head %>
|
|
39
37
|
</head>
|
|
40
38
|
|
|
41
|
-
<body
|
|
39
|
+
<body<%=raw " class=\"sidebar-#{cookies["trestle:sidebar"]}\"" if cookies["trestle:sidebar"] %>>
|
|
42
40
|
<div class="app-wrapper">
|
|
43
41
|
<%= render "trestle/shared/sidebar" %>
|
|
44
42
|
|
|
45
43
|
<div class="app-container">
|
|
46
44
|
<%= render "trestle/shared/header" %>
|
|
47
45
|
|
|
48
|
-
<main class="app-main">
|
|
46
|
+
<main class="app-main" data-context="<%= request.fullpath %>">
|
|
49
47
|
<%= yield %>
|
|
50
48
|
</main>
|
|
51
49
|
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<div class="modal-header">
|
|
2
|
+
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
|
3
|
+
<h4 class="modal-title"><%= content_for(:title) %></h4>
|
|
4
|
+
</div>
|
|
5
|
+
|
|
6
|
+
<div class="modal-flash">
|
|
7
|
+
<%= render "trestle/flash/flash" %>
|
|
8
|
+
</div>
|
|
9
|
+
|
|
10
|
+
<div class="modal-tabs">
|
|
11
|
+
<%= render "tabs" %>
|
|
12
|
+
</div>
|
|
13
|
+
|
|
14
|
+
<div class="modal-body">
|
|
15
|
+
<%= yield %>
|
|
16
|
+
|
|
17
|
+
<% if content_for?(:sidebar) %>
|
|
18
|
+
<div id="tab-sidebar" class="tab-pane" role="tabpanel">
|
|
19
|
+
<%= content_for(:sidebar) %>
|
|
20
|
+
</div>
|
|
21
|
+
<% end %>
|
|
22
|
+
</div>
|
|
23
|
+
|
|
24
|
+
<div class="modal-footer">
|
|
25
|
+
<div class="btn-toolbar secondary-toolbar">
|
|
26
|
+
<%= render_toolbar(toolbar(:secondary)) %>
|
|
27
|
+
<%= deprecated_toolbar(:secondary) %>
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
<div class="btn-toolbar primary-toolbar">
|
|
31
|
+
<%= render_toolbar(toolbar(:primary)) %>
|
|
32
|
+
<%= deprecated_toolbar(:primary) %>
|
|
33
|
+
</div>
|
|
34
|
+
</div>
|
|
@@ -1,27 +1,29 @@
|
|
|
1
1
|
<header class="content-header">
|
|
2
|
-
|
|
2
|
+
<div class="content-header-title">
|
|
3
|
+
<h1>
|
|
4
|
+
<%= content_for(:title) %>
|
|
5
|
+
</h1>
|
|
6
|
+
|
|
7
|
+
<% unless local_assigns.fetch(:hide_breadcrumbs, false) %>
|
|
8
|
+
<ol class="breadcrumb">
|
|
9
|
+
<% breadcrumbs.each do |breadcrumb| %>
|
|
10
|
+
<li class="breadcrumb-item<% if breadcrumb == breadcrumbs.last %> active<% end %>">
|
|
11
|
+
<%= link_to breadcrumb.label, breadcrumb.path %>
|
|
12
|
+
</li>
|
|
13
|
+
<% end %>
|
|
14
|
+
</ol>
|
|
15
|
+
<% end %>
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
<div class="content-header-toolbars">
|
|
3
19
|
<div class="btn-toolbar primary-toolbar">
|
|
4
|
-
<%=
|
|
20
|
+
<%= render_toolbar(toolbar(:primary)) %>
|
|
21
|
+
<%= deprecated_toolbar(:primary) %>
|
|
5
22
|
</div>
|
|
6
|
-
<% end %>
|
|
7
23
|
|
|
8
|
-
<% if content_for?(:secondary_toolbar) %>
|
|
9
24
|
<div class="btn-toolbar secondary-toolbar">
|
|
10
|
-
<%=
|
|
25
|
+
<%= render_toolbar(toolbar(:secondary)) %>
|
|
26
|
+
<%= deprecated_toolbar(:secondary) %>
|
|
11
27
|
</div>
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
<h1>
|
|
15
|
-
<%= content_for(:title) %>
|
|
16
|
-
</h1>
|
|
17
|
-
|
|
18
|
-
<% unless local_assigns.fetch(:hide_breadcrumbs, false) %>
|
|
19
|
-
<ol class="breadcrumb">
|
|
20
|
-
<% breadcrumbs.each do |breadcrumb| %>
|
|
21
|
-
<li class="breadcrumb-item<% if breadcrumb == breadcrumbs.last %> active<% end %>">
|
|
22
|
-
<%= link_to breadcrumb.label, breadcrumb.path %>
|
|
23
|
-
</li>
|
|
24
|
-
<% end %>
|
|
25
|
-
</ol>
|
|
26
|
-
<% end %>
|
|
28
|
+
</div>
|
|
27
29
|
</header>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<%= render "header", hide_breadcrumbs: local_assigns.fetch(:hide_breadcrumbs, false) if local_assigns.fetch(:header, true) %>
|
|
2
2
|
|
|
3
3
|
<div class="main-content-area">
|
|
4
|
-
<%= render "flash" %>
|
|
4
|
+
<%= render "trestle/flash/flash" %>
|
|
5
5
|
<%= render "utilities" %>
|
|
6
6
|
<%= render "tabs" %>
|
|
7
7
|
|
|
@@ -1,8 +1,14 @@
|
|
|
1
|
-
<% if tabs.size > 1 -%>
|
|
1
|
+
<% if tabs.size > 1 || render_sidebar_as_tab? -%>
|
|
2
2
|
<ul class="nav nav-tabs">
|
|
3
3
|
<% tabs.each do |name, tab| %>
|
|
4
4
|
<li<% if name == tabs.keys.first %> class="active"<% end %>>
|
|
5
|
-
<%= link_to tab.label, "
|
|
5
|
+
<%= link_to tab.label, "##{tab.id(("modal" if dialog_request?))}", role: "tab", data: { toggle: "tab" } %>
|
|
6
|
+
</li>
|
|
7
|
+
<% end %>
|
|
8
|
+
|
|
9
|
+
<% if render_sidebar_as_tab? %>
|
|
10
|
+
<li class="pull-right">
|
|
11
|
+
<%= link_to icon("fa fa-list-alt"), "#tab-sidebar", role: "tab", data: { toggle: "tab" } %>
|
|
6
12
|
</li>
|
|
7
13
|
<% end %>
|
|
8
14
|
</ul>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
<%= link_to "Debug errors", "#debug-errors", class: "toggle-debug-errors small", data: { toggle: "collapse" } %>
|
|
2
|
+
<div id="debug-errors" class="debug-errors collapse">
|
|
3
|
+
<ul>
|
|
4
|
+
<% instance.errors.each do |key, message| %>
|
|
5
|
+
<li class="small"><tt><%= key %>:</tt> <%= message %></li>
|
|
6
|
+
<% end %>
|
|
7
|
+
</ul>
|
|
8
|
+
</div>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
<% if flash[:message] -%>
|
|
2
|
+
<%= render "trestle/flash/alert", html_class: "alert-success", icon: icon("alert-icon ion-ios-checkmark-outline"), alert: normalize_flash_alert(flash[:message]) %>
|
|
3
|
+
<% elsif flash[:error] -%>
|
|
4
|
+
<%= render layout: "trestle/flash/alert", locals: { html_class: "alert-danger", icon: icon("alert-icon ion-ios-close-outline"), alert: normalize_flash_alert(flash[:error]) } do %>
|
|
5
|
+
<%= render "trestle/flash/debug" if debug_form_errors? %>
|
|
6
|
+
<% end %>
|
|
7
|
+
<% end -%>
|