trestle 0.8.3 → 0.8.6

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 (171) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -0
  3. data/.travis.yml +10 -1
  4. data/Gemfile +4 -0
  5. data/README.md +1 -0
  6. data/app/assets/javascripts/trestle/admin.js +24 -0
  7. data/app/assets/javascripts/trestle/components/_confirmation.js +23 -0
  8. data/app/assets/javascripts/trestle/components/_datepicker.js +22 -0
  9. data/app/assets/javascripts/trestle/components/_dialog.js +107 -0
  10. data/app/assets/javascripts/trestle/components/_errors.js +11 -0
  11. data/app/assets/javascripts/trestle/components/_form.js +48 -0
  12. data/app/assets/javascripts/trestle/components/_gallery.js +27 -0
  13. data/app/assets/javascripts/trestle/components/_select.js +11 -0
  14. data/app/assets/javascripts/trestle/components/_sidebar.js +75 -0
  15. data/app/assets/javascripts/trestle/components/_table.js +21 -0
  16. data/app/assets/javascripts/trestle/components/_tabs.js +24 -0
  17. data/app/assets/javascripts/trestle/components/_tooltips.js +3 -0
  18. data/app/assets/javascripts/trestle/core/_contexts.js +13 -0
  19. data/app/assets/javascripts/trestle/core/_cookies.js +24 -0
  20. data/app/assets/javascripts/trestle/core/_events.js +39 -0
  21. data/app/assets/javascripts/trestle/core/_visit.js +10 -0
  22. data/app/assets/javascripts/trestle/custom.js +4 -0
  23. data/app/assets/stylesheets/trestle/components/_alerts.scss +28 -0
  24. data/app/assets/stylesheets/trestle/components/_buttons.scss +9 -0
  25. data/app/assets/stylesheets/trestle/components/_modal.scss +92 -0
  26. data/app/assets/stylesheets/trestle/components/_navigation.scss +80 -10
  27. data/app/assets/stylesheets/trestle/components/_sidebar.scss +1 -0
  28. data/app/assets/stylesheets/trestle/components/_table.scss +6 -0
  29. data/app/assets/stylesheets/trestle/core/_defaults.scss +5 -1
  30. data/app/controllers/trestle/application_controller.rb +5 -1
  31. data/app/helpers/trestle/dialog_helper.rb +7 -0
  32. data/app/helpers/trestle/form_helper.rb +8 -1
  33. data/app/helpers/trestle/format_helper.rb +48 -0
  34. data/app/helpers/trestle/hook_helper.rb +8 -3
  35. data/app/helpers/trestle/url_helper.rb +33 -11
  36. data/app/views/layouts/trestle/admin.html.erb +4 -4
  37. data/app/views/trestle/admin/index.html.erb +1 -1
  38. data/app/views/trestle/application/_alert.html.erb +2 -0
  39. data/app/views/trestle/application/_dialog.html.erb +36 -0
  40. data/app/views/trestle/application/_flash.html.erb +18 -4
  41. data/app/views/trestle/application/_tabs.html.erb +7 -1
  42. data/app/views/trestle/dashboard/index.html.erb +2 -2
  43. data/app/views/trestle/resource/_form.html.erb +1 -1
  44. data/app/views/trestle/resource/edit.html.erb +6 -6
  45. data/app/views/trestle/resource/index.html.erb +5 -2
  46. data/app/views/trestle/resource/new.html.erb +4 -4
  47. data/app/views/trestle/resource/show.html.erb +6 -6
  48. data/app/views/trestle/shared/_sidebar.html.erb +7 -4
  49. data/bower.json +2 -2
  50. data/config/locales/en.yml +38 -18
  51. data/config/locales/fr.rb +18 -0
  52. data/config/locales/fr.yml +69 -0
  53. data/config/locales/nl.rb +18 -0
  54. data/config/locales/nl.yml +67 -0
  55. data/config/locales/pl.rb +18 -0
  56. data/config/locales/pl.yml +70 -0
  57. data/config/locales/pt-BR.rb +18 -0
  58. data/config/locales/pt-BR.yml +69 -0
  59. data/gemfiles/rails-4.2.gemfile +14 -0
  60. data/gemfiles/rails-5.0.gemfile +14 -0
  61. data/gemfiles/rails-5.1.gemfile +14 -0
  62. data/gemfiles/rails-edge.gemfile +15 -0
  63. data/lib/generators/trestle/install/install_generator.rb +3 -3
  64. data/lib/generators/trestle/install/templates/custom.js +7 -0
  65. data/lib/generators/trestle/install/templates/trestle.rb.erb +9 -2
  66. data/lib/generators/trestle/resource/templates/admin.rb.erb +1 -1
  67. data/lib/trestle/adapters/active_record_adapter.rb +46 -20
  68. data/lib/trestle/adapters/adapter.rb +176 -0
  69. data/lib/trestle/adapters/sequel_adapter.rb +85 -0
  70. data/lib/trestle/adapters.rb +7 -64
  71. data/lib/trestle/admin/builder.rb +10 -2
  72. data/lib/trestle/admin.rb +14 -1
  73. data/lib/trestle/attribute.rb +14 -37
  74. data/lib/trestle/breadcrumb.rb +19 -0
  75. data/lib/trestle/configuration.rb +14 -3
  76. data/lib/trestle/display.rb +1 -1
  77. data/lib/trestle/form/automatic.rb +29 -21
  78. data/lib/trestle/form/builder.rb +4 -0
  79. data/lib/trestle/form/field.rb +2 -2
  80. data/lib/trestle/form/fields/check_box.rb +1 -1
  81. data/lib/trestle/form/fields/collection_select.rb +1 -1
  82. data/lib/trestle/form/fields/date_select.rb +1 -1
  83. data/lib/trestle/form/fields/datetime_select.rb +1 -1
  84. data/lib/trestle/form/fields/grouped_collection_select.rb +1 -1
  85. data/lib/trestle/form/fields/select.rb +2 -2
  86. data/lib/trestle/form/fields/tag_select.rb +1 -2
  87. data/lib/trestle/form/fields/time_select.rb +1 -1
  88. data/lib/trestle/form/fields/time_zone_select.rb +1 -1
  89. data/lib/trestle/form.rb +7 -3
  90. data/lib/trestle/model_name.rb +64 -0
  91. data/lib/trestle/navigation/group.rb +8 -0
  92. data/lib/trestle/navigation/item.rb +1 -1
  93. data/lib/trestle/options.rb +7 -5
  94. data/lib/trestle/reloader.rb +1 -1
  95. data/lib/trestle/resource/builder.rb +17 -1
  96. data/lib/trestle/resource/controller.rb +80 -18
  97. data/lib/trestle/resource.rb +26 -16
  98. data/lib/trestle/scope.rb +1 -1
  99. data/lib/trestle/table/actions_column.rb +21 -16
  100. data/lib/trestle/table/automatic.rb +5 -12
  101. data/lib/trestle/table/builder.rb +3 -2
  102. data/lib/trestle/table/column.rb +27 -45
  103. data/lib/trestle/table/row.rb +8 -2
  104. data/lib/trestle/table.rb +7 -1
  105. data/lib/trestle/version.rb +1 -1
  106. data/lib/trestle.rb +1 -0
  107. data/trestle.gemspec +5 -5
  108. data/vendor/assets/bower_components/trestle/flatpickr/dist/flatpickr.css +51 -26
  109. data/vendor/assets/bower_components/trestle/flatpickr/dist/flatpickr.js +349 -299
  110. data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/ar.js +5 -5
  111. data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/bg.js +5 -5
  112. data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/bn.js +5 -5
  113. data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/cat.js +7 -7
  114. data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/cs.js +7 -7
  115. data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/cy.js +7 -7
  116. data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/da.js +6 -6
  117. data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/de.js +10 -10
  118. data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/eo.js +11 -11
  119. data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/es.js +7 -7
  120. data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/et.js +11 -11
  121. data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/fa.js +6 -6
  122. data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/fi.js +7 -7
  123. data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/fr.js +11 -11
  124. data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/gr.js +13 -13
  125. data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/he.js +5 -5
  126. data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/hi.js +5 -5
  127. data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/hr.js +6 -6
  128. data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/hu.js +10 -10
  129. data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/id.js +7 -7
  130. data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/index.js +97 -0
  131. data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/it.js +10 -10
  132. data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/ja.js +5 -5
  133. data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/ko.js +6 -6
  134. data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/lt.js +10 -10
  135. data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/lv.js +6 -6
  136. data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/mk.js +8 -8
  137. data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/ms.js +7 -7
  138. data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/my.js +7 -7
  139. data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/nl.js +11 -11
  140. data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/no.js +11 -11
  141. data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/pa.js +5 -5
  142. data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/pl.js +6 -6
  143. data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/pt.js +6 -8
  144. data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/ro.js +7 -9
  145. data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/ru.js +6 -8
  146. data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/si.js +5 -7
  147. data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/sk.js +8 -8
  148. data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/sl.js +8 -10
  149. data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/sq.js +5 -7
  150. data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/sr.js +9 -10
  151. data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/sv.js +8 -10
  152. data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/th.js +10 -11
  153. data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/tr.js +6 -8
  154. data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/uk.js +6 -7
  155. data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/vn.js +6 -8
  156. data/vendor/assets/bower_components/trestle/flatpickr/dist/l10n/zh.js +9 -11
  157. data/vendor/assets/bower_components/trestle/select2/dist/js/select2.full.js +90 -69
  158. metadata +58 -33
  159. data/app/assets/javascripts/trestle/_confirmation.js.coffee +0 -18
  160. data/app/assets/javascripts/trestle/_datepicker.js.coffee +0 -18
  161. data/app/assets/javascripts/trestle/_errors.js.coffee +0 -8
  162. data/app/assets/javascripts/trestle/_form.js.coffee +0 -4
  163. data/app/assets/javascripts/trestle/_gallery.js.coffee +0 -21
  164. data/app/assets/javascripts/trestle/_select.js.coffee +0 -7
  165. data/app/assets/javascripts/trestle/_sidebar.js.coffee +0 -45
  166. data/app/assets/javascripts/trestle/_table.js.coffee +0 -16
  167. data/app/assets/javascripts/trestle/_tabs.js.coffee +0 -9
  168. data/app/assets/javascripts/trestle/_tooltips.js.coffee +0 -2
  169. data/app/assets/javascripts/trestle/admin.js.coffee +0 -22
  170. data/app/assets/javascripts/trestle/custom.js.coffee +0 -4
  171. data/lib/generators/trestle/install/templates/custom.js.coffee +0 -7
