trestle 0.8.9 → 0.8.10

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.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/trestle/components/_confirmation.js +31 -14
  3. data/app/assets/javascripts/trestle/components/_form.js +19 -15
  4. data/app/assets/javascripts/trestle/components/_tabs.js +1 -1
  5. data/app/assets/stylesheets/trestle/components/_breadcrumbs.scss +12 -0
  6. data/app/assets/stylesheets/trestle/components/_buttons.scss +102 -1
  7. data/app/assets/stylesheets/trestle/components/_content.scss +41 -21
  8. data/app/assets/stylesheets/trestle/components/_input-group.scss +8 -1
  9. data/app/assets/stylesheets/trestle/components/_modal.scss +3 -0
  10. data/app/assets/stylesheets/trestle/components/_pagination.scss +0 -3
  11. data/app/assets/stylesheets/trestle/components/_scopes.scss +11 -2
  12. data/app/assets/stylesheets/trestle/components/_table.scss +34 -10
  13. data/app/assets/stylesheets/trestle/components/_timestamp.scss +4 -1
  14. data/app/assets/stylesheets/trestle/components/_toolbars.scss +55 -0
  15. data/app/assets/stylesheets/trestle/core/_defaults.scss +13 -2
  16. data/app/assets/stylesheets/trestle/core/_mixins.scss +11 -0
  17. data/app/helpers/trestle/form_helper.rb +1 -5
  18. data/app/helpers/trestle/hook_helper.rb +10 -6
  19. data/app/helpers/trestle/timestamp_helper.rb +49 -7
  20. data/app/helpers/trestle/toolbars_helper.rb +34 -0
  21. data/app/views/layouts/trestle/admin.html.erb +2 -2
  22. data/app/views/trestle/application/_dialog.html.erb +8 -10
  23. data/app/views/trestle/application/_header.html.erb +22 -20
  24. data/app/views/trestle/resource/edit.html.erb +4 -6
  25. data/app/views/trestle/resource/index.html.erb +15 -6
  26. data/app/views/trestle/resource/new.html.erb +2 -2
  27. data/app/views/trestle/resource/show.html.erb +4 -6
  28. data/app/views/trestle/shared/_sidebar.html.erb +3 -1
  29. data/app/views/trestle/shared/_title.html.erb +14 -0
  30. data/config/locales/en.yml +2 -0
  31. data/config/locales/es-MX.yml +94 -0
  32. data/config/locales/es.yml +94 -0
  33. data/config/locales/lv.rb +18 -0
  34. data/config/locales/lv.yml +94 -0
  35. data/lib/generators/trestle/install/templates/trestle.rb.erb +12 -2
  36. data/lib/trestle.rb +2 -0
  37. data/lib/trestle/configuration.rb +9 -3
  38. data/lib/trestle/engine.rb +5 -3
  39. data/lib/trestle/form/fields/form_control.rb +14 -4
  40. data/lib/trestle/form/renderer.rb +2 -2
  41. data/lib/trestle/hook.rb +27 -0
  42. data/lib/trestle/table/actions_column.rb +31 -26
  43. data/lib/trestle/table/column.rb +1 -0
  44. data/lib/trestle/toolbar.rb +43 -0
  45. data/lib/trestle/toolbar/builder.rb +52 -0
  46. data/lib/trestle/toolbar/context.rb +39 -0
  47. data/lib/trestle/version.rb +1 -1
  48. metadata +13 -3
  49. data/app/helpers/trestle/title_helper.rb +0 -26