@@ -0,0 +1,92 @@
1
+ .modal-content {
2
+ border: none;
3
+ border-radius: 0;
4
+
5
+ .modal.loading & {
6
+ min-height: 100px;
7
+
8
+ display: flex;
9
+ align-items: center;
10
+ justify-content: center;
11
+
12
+ &:after {
13
+ @extend .fa;
14
+ @extend .fa-spin;
15
+ content: $fa-var-spinner;
16
+
17
+ font-size: 32px;
18
+ opacity: 0.25;
19
+ }
20
+ }
21
+ }
22
+
23
+ .modal-header {
24
+ background: $theme-bg;
25
+ border-bottom: none;
26
+
27
+ .close {
28
+ opacity: 0.75;
29
+
30
+ &, &:hover, &:focus {
31
+ color: white;
32
+ }
33
+
34
+ &:hover, &:focus {
35
+ opacity: 1;
36
+ }
37
+ }
38
+
39
+ .modal.error & {
40
+ background: $error-bg;
41
+ }
42
+ }
43
+
44
+ .modal-title {
45
+ font-size: 18px;
46
+ font-weight: 500;
47
+ text-shadow: rgba(black, 0.5) 0 1px 1px;
48
+ color: white;
49
+ }
50
+
51
+ .modal-tabs .nav-tabs {
52
+ background: $body-bg;
53
+ padding: 10px 15px 0 15px;
54
+ }
55
+
56
+ .modal-flash {
57
+ .alert {
58
+ margin-bottom: 0;
59
+ border-radius: 0;
60
+ border-width: 0 0 1px 0;
61
+
62
+ padding-top: 10px;
63
+ padding-bottom: 10px;
64
+
65
+ .alert-icon {
66
+ font-size: 40px;
67
+ margin-right: 15px;
68
+ }
69
+
70
+ h3 {
71
+ font-size: 18px;
72
+ }
73
+
74
+ p {
75
+ font-size: 13px;
76
+ }
77
+ }
78
+ }
79
+
80
+ .modal-body {
81
+ @extend .tab-content;
82
+ }
83
+
84
+ .modal-footer {
85
+ .primary-toolbar {
86
+ float: right;
87
+ }
88
+
89
+ .secondary-toolbar {
90
+ float: left;
91
+ }
92
+ }
@@ -38,7 +38,8 @@
38
38
  vertical-align: 0;