@@ -1,3 +1,17 @@
1
+ @mixin table-container-background($background) {
2
+ background-image: linear-gradient(to right, $background 30%, rgba($background, 0)),
3
+ linear-gradient(to left, $background 30%, rgba($background, 0)),
4
+ radial-gradient(at 0 50%, rgba(black, 0.2), rgba(black, 0) 70%),
5
+ radial-gradient(at 100% 50%, rgba(black, 0.2), rgba(black, 0) 70%);
6
+
7
+ background-color: $background;
8
+
9
+ background-position: 0 0, 100% 0, 0 0, 100% 0;
10
+ background-repeat: no-repeat;
11
+ background-size: 50px 100%, 50px 100%, 15px 100%, 15px 100%;
12
+ background-attachment: local, local, scroll, scroll;
13
+ }
14
+
1
15
  .table-container {
2
16
  overflow-x: auto;
3
17
 
@@ -5,15 +19,11 @@
5
19
  // scrolling background hints. Must be disabled explicitly.
6
20
  -webkit-overflow-scrolling: auto;
7
21
 
8
- background-image: linear-gradient(to right, white 30%, rgba(white, 0)),
9
- linear-gradient(to left, white 30%, rgba(white, 0)),
10
- radial-gradient(at 0 50%, rgba(black, 0.2), rgba(black, 0) 70%),
11
- radial-gradient(at 100% 50%, rgba(black, 0.2), rgba(black, 0) 70%);
12
- background-position: 0 0, 100% 0, 0 0, 100% 0;
13
- background-repeat: no-repeat;
14
- background-color: white;
15
- background-size: 50px 100%, 50px 100%, 15px 100%, 15px 100%;
16
- background-attachment: local, local, scroll, scroll;
22
+ @include table-container-background(white);
23
+
24
+ .main-content-sidebar & {
25
+ @include table-container-background($content-sidebar-background);
26
+ }
17
27
  }
18
28
 
19
29
  .trestle-table {
@@ -66,10 +76,24 @@
66
76
  text-align: center;
67
77
  }
68
78
 
69
- & + .btn {
79
+ &.has-icon .btn-label {
80
+ @include sr-only;
81
+ }
82
+ }
83
+
84
+ .btn,
85
+ .btn-group {
86
+ + .btn,
87
+ + .btn-group {
70
88
  margin-left: 4px;
71
89
  }
72
90
  }
91
+
92
+ .btn-group {
93
+ .btn + .btn {
94
+ margin-left: -1px;
95
+ }
96
+ }
73
97
  }
74
98
 