39
39
  }
40
40
 
41
- .nav-header {
41
+ .nav-header a {
42
+ position: relative;
42
43
  color: rgba(white, 0.25);
43
44
 
44
45
  text-transform: uppercase;
@@ -46,6 +47,24 @@
46
47
  font-size: 11px;
47
48
 
48
49
  padding: 5px 20px;
50
+
51
+ &::after {
52
+ @extend .ion;
53
+ content: $ionicon-var-arrow-down-b;
54
+
55
+ float: right;
56
+ margin-top: 2px;
57
+
58
+ opacity: 0.75;
59
+ }
60
+
61
+ &:hover, &:focus {
62
+ background: none;
63
+
64
+ &::before, &::after {
65
+ opacity: 1 !important;
66
+ }
67
+ }
49
68
  }
50
69
 
51
70
  .active a {
@@ -62,14 +81,46 @@
62
81
  position: relative;
63
82
  top: 1px;
64
83
  }
84
+
85
+ .collapsed {
86
+ li {
87
+ display: none;
88
+
89
+ &.nav-header {
90
+ display: block;
91
+ }
92
+ }
93
+ }
65
94
  }
66
95
 
67
96
  @mixin collapsed-nav-header {
68
- border-bottom: 1px solid rgba(white, 0.1);
69
97
  height: 0;
70
- margin: 0 15px 14px;
71
- padding: 5px 0;
98
+ padding: 10px 15px 15px;
72
99
  text-indent: -99999px;
100
+
101
+ &::after {
102
+ display: none;
103
+
104
+ position: absolute;
105
+ top: 4px;
106
+ left: 50%;
107
+ margin-left: -3px;
108
+
109
+ text-indent: 0;
110
+ }
111
+
112
+ &::before {
113
+ content: "";
114
+
115
+ position: absolute;
116
+ left: 15px;
117
+ right: 15px;
118
+ top: 50%;
119
+ margin-top: -4px;
120
+
121
+ border-bottom: 1px solid rgba(white, 0.1);
122
+ opacity: 0.75;
123
+ }
73
124
  }
74
125
 
75
126
  @include tablet {
@@ -78,18 +129,31 @@
78
129
  display: none;
79
130
  }
80
131
 
81
- .nav-header {
132
+ .nav-header a {
82
133
  @include collapsed-nav-header;
83
134
  }
84
135
 
85
- .expanded & {
86
- .nav-header {
136
+ .collapsed .nav-header a {
137
+ &::after {
87
138
  display: block;
88
- border-bottom: none;
139
+ }
140
+ }
141
+
142
+ .expanded & {
143
+ .nav-header a {
89
144
  height: auto;
90
- margin: 0;
91
145
  padding: 5px 20px;
92
146
  text-indent: 0;
147
+
148
+ &::before {
149
+ display: none;
150
+ }
151
+
152
+ &::after {
153
+ display: block;
154
+ position: static;
155
+ margin-left: 0;
156
+ }
93
157
  }
94
158
 
95
159
  .nav-label { display: inline; }
@@ -104,8 +168,14 @@
104
168
  display: none;
105
169
  }
106
170
 
107
- .nav-header {
171
+ .nav-header a {
108
172
  @include collapsed-nav-header;
109
173
  }
174
+
175
+ .collapsed .nav-header a {
176
+ &::after {
177
+ display: block;
178
+ }
179
+ }
110
180
  }
111
181
  }
@@ -15,6 +15,7 @@
15
15
  display: flex;
16
16
  flex-direction: column;
17
17
 
18
+ overflow-x: hidden;
18
19
  overflow-y: auto;
19
20
 
20
21
  &::-webkit-scrollbar {
@@ -77,4 +77,10 @@
77
77
  height: 32px;
78
78
  vertical-align: middle;
79
79
  }
80
+
81
+ ul, ol {
82
+ margin-bottom: 0;
83
+ padding-left: 0;
84
+ list-style-position: inside;
85
+ }
80
86
  }
@@ -11,6 +11,7 @@ $theme-bg-gradient: linear-gradient(rgba(white, $theme-bg-gradient-stre
11
11
  $theme-bg-color: darken($brand-primary, 15%) !default;
12
12
 
13
13
  $theme-bg: $theme-bg-texture-url, $theme-bg-gradient, $theme-bg-color !default;
14
+ $error-bg: $theme-bg-texture-url, $theme-bg-gradient, $brand-danger !default;
14
15
 
15
16
  $body-bg: #f3f3f3 !default;
16
17
 
@@ -45,7 +46,7 @@ $btn-default-color: white !default;
45
46
 
46
47
  $state-success-bg: lighten(#dff0d8, 5%) !default;
47
48
  $state-info-bg: lighten(#d9edf7, 5%) !default;
48
- $state-warning-bg: lighten(#fcf8e3, 5%) !default;
49
+ $state-warning-bg: lighten(#fcf8e3, 2.5%) !default;
49
50
  $state-danger-bg: lighten(#f2dede, 5%) !default;
50
51
 
51
52
  $alert-padding: 20px !default;
@@ -79,4 +80,7 @@ $input-border: #ccc !default;
79
80
  $input-border-focus: mix($brand-primary, $input-border) !default;
80
81
  $input-bg-disabled: #fafafa !default;
81
82
 
83
+ $modal-inner-padding: 20px !default;
84
+ $modal-title-padding: 15px 20px !default;
85
+
82
86
  $s2bs-btn-default-bg: #eee !default;
@@ -1,7 +1,7 @@
1
1
  class Trestle::ApplicationController < ActionController::Base
2
2
  protect_from_forgery
3
3
 
4
- layout 'trestle/admin'
4
+ layout :choose_layout
5
5
 
6
6
  # Global helpers
7
7
  self.helpers_path += Rails.application.helpers_paths
@@ -31,4 +31,8 @@ protected
31
31
  breadcrumbs.append(label, path)
32
32
  end
33
33
  helper_method :breadcrumb
34
+
35
+ def choose_layout
36
+ request.xhr? ? false : "trestle/admin"
37
+ end
34
38
  end
@@ -0,0 +1,7 @@
1
+ module Trestle
2
+ module DialogHelper
3
+ def dialog_request?
4
+ request.headers["X-Trestle-Dialog"]
5
+ end
6
+ end
7
+ end
@@ -4,8 +4,11 @@ module Trestle
4
4
  options[:builder] ||= Form::Builder
5
5
  options[:as] ||= admin.admin_name.singularize
6
6
 
7
+ options[:data] ||= {}
8
+ options[:data].merge!(remote: true, type: :html, behavior: "trestle-form", turbolinks: false)
9
+
7
10
  form_for(instance, options) do |f|
8
- with_form(f) { yield }
11
+ with_form(f) { yield f }
9
12
  end
10
13
  end
11
14
 
@@ -27,5 +30,9 @@ module Trestle
27
30
  def sidebar(&block)
28
31
  content_for(:sidebar, &block)
29
32
  end
33
+
34
+ def render_sidebar_as_tab?
35
+ dialog_request? && content_for?(:sidebar)
36
+ end
30
37
  end
31
38
  end
@@ -0,0 +1,48 @@
1
+ module Trestle
2
+ module FormatHelper
3
+ def format_value(value, options={})
4
+ if options.key?(:format)
5
+ format_value_from_options(value, options)
6
+ else
7
+ autoformat_value(value, options)
8
+ end
9
+ end
10
+
11
+ def format_value_from_options(value, options={})
12
+ case options[:format]
13
+ when :currency
14
+ number_to_currency(value)
15
+ when :tags
16
+ safe_join(value.map { |tag| content_tag(:span, tag, class: "tag") })
17
+ else
18
+ value
19
+ end
20
+ end
21
+
22
+ def autoformat_value(value, options={})
23
+ case value
24
+ when Array
25
+ content_tag(:ol, safe_join(value.map { |v| content_tag(:li, autoformat_value(v, options)) }, "\n"))
26
+ when Time, DateTime
27
+ timestamp(value)
28
+ when Date
29
+ datestamp(value)
30
+ when TrueClass, FalseClass
31
+ status_tag(icon("fa fa-check"), :success) if value
32
+ when NilClass
33
+ text = options.key?(:blank) ? options[:blank] : I18n.t("admin.format.blank")
34
+ content_tag(:span, text, class: "blank")
35
+ when String
36
+ if value.html_safe? || options[:truncate] == false
37
+ value
38
+ else
39
+ truncate(value, options[:truncate] || {})
40
+ end
41
+ when ->(value) { value.respond_to?(:id) }
42
+ display(value)
43
+ else
44
+ value
45
+ end
46
+ end
47
+ end
48
+ end
@@ -1,13 +1,18 @@
1
1
  module Trestle
2
2
  module HookHelper
3
3
  def hook(name)
4
- safe_join(Trestle.config.hooks[name.to_s].map { |hook|
4
+ safe_join(hooks[name.to_s].map { |hook|
5
5
  instance_exec(&hook)
6
- }, "\n")
6
+ }, "\n") if hook?(name)
7
7
  end
8
8
 
9
9
  def hook?(name)
10
- Trestle.config.hooks[name.to_s].any?
10
+ hooks.key?(name.to_s) && hooks[name.to_s].any?
11
+ end
12
+
13
+ protected
14
+ def hooks
15
+ Trestle.config.hooks
11
16
  end
12
17
  end
13
18
  end
@@ -1,26 +1,48 @@
1
1
  module Trestle
2
2
  module UrlHelper
3
- def admin_link_to(content, instance=nil, options={}, &block)
3
+ def admin_link_to(content, instance_or_url=nil, options={}, &block)
4
4
  if block_given?
5
- instance, options = content, instance || {}
5
+ instance_or_url, options = content, instance_or_url || {}
6
6
  content = capture(&block)
7
7
  end
8
8
 
9
- if options.key?(:admin)
10
- admin = Trestle.lookup(options.delete(:admin))
9
+ if instance_or_url.is_a?(String)
10
+ link_to(content, instance_or_url, options)
11
11
  else
12
- admin = admin_for(instance) || self.admin
13
- end
12
+ if instance_or_url.is_a?(Hash)
13
+ instance_or_url, options = nil, instance_or_url
14
+ end
14
15
 
15
- if admin
16
- link_to(content, admin_url_for(instance, admin: admin), options)
17
- else
18
- content
16
+ if options.key?(:admin)
17
+ admin = Trestle.lookup(options.delete(:admin))
18
+ elsif instance_or_url.respond_to?(:id)
19
+ admin = admin_for(instance_or_url)
20
+ end
21
+
22
+ admin ||= self.admin if respond_to?(:admin)
23
+
24
+ if admin
25
+ action = options.delete(:action) || :show
26
+
27
+ params = options.delete(:params) || {}
28
+ params[:id] ||= admin.to_param(instance_or_url) if instance_or_url
29
+
30
+ if [:show, :edit].include?(action) && admin.form.dialog?
31
+ options[:data] ||= {}
32
+ options[:data][:behavior] ||= "dialog"
33
+ end
34
+
35
+ link_to(content, admin.path(action, params), options)
36
+ else
37
+ raise ActionController::UrlGenerationError, "An admin could not be inferred. Please specify an admin using the :admin option."
38
+ end
19
39
  end
20
40
  end
21
41
 
22
42
  def admin_url_for(instance, options={})
23
- admin = Trestle.lookup(options[:admin] || self.admin)
43
+ admin = Trestle.lookup(options[:admin]) if options.key?(:admin)
44
+ admin ||= admin_for(instance)
45
+
24
46
  admin.path(options[:action] || :show, id: admin.to_param(instance)) if admin
25
47
  end
26
48
 
@@ -23,11 +23,11 @@
23
23
 
24
24
  <script type="text/javascript">
25
25
  <% Trestle.config.javascript_i18n_keys.each do |key| %>
26
- Trestle.i18n['<%= key %>'] = "<%= escape_javascript(t(key, default: t(key, locale: :en))) %>";
26
+ Trestle.i18n['<%= key %>'] = "<%= escape_javascript(t(key, default: t(key, locale: :en))) %>";
27
27
  <% end %>
28
28
 
29
- if (Flatpickr.l10ns['<%= I18n.locale %>']) {
30
- Flatpickr.localize(Flatpickr.l10ns['<%= I18n.locale %>']);
29
+ if (flatpickr.l10ns['<%= I18n.locale %>']) {
30
+ flatpickr.localize(flatpickr.l10ns['<%= I18n.locale %>']);
31
31
  }
32
32
  </script>
33
33
 
@@ -45,7 +45,7 @@
45
45
  <div class="app-container">
46
46
  <%= render "trestle/shared/header" %>
47
47
 
48
- <main class="app-main">
48
+ <main class="app-main" data-context="<%= request.path %>">
49
49
  <%= yield %>
50
50
  </main>
51
51
 
@@ -1,5 +1,5 @@
1
1
  <% content_for(:title, admin.admin_name.titleize) %>
2
2
 
3
3
  <%= render layout: "layout" do %>
4
- To customize this template, please create <code>app/views/<%= admin.controller_path %>/index.html.erb</code>.
4
+ <p><%= t("trestle.onboarding.no_template", path: "app/views/#{admin.controller_path}/index.html.erb", default: "To customize this template, please create <code>%{path}</code>.").html_safe %></p>
5
5
  <% end %>
@@ -6,5 +6,7 @@
6
6
  <div class="alert-content">
7
7
  <h3><%= title %></h3>
8
8
  <p><%= message %></p>
9
+
10
+ <%= yield if block_given? %>
9
11
  </div>
10
12
  </div>
@@ -0,0 +1,36 @@
1
+ <div class="modal-header">
2
+ <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
3
+ <h4 class="modal-title"><%= content_for(:title) %></h4>
4
+ </div>
5
+
6
+ <div class="modal-flash">
7
+ <%= render "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
+ <% if content_for?(:secondary_toolbar) %>
26
+ <div class="btn-toolbar secondary-toolbar">
27
+ <%= content_for(:secondary_toolbar) %>
28
+ </div>
29
+ <% end %>
30
+
31
+ <% if content_for?(:primary_toolbar) %>
32
+ <div class="btn-toolbar primary-toolbar">
33
+ <%= content_for(:primary_toolbar) %>
34
+ </div>
35
+ <% end %>
36
+ </div>
@@ -4,8 +4,22 @@
4
4
  title: t("trestle.flash.success.title", default: "Success!"),
5
5
  message: flash[:message] %>
6
6
  <% elsif flash[:error] -%>
7
- <%= render "alert", html_class: "alert-danger",
8
- icon: icon("alert-icon ion-ios-close-outline"),
9
- title: t("trestle.flash.failure.title", default: "Warning!"),
10
- message: flash[:error] %>
7
+ <%= render layout: "alert",
8
+ locals: {
9
+ html_class: "alert-danger",
10
+ icon: icon("alert-icon ion-ios-close-outline"),
11
+ title: t("trestle.flash.failure.title", default: "Warning!"),
12
+ message: flash[:error]
13
+ } do %>
14
+ <%- if Trestle.config.debug_form_errors && instance && instance.errors.any? -%>
15
+ <%= link_to "Debug errors", "#debug-errors", class: "toggle-debug-errors small", data: { toggle: "collapse" } %>
16
+ <div id="debug-errors" class="debug-errors collapse">
17
+ <ul>
18
+ <% instance.errors.each do |key, message| %>
19
+ <li class="small"><tt><%= key %>:</tt> <%= message %></li>
20
+ <% end %>
21
+ </ul>
22
+ </div>
23
+ <%- end -%>
24
+ <% end %>
11
25
  <% end -%>
@@ -1,9 +1,15 @@
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
5
  <%= link_to tab.label, "#tab-#{name}", role: "tab", data: { toggle: "tab" } %>
6
6
  </li>
7
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" } %>
12
+ </li>
13
+ <% end %>
8
14
  </ul>
9
15
  <% end %>
@@ -1,5 +1,5 @@
1
- <% content_for(:title, "Welcome to Trestle") %>
1
+ <% content_for(:title, t("trestle.onboarding.welcome", default: "Welcome to Trestle")) %>
2
2
 
3
3
  <%= render layout: "layout" do %>
4
- <p>To begin, please create an admin within <code>app/admin</code>.</p>
4
+ <p><%= t("trestle.onboarding.no_admins", default: "To begin, please create an admin within <code>app/admin</code>.").html_safe %></p>
5
5
  <% end %>
@@ -1,5 +1,5 @@
1
1
  <% if admin.form -%>
2
2
  <%= admin.form.render(self, instance) %>
3
3
  <% else %>
4
- <p>Please define a form block or create a <code>_form.html</code> partial.</p>
4
+ <p><%= t("trestle.onboarding.no_form", default: "Please define a form block or create a <code>_form.html</code> partial.").html_safe %></p>
5
5
  <% end %>
@@ -1,18 +1,18 @@
1
- <% title = I18n.t("admin.titles.edit", default: "Editing %{model_name}", model_name: admin.model_name, pluralized_model_name: admin.model_name.pluralize) %>
1
+ <% title = t("admin.titles.edit", default: "Editing %{model_name}", model_name: admin.model_name.titleize, pluralized_model_name: admin.model_name.plural.titleize) %>
2
2
 
3
3
  <% content_for(:title, title) %>
4
4
  <% breadcrumb title %>
5
5
 
6
6
  <% content_for(:primary_toolbar) do %>
7
- <%= button_tag t("admin.buttons.save", default: "Save %{model_name}", model_name: admin.model_name), class: "btn btn-success btn-lg" unless admin.readonly? %>
7
+ <%= button_tag t("admin.buttons.save", default: "Save %{model_name}", model_name: admin.model_name), class: "btn btn-success btn-lg" if admin.actions.include?(:update) %>
8
8
  <% end %>
9
9
 
10
10
  <% content_for(:secondary_toolbar) do %>
11
- <%= link_to admin.path(:destroy, id: admin.to_param(instance)), method: :delete, class: "btn btn-danger", data: { toggle: "confirm-delete", placement: "bottom" } do %>
11
+ <%= admin_link_to instance, action: :destroy, method: :delete, class: "btn btn-danger", data: { toggle: "confirm-delete", placement: "bottom" } do %>
12
12
  <%= icon("fa fa-trash") %> <%= t("admin.buttons.delete", default: "Delete %{model_name}", model_name: admin.model_name) %>
13
- <% end unless admin.readonly? %>
13
+ <% end if admin.actions.include?(:destroy) %>
14
14
  <% end %>
15
15
 
16
- <%= trestle_form_for instance, url: admin.readonly? ? "#" : admin.path(:update, id: admin.to_param(instance)) do |f| %>
17
- <%= render partial: "form", layout: "layout" %>
16
+ <%= trestle_form_for instance, url: admin.actions.include?(:update) ? admin.path(:update, id: admin.to_param(instance)) : "#", method: :patch do |f| %>
17
+ <%= render partial: "form", layout: dialog_request? ? "dialog" : "layout" %>
18
18
  <% end %>
@@ -1,7 +1,10 @@
1
- <% content_for(:title, I18n.t("admin.titles.index", default: "Listing %{pluralized_model_name}", model_name: admin.model_name, pluralized_model_name: admin.model_name.pluralize)) %>
1
+ <% content_for(:title, t("admin.titles.index", default: "Listing %{pluralized_model_name}", model_name: admin.model_name.titleize, pluralized_model_name: admin.model_name.plural.titleize)) %>
2
2
 
3
3
  <% content_for(:primary_toolbar) do %>
4
- <%= link_to icon("fa fa-plus"), admin.path(:new), class: "btn btn-default btn-lg" unless admin.readonly? %>
4
+ <%= admin_link_to action: :new, class: "btn btn-default btn-lg" do %>
5
+ <%= icon("fa fa-plus") %>
6
+ <span class="sr-only"><%= t("admin.buttons.new", default: "New %{model_name}", model_name: admin.model_name) %></span>
7
+ <% end if admin.actions.include?(:new) %>
5
8
  <% end %>
6
9
 
7
10
  <% content_for(:utilities) do %>
@@ -1,12 +1,12 @@
1
- <% title = t("admin.titles.new", default: "New %{model_name}", model_name: admin.model_name, pluralized_model_name: admin.model_name.pluralize) %>
1
+ <% title = t("admin.titles.new", default: "New %{model_name}", model_name: admin.model_name.titleize, pluralized_model_name: admin.model_name.plural.titleize) %>
2
2
 
3
3
  <% content_for(:title, title) %>
4
4
  <% breadcrumb title %>
5
5
 
6
6
  <% content_for(:primary_toolbar) do %>
7
- <%= button_tag t("admin.buttons.save", default: "Save %{model_name}", model_name: admin.model_name), class: "btn btn-success btn-lg" %>
7
+ <%= button_tag t("admin.buttons.save", default: "Save %{model_name}", model_name: admin.model_name), class: "btn btn-success btn-lg" if admin.actions.include?(:create) %>
8
8
  <% end %>
9
9
 
10
- <%= trestle_form_for instance, url: admin.path do |f| %>
11
- <%= render partial: "form", layout: "layout" %>
10
+ <%= trestle_form_for instance, url: admin.path, method: :post do |f| %>
11
+ <%= render partial: "form", layout: dialog_request? ? "dialog" : "layout" %>
12
12
  <% end %>