75
99
  .avatar {
@@ -5,8 +5,11 @@
5
5
  small {
6
6
  display: block;
7
7
  color: #666;
8
+ }
8
9
 
9
- .inline & {
10
+ &.timestamp-inline,
11
+ &.inline, {
12
+ small {
10
13
  display: inline;
11
14
  }
12
15
  }
@@ -0,0 +1,55 @@
1
+ .btn-toolbar {
2
+ .btn,
3
+ .btn-group,
4
+ .input-group {
5
+ float: none;
6
+ }
7
+
8
+ > .btn,
9
+ > .btn-group,
10
+ > .input-group {
11
+ margin-left: 1px;
12
+ }
13
+
14
+ .btn-group {
15
+ .btn + .btn,
16
+ .btn + .btn-group,
17
+ .btn-group + .btn,
18
+ .btn-group + .btn-group {
19
+ margin-left: -4px;
20
+ }
21
+ }
22
+ }
23
+
24
+ .primary-toolbar {
25
+ .btn {
26
+ @extend .btn-lg;
27
+ font-size: 20px;
28
+ padding: 8px 16px;
29
+ border-radius: $border-radius-base;
30
+
31
+ @include mobile {
32
+ font-size: 18px;
33
+ padding: 7px 12px;
34
+ }
35
+ }
36
+ }
37
+
38
+ .secondary-toolbar {
39
+ .btn {
40
+ font-size: 12px;
41
+ padding: 4px 10px;
42
+
43
+ i {
44
+ font-size: 11px;
45
+ }
46
+
47
+ @include mobile {
48
+ font-size: 11px;
49
+
50
+ i {
51
+ font-size: 10px;
52
+ }
53
+ }
54
+ }
55
+ }
@@ -32,7 +32,15 @@ $sidebar-toggle-color: rgba(white, 0.5) !default;
32
32
  $content-header-background: rgba(white, 0.6) !default;
33
33
 
34
34
  $content-sidebar-width: 285px !default;
35
- $content-sidebar-background: rgba(black, 0.025) !default;
35
+ $content-sidebar-background: #f9f9f9 !default;
36
+
37
+ $main-content-header-background: $content-sidebar-background !default;
38
+ $main-content-header-padding: 12px 20px !default;
39
+ $main-content-header-border: 1px solid rgba(black, 0.1) !default;
40
+
41
+ $main-content-footer-background: $content-sidebar-background !default;
42
+ $main-content-footer-padding: 12px 20px !default;
43
+ $main-content-footer-border: 1px solid rgba(black, 0.1) !default;
36
44
 
37
45
  $sidebar-transition-duration: 250ms !default;
38
46
 
@@ -41,7 +49,7 @@ $footer-text: #888 !default;
41
49
 
42
50
  $headings-font-weight: 400 !default;
43
51
 
44
- $btn-default-bg: #dbdbdb !default;
52
+ $btn-default-bg: #bbb !default;
45
53
  $btn-default-color: white !default;
46
54
 
47
55
  $state-success-bg: lighten(#dff0d8, 5%) !default;
@@ -83,4 +91,7 @@ $input-bg-disabled: #fafafa !default;
83
91
  $modal-inner-padding: 20px !default;
84
92
  $modal-title-padding: 15px 20px !default;
85
93
 
94
+ $modal-footer-background: $content-sidebar-background !default;
95
+ $modal-footer-border-color: rgba(black, 0.1) !default;
96
+
86
97
  $s2bs-btn-default-bg: #eee !default;
@@ -24,6 +24,17 @@
24
24
  right: 0;
25
25
  }
26
26
 
27
+ @mixin sr-only {
28
+ position: absolute;
29
+ width: 1px;
30
+ height: 1px;
31
+ margin: -1px;
32
+ padding: 0;
33
+ overflow: hidden;
34
+ clip: rect(0, 0, 0, 0);
35
+ border: 0;
36
+ }
37
+
27
38
  @mixin mobile {
28
39
  @media (max-width: $screen-xs-max) {
29
40
  @content;
@@ -5,7 +5,7 @@ module Trestle
5
5
  options[:as] ||= admin.parameter_name
6
6
 
7
7
  options[:data] ||= {}
8
- options[:data].merge!(remote: true, type: :html, behavior: "trestle-form", turbolinks: false)
8
+ options[:data].reverse_merge!(remote: true, type: :html, behavior: "trestle-form", turbolinks: false)
9
9
 
10
10
  form_for(instance, options) do |f|
11
11
  with_form(f) { yield f }
@@ -23,10 +23,6 @@ module Trestle
23
23
  @_trestle_form
24
24
  end
25
25
 
26
- def toolbar(name, &block)
27
- content_for(:"#{name}_toolbar", &block)
28
- end
29
-
30
26
  def sidebar(&block)
31
27
  content_for(:sidebar, &block)
32
28
  end
@@ -1,18 +1,22 @@
1
1
  module Trestle
2
2
  module HookHelper
3
3
  def hook(name)
4
- safe_join(hooks[name.to_s].map { |hook|
5
- instance_exec(&hook)
6
- }, "\n") if hook?(name)
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
- hooks.key?(name.to_s) && hooks[name.to_s].any?
14
+ Trestle.config.hooks.key?(name.to_s) && hooks(name).any?
11
15
  end
12
16
 
13
17
  protected
14
- def hooks
15
- Trestle.config.hooks
18
+ def hooks(name)
19
+ Trestle.config.hooks[name.to_s].select { |h| h.visible?(self) }
16
20
  end
17
21
  end
18
22
  end
@@ -1,17 +1,59 @@
1
1
  module Trestle
2
2
  module TimestampHelper
3
- def timestamp(time)
4
- time_tag(time, class: "timestamp") do
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: :trestle_date, default: proc { |date| "#{date.day.ordinalize} %b %Y" }),
7
- content_tag(:small, l(time, format: :trestle_time_with_seconds, default: "%l:%M:%S %p"))
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
- def datestamp(date)
13
- time_tag(date, class: "datestamp") do
14
- l(date, format: :trestle_calendar, default: "%-m/%-d/%Y")
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
@@ -36,14 +36,14 @@
36
36
  <%= hook :head %>
37
37
  </head>
38
38
 
39
- <body<%= " class=\"sidebar-#{cookies["trestle:sidebar"]}\"" if cookies["trestle:sidebar"] %>>
39
+ <body<%=raw " class=\"sidebar-#{cookies["trestle:sidebar"]}\"" if cookies["trestle:sidebar"] %>>
40
40
  <div class="app-wrapper">
41
41
  <%= render "trestle/shared/sidebar" %>
42
42
 
43
43
  <div class="app-container">
44
44
  <%= render "trestle/shared/header" %>
45
45
 
46
- <main class="app-main" data-context="<%= request.path %>">
46
+ <main class="app-main" data-context="<%= request.fullpath %>">
47
47
  <%= yield %>
48
48
  </main>
49
49
 
@@ -22,15 +22,13 @@
22
22
  </div>
23
23
 
24
24
  <div class="modal-footer">
25
- <% if content_for?(:secondary_toolbar) %>
26
- <div class="btn-toolbar secondary-toolbar">
27
- <%= content_for(:secondary_toolbar) %>
28
- </div>
29
- <% end %>
25
+ <div class="btn-toolbar secondary-toolbar">
26
+ <%= render_toolbar(toolbar(:secondary)) %>
27
+ <%= deprecated_toolbar(:secondary) %>
28
+ </div>
30
29
 
31
- <% if content_for?(:primary_toolbar) %>
32
- <div class="btn-toolbar primary-toolbar">
33
- <%= content_for(:primary_toolbar) %>
34
- </div>
35
- <% end %>
30
+ <div class="btn-toolbar primary-toolbar">
31
+ <%= render_toolbar(toolbar(:primary)) %>
32
+ <%= deprecated_toolbar(:primary) %>
33
+ </div>
36
34
  </div>
@@ -1,27 +1,29 @@
1
1
  <header class="content-header">
2
- <% if content_for?(:primary_toolbar) %>
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
- <%= content_for(:primary_toolbar) %>
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
- <%= content_for(:secondary_toolbar) %>
25
+ <%= render_toolbar(toolbar(:secondary)) %>
26
+ <%= deprecated_toolbar(:secondary) %>
11
27
  </div>
12
- <% end %>
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>
@@ -3,14 +3,12 @@
3
3
  <% content_for(:title, title) %>
4
4
  <% breadcrumb(title) %>
5
5
 
6
- <% content_for(:primary_toolbar) do %>
7
- <%= button_tag admin.t("buttons.save", default: "Save %{model_name}"), class: "btn btn-success btn-lg" if admin.actions.include?(:update) %>
6
+ <% toolbar(:primary) do |t| %>
7
+ <%= t.button admin.t("buttons.save", default: "Save %{model_name}"), style: :success if admin.actions.include?(:update) %>
8
8
  <% end %>
9
9
 
10
- <% content_for(:secondary_toolbar) do %>
11
- <%= admin_link_to instance, action: :destroy, method: :delete, class: "btn btn-danger", data: { toggle: "confirm-delete", placement: "bottom" } do %>
12
- <%= icon("fa fa-trash") %> <%= admin.t("buttons.delete", default: "Delete %{model_name}") %>
13
- <% end if admin.actions.include?(:destroy) %>
10
+ <% toolbar(:secondary) do |t| %>
11
+ <%= t.link admin.t("buttons.delete", default: "Delete %{model_name}"), instance, action: :destroy, method: :delete, style: :danger, icon: "fa fa-trash", data: { toggle: "confirm-delete", placement: "bottom" } if admin.actions.include?(:destroy) %>
14
12
  <% end %>
15
13
 
16
14
  <%= trestle_form_for instance, url: admin.actions.include?(:update) ? admin.instance_path(instance, action: :update) : "#", method: :patch do |f| %>