administrate 0.9.0 → 0.14.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.
Files changed (113) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/administrate/components/{has_many_form.js → associative.js} +1 -0
  3. data/app/assets/javascripts/administrate/components/date_time_picker.js +10 -2
  4. data/app/assets/javascripts/administrate/components/table.js +1 -1
  5. data/app/assets/stylesheets/administrate/base/_tables.scss +3 -0
  6. data/app/assets/stylesheets/administrate/base/_typography.scss +1 -1
  7. data/app/assets/stylesheets/administrate/components/_attributes.scss +1 -1
  8. data/app/assets/stylesheets/administrate/components/_buttons.scss +8 -0
  9. data/app/assets/stylesheets/administrate/components/_cells.scss +2 -0
  10. data/app/assets/stylesheets/administrate/components/_field-unit.scss +13 -4
  11. data/app/assets/stylesheets/administrate/components/_flashes.scss +0 -8
  12. data/app/assets/stylesheets/administrate/components/_navigation.scss +2 -3
  13. data/app/assets/stylesheets/administrate/library/_variables.scss +10 -8
  14. data/app/controllers/administrate/application_controller.rb +42 -13
  15. data/app/controllers/concerns/administrate/punditize.rb +3 -3
  16. data/app/helpers/administrate/application_helper.rb +59 -14
  17. data/app/views/administrate/application/_collection.html.erb +7 -6
  18. data/app/views/administrate/application/_flashes.html.erb +1 -1
  19. data/app/views/administrate/application/_form.html.erb +2 -2
  20. data/app/views/administrate/application/{_icons.erb → _icons.html.erb} +0 -0
  21. data/app/views/administrate/application/_navigation.html.erb +5 -3
  22. data/app/views/administrate/application/index.html.erb +2 -0
  23. data/app/views/administrate/application/show.html.erb +1 -1
  24. data/app/views/fields/belongs_to/_index.html.erb +1 -1
  25. data/app/views/fields/belongs_to/_show.html.erb +1 -1
  26. data/app/views/fields/date/_form.html.erb +24 -0
  27. data/app/views/fields/date/_index.html.erb +21 -0
  28. data/app/views/fields/date/_show.html.erb +21 -0
  29. data/app/views/fields/date_time/_form.html.erb +1 -1
  30. data/app/views/fields/date_time/_index.html.erb +1 -1
  31. data/app/views/fields/has_many/_form.html.erb +2 -2
  32. data/app/views/fields/has_many/_show.html.erb +8 -5
  33. data/app/views/fields/has_one/_form.html.erb +1 -1
  34. data/app/views/fields/password/_form.html.erb +23 -0
  35. data/app/views/fields/password/_index.html.erb +18 -0
  36. data/app/views/fields/password/_show.html.erb +18 -0
  37. data/app/views/fields/polymorphic/_form.html.erb +0 -3
  38. data/app/views/fields/select/_form.html.erb +22 -10
  39. data/app/views/fields/string/_show.html.erb +2 -2
  40. data/app/views/fields/text/_show.html.erb +2 -3
  41. data/app/views/fields/time/_form.html.erb +23 -0
  42. data/app/views/fields/time/_index.html.erb +17 -0
  43. data/app/views/fields/time/_show.html.erb +17 -0
  44. data/app/views/fields/url/_form.html.erb +23 -0
  45. data/app/views/fields/url/_index.html.erb +20 -0
  46. data/app/views/fields/url/_show.html.erb +20 -0
  47. data/app/views/layouts/administrate/application.html.erb +1 -1
  48. data/config/locales/administrate.ar.yml +2 -0
  49. data/config/locales/administrate.bs.yml +2 -0
  50. data/config/locales/administrate.ca.yml +2 -0
  51. data/config/locales/administrate.da.yml +2 -0
  52. data/config/locales/administrate.de.yml +2 -0
  53. data/config/locales/administrate.en.yml +2 -0
  54. data/config/locales/administrate.es.yml +3 -1
  55. data/config/locales/administrate.fr.yml +2 -0
  56. data/config/locales/administrate.id.yml +30 -0
  57. data/config/locales/administrate.it.yml +2 -0
  58. data/config/locales/administrate.ja.yml +4 -2
  59. data/config/locales/administrate.ko.yml +12 -10
  60. data/config/locales/administrate.nl.yml +3 -1
  61. data/config/locales/administrate.pl.yml +2 -0
  62. data/config/locales/administrate.pt-BR.yml +2 -0
  63. data/config/locales/administrate.pt.yml +2 -0
  64. data/config/locales/administrate.ru.yml +4 -2
  65. data/config/locales/administrate.sq.yml +30 -0
  66. data/config/locales/administrate.sv.yml +2 -0
  67. data/config/locales/administrate.uk.yml +2 -0
  68. data/config/locales/administrate.vi.yml +2 -0
  69. data/config/locales/administrate.zh-CN.yml +4 -2
  70. data/config/locales/administrate.zh-TW.yml +6 -4
  71. data/docs/adding_controllers_without_related_model.md +36 -0
  72. data/docs/adding_custom_field_types.md +3 -1
  73. data/docs/authentication.md +3 -1
  74. data/docs/authorization.md +5 -3
  75. data/docs/contributing.md +1 -0
  76. data/docs/customizing_attribute_partials.md +5 -2
  77. data/docs/customizing_controller_actions.md +32 -2
  78. data/docs/customizing_dashboards.md +103 -13
  79. data/docs/customizing_page_views.md +23 -5
  80. data/docs/getting_started.md +22 -51
  81. data/docs/rails_api.md +45 -0
  82. data/lib/administrate/base_dashboard.rb +33 -8
  83. data/lib/administrate/custom_dashboard.rb +15 -0
  84. data/lib/administrate/engine.rb +1 -1
  85. data/lib/administrate/field/associative.rb +5 -5
  86. data/lib/administrate/field/base.rb +13 -13
  87. data/lib/administrate/field/belongs_to.rb +3 -1
  88. data/lib/administrate/field/date.rb +20 -0
  89. data/lib/administrate/field/date_time.rb +1 -1
  90. data/lib/administrate/field/deferred.rb +19 -0
  91. data/lib/administrate/field/has_many.rb +16 -9
  92. data/lib/administrate/field/has_one.rb +7 -7
  93. data/lib/administrate/field/password.rb +25 -0
  94. data/lib/administrate/field/polymorphic.rb +6 -6
  95. data/lib/administrate/field/select.rb +6 -1
  96. data/lib/administrate/field/time.rb +8 -0
  97. data/lib/administrate/field/url.rb +21 -0
  98. data/lib/administrate/namespace.rb +5 -1
  99. data/lib/administrate/order.rb +17 -7
  100. data/lib/administrate/page/base.rb +9 -3
  101. data/lib/administrate/page/collection.rb +5 -1
  102. data/lib/administrate/page/form.rb +1 -1
  103. data/lib/administrate/search.rb +126 -11
  104. data/lib/administrate/version.rb +1 -1
  105. data/lib/administrate/view_generator.rb +2 -2
  106. data/lib/generators/administrate/dashboard/dashboard_generator.rb +19 -6
  107. data/lib/generators/administrate/dashboard/templates/controller.rb.erb +33 -8
  108. data/lib/generators/administrate/dashboard/templates/dashboard.rb.erb +18 -6
  109. data/lib/generators/administrate/install/templates/application_controller.rb.erb +3 -3
  110. data/lib/generators/administrate/routes/routes_generator.rb +18 -13
  111. data/lib/generators/administrate/views/layout_generator.rb +1 -0
  112. metadata +47 -31
  113. data/config/secrets.yml +0 -14
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 200650aa4703202324342f17c6e1bce7642309664b28149e3aa5763d708af7cf
4
- data.tar.gz: 2b49177bd91bc20d1c5ffcb15fb33497339163e5058e24c39d82ef7fba6bdae9
3
+ metadata.gz: e8120deb0ddc3a88302230382298ce39c25d60e4effca6336787016c46024d91
4
+ data.tar.gz: ad6262c38fca6d8be885d8687db7b02444da05c751c8dcb25a71d7a292d43f05
5
5
  SHA512:
6
- metadata.gz: 56aa3cfb03420e71ee5ce158e3ce2d98b04a2038d8322b84dcddf4ebca67e27c599806d58d61d8f7c2d39f1bec4a723ac47f2157e73ae54df0e7249e6d37a9fd
7
- data.tar.gz: 6856dcf40b1cabea4b46e580f1379e07a79fca813040c39ae7e5018e1fb2a0c55e62ed4940872f5a28b983f762a276808b47d3954593660fd81a170f01ddf749
6
+ metadata.gz: e6bfde68398c548cfe04665c21c5e44fd8f659c404ddfcb141c5b358396cb6d0ca1c087b459a322553ff9dfeb195f033d817829d7a84bc80024004f1390faf5c
7
+ data.tar.gz: 794416e6cc50fadef9674c2fcb5316be67e7523d19c31431dfe3f80165a5355f3ce12019aad78681b6f5ede71797f3b3bab9b911236e8f3231bd0fcdacd15bc2
@@ -1,3 +1,4 @@
1
1
  $(function() {
2
+ $('.field-unit--belongs-to select').selectize({});
2
3
  $(".field-unit--has-many select").selectize({});
3
4
  });
@@ -1,6 +1,14 @@
1
1
  $(function () {
2
- $(".datetimepicker").datetimepicker({
2
+ $('[data-type="time"]').datetimepicker({
3
3
  debug: false,
4
- format: "YYYY-MM-DD HH:mm:ss",
4
+ format: 'HH:mm:ss',
5
+ });
6
+ $('[data-type="datetime"]').datetimepicker({
7
+ debug: false,
8
+ format: 'YYYY-MM-DD HH:mm:ss',
9
+ });
10
+ $('[data-type="date"]').datetimepicker({
11
+ debug: false,
12
+ format: 'YYYY-MM-DD',
5
13
  });
6
14
  });
@@ -13,7 +13,7 @@ $(function() {
13
13
  var dataUrl = $(event.target).closest("tr").data("url");
14
14
  var selection = window.getSelection().toString();
15
15
  if (selection.length === 0 && dataUrl) {
16
- window.location = dataUrl;
16
+ window.location = window.location.protocol + '//' + window.location.host + dataUrl;
17
17
  }
18
18
  }
19
19
  };
@@ -21,6 +21,9 @@ tr {
21
21
  tbody tr {
22
22
  &:hover {
23
23
  background-color: $base-background-color;
24
+ }
25
+
26
+ [role=link] {
24
27
  cursor: pointer;
25
28
  }
26
29
 
@@ -23,7 +23,7 @@ p {
23
23
 
24
24
  a {
25
25
  color: $action-color;
26
- text-decoration-skip: ink;
26
+ text-decoration-skip-ink: auto;
27
27
  transition: color $base-duration $base-timing;
28
28
 
29
29
  &:hover {
@@ -3,7 +3,7 @@
3
3
  clear: left;
4
4
  float: left;
5
5
  margin-bottom: $base-spacing;
6
- margin-top: 0;
6
+ margin-top: 0.25em;
7
7
  text-align: right;
8
8
  width: calc(15% - 1rem);
9
9
  }
@@ -41,3 +41,11 @@ input[type="submit"],
41
41
  }
42
42
  }
43
43
  }
44
+
45
+ .button--alt {
46
+ background-color: transparent;
47
+ border: $base-border;
48
+ border-color: $blue;
49
+ color: $blue;
50
+ margin-bottom: $base-spacing;
51
+ }
@@ -1,4 +1,6 @@
1
1
  .cell-label {
2
+ padding-top: 0.15em;
3
+
2
4
  &:hover {
3
5
  a {
4
6
  color: $action-color;
@@ -17,20 +17,29 @@
17
17
  .field-unit__field {
18
18
  float: left;
19
19
  margin-left: 2rem;
20
- width: 45%;
20
+ max-width: 50rem;
21
+ width: 100%;
21
22
  }
22
23
 
23
24
  .field-unit--nested {
24
25
  border: $base-border;
25
26
  margin-left: 7.5%;
27
+ max-width: 60rem;
26
28
  padding: $small-spacing;
27
- width: 50%;
29
+ width: 100%;
28
30
 
29
31
  .field-unit__field {
30
- width: calc(75% - 1rem);
32
+ width: 100%;
31
33
  }
32
34
 
33
35
  .field-unit__label {
34
- width: calc(25% - 1rem);
36
+ width: 10rem;
37
+ }
38
+ }
39
+
40
+ .field-unit--required {
41
+ label::after {
42
+ color: $red;
43
+ content: " *";
35
44
  }
36
45
  }
@@ -1,11 +1,3 @@
1
- $base-spacing: 1.5em !default;
2
- $flashes: (
3
- "alert": #fff6bf,
4
- "error": #fbe3e4,
5
- "notice": #e5edf8,
6
- "success": #e6efc2,
7
- ) !default;
8
-
9
1
  @each $flash-type, $color in $flashes {
10
2
  .flash-#{$flash-type} {
11
3
  background-color: $color;
@@ -2,9 +2,8 @@ $_navigation-link-padding: 0.6em;
2
2
 
3
3
  .navigation {
4
4
  flex: 1 0 10rem;
5
- padding-bottom: $base-spacing;
6
- padding-right: calc(#{$base-spacing} - #{$_navigation-link-padding});
7
- padding-top: $base-spacing;
5
+ padding: $base-spacing;
6
+ padding-left: 0;
8
7
  }
9
8
 
10
9
  .navigation__link {
@@ -22,8 +22,10 @@ $black: #000 !default;
22
22
 
23
23
  $blue: #1976d2 !default;
24
24
  $red: #d32f2f !default;
25
- $light-yellow: #f0cd66 !default;
26
- $light-green: #4ab471 !default;
25
+ $light-yellow: #fff6bf !default;
26
+ $light-red: #fbe3e4 !default;
27
+ $light-green: #e6efc2 !default;
28
+ $light-blue: #e5edf8 !default;
27
29
 
28
30
  $grey-0: #f6f7f7 !default;
29
31
  $grey-1: #dfe0e1 !default;
@@ -47,12 +49,12 @@ $focus-outline: $focus-outline-width solid $focus-outline-color;
47
49
  $focus-outline-offset: 1px;
48
50
 
49
51
  // Flash Colors
50
- $flash-colors: (
51
- alert: $light-yellow,
52
- error: $red,
53
- notice: mix($white, $blue, 50%),
54
- success: $light-green
55
- );
52
+ $flashes: (
53
+ "alert": $light-yellow,
54
+ "error": $light-red,
55
+ "notice": $light-blue,
56
+ "success": $light-green
57
+ ) !default;
56
58
 
57
59
  // Border
58
60
  $base-border-color: $grey-1 !default;
@@ -7,7 +7,7 @@ module Administrate
7
7
  resources = Administrate::Search.new(scoped_resource,
8
8
  dashboard_class,
9
9
  search_term).run
10
- resources = resources.includes(*resource_includes) if resource_includes.any?
10
+ resources = apply_collection_includes(resources)
11
11
  resources = order.apply(resources)
12
12
  resources = resources.page(params[:page]).per(records_per_page)
13
13
  page = Administrate::Page::Collection.new(dashboard, order: order)
@@ -16,7 +16,7 @@ module Administrate
16
16
  resources: resources,
17
17
  search_term: search_term,
18
18
  page: page,
19
- show_search_bar: show_search_bar?
19
+ show_search_bar: show_search_bar?,
20
20
  }
21
21
  end
22
22
 
@@ -27,7 +27,7 @@ module Administrate
27
27
  end
28
28
 
29
29
  def new
30
- resource = resource_class.new
30
+ resource = new_resource
31
31
  authorize_resource(resource)
32
32
  render locals: {
33
33
  page: Administrate::Page::Form.new(dashboard, resource),
@@ -70,8 +70,11 @@ module Administrate
70
70
  end
71
71
 
72
72
  def destroy
73
- requested_resource.destroy
74
- flash[:notice] = translate_with_resource("destroy.success")
73
+ if requested_resource.destroy
74
+ flash[:notice] = translate_with_resource("destroy.success")
75
+ else
76
+ flash[:error] = requested_resource.errors.full_messages.join("<br/>")
77
+ end
75
78
  redirect_to action: :index
76
79
  end
77
80
 
@@ -98,15 +101,37 @@ module Administrate
98
101
  end
99
102
 
100
103
  def order
101
- @_order ||= Administrate::Order.new(params[:order], params[:direction])
104
+ @order ||= Administrate::Order.new(sorting_attribute, sorting_direction)
105
+ end
106
+
107
+ def sorting_attribute
108
+ params.fetch(resource_name, {}).fetch(
109
+ :order,
110
+ default_sorting_attribute,
111
+ )
112
+ end
113
+
114
+ def default_sorting_attribute
115
+ nil
116
+ end
117
+
118
+ def sorting_direction
119
+ params.fetch(resource_name, {}).fetch(
120
+ :direction,
121
+ default_sorting_direction,
122
+ )
123
+ end
124
+
125
+ def default_sorting_direction
126
+ nil
102
127
  end
103
128
 
104
129
  def dashboard
105
- @_dashboard ||= dashboard_class.new
130
+ @dashboard ||= dashboard_class.new
106
131
  end
107
132
 
108
133
  def requested_resource
109
- @_requested_resource ||= find_resource(params[:id]).tap do |resource|
134
+ @requested_resource ||= find_resource(params[:id]).tap do |resource|
110
135
  authorize_resource(resource)
111
136
  end
112
137
  end
@@ -119,8 +144,10 @@ module Administrate
119
144
  resource_class.default_scoped
120
145
  end
121
146
 
122
- def resource_includes
123
- dashboard.association_includes
147
+ def apply_collection_includes(relation)
148
+ resource_includes = dashboard.collection_includes
149
+ return relation if resource_includes.empty?
150
+ relation.includes(*resource_includes)
124
151
  end
125
152
 
126
153
  def resource_params
@@ -136,6 +163,8 @@ module Administrate
136
163
  else
137
164
  raise "Unrecognised param data: #{data.inspect}"
138
165
  end
166
+ elsif data.is_a?(ActionController::Parameters)
167
+ data.transform_values { |v| read_param_value(v) }
139
168
  else
140
169
  data
141
170
  end
@@ -147,7 +176,7 @@ module Administrate
147
176
  helper_method :resource_name
148
177
 
149
178
  def resource_resolver
150
- @_resource_resolver ||=
179
+ @resource_resolver ||=
151
180
  Administrate::ResourceResolver.new(controller_path)
152
181
  end
153
182
 
@@ -160,11 +189,11 @@ module Administrate
160
189
 
161
190
  def show_search_bar?
162
191
  dashboard.attribute_types_for(
163
- dashboard.collection_attributes
192
+ dashboard.all_attributes,
164
193
  ).any? { |_name, attribute| attribute.searchable? }
165
194
  end
166
195
 
167
- def show_action?(action, resource)
196
+ def show_action?(_action, _resource)
168
197
  true
169
198
  end
170
199
  helper_method :show_action?
@@ -1,6 +1,6 @@
1
- if Object.const_defined?("Pundit")
2
- module Administrate
3
- module Punditize
1
+ module Administrate
2
+ module Punditize
3
+ if Object.const_defined?("Pundit")
4
4
  extend ActiveSupport::Concern
5
5
  include Pundit
6
6
 
@@ -2,22 +2,52 @@ module Administrate
2
2
  module ApplicationHelper
3
3
  PLURAL_MANY_COUNT = 2.1
4
4
 
5
+ def application_title
6
+ if Rails::VERSION::MAJOR <= 5
7
+ Rails.application.class.parent_name.titlecase
8
+ else
9
+ Rails.application.class.module_parent_name.titlecase
10
+ end
11
+ end
12
+
5
13
  def render_field(field, locals = {})
6
- locals.merge!(field: field)
14
+ locals[:field] = field
7
15
  render locals: locals, partial: field.to_partial_path
8
16
  end
9
17
 
10
- def class_from_resource(resource_name)
11
- resource_name.to_s.classify.constantize
18
+ def requireness(field)
19
+ required_field?(field) ? "required" : "optional"
20
+ end
21
+
22
+ def required_field?(field)
23
+ has_presence_validator?(field.resource.class, field.attribute)
24
+ end
25
+
26
+ def has_presence_validator?(resource_class, field_name)
27
+ validators_on(resource_class, field_name).
28
+ any? { |v| v.class == ActiveRecord::Validations::PresenceValidator }
29
+ end
30
+
31
+ def validators_on(resource_class, field_name)
32
+ return [] unless resource_class.respond_to?(:validators_on)
33
+
34
+ resource_class.validators_on(field_name)
35
+ end
36
+
37
+ def dashboard_from_resource(resource_name)
38
+ "#{resource_name.to_s.singularize}_dashboard".classify.constantize
39
+ end
40
+
41
+ def model_from_resource(resource_name)
42
+ dashboard = dashboard_from_resource(resource_name)
43
+ dashboard.try(:model) || resource_name.to_sym
12
44
  end
13
45
 
14
46
  def display_resource_name(resource_name)
15
- class_from_resource(resource_name).
16
- model_name.
17
- human(
18
- count: PLURAL_MANY_COUNT,
19
- default: resource_name.to_s.pluralize.titleize,
20
- )
47
+ dashboard_from_resource(resource_name).resource_name(
48
+ count: PLURAL_MANY_COUNT,
49
+ default: default_resource_name(resource_name),
50
+ )
21
51
  end
22
52
 
23
53
  def sort_order(order)
@@ -28,16 +58,31 @@ module Administrate
28
58
  end
29
59
  end
30
60
 
31
- def resource_index_route_key(resource_name)
32
- ActiveModel::Naming.route_key(class_from_resource(resource_name))
61
+ def resource_index_route(resource_name)
62
+ url_for(
63
+ action: "index",
64
+ controller: "/#{namespace}/#{resource_name}",
65
+ )
33
66
  end
34
67
 
35
- def sanitized_order_params
36
- params.permit(:search, :id, :order, :page, :per_page, :direction, :orders)
68
+ def sanitized_order_params(page, current_field_name)
69
+ collection_names = page.item_includes + [current_field_name]
70
+ association_params = collection_names.map do |assoc_name|
71
+ { assoc_name => %i[order direction page per_page] }
72
+ end
73
+ params.permit(:search, :id, :page, :per_page, association_params)
37
74
  end
38
75
 
39
76
  def clear_search_params
40
- params.except(:search, :page).permit(:order, :direction, :per_page)
77
+ params.except(:search, :page).permit(
78
+ :per_page, resource_name => %i[order direction]
79
+ )
80
+ end
81
+
82
+ private
83
+
84
+ def default_resource_name(resource_name)
85
+ resource_name.to_s.pluralize.gsub("/", "_").titleize
41
86
  end
42
87
  end
43
88
  end
@@ -28,14 +28,13 @@ to display a collection of resources in an HTML table.
28
28
  scope="col"
29
29
  role="columnheader"
30
30
  aria-sort="<%= sort_order(collection_presenter.ordered_html_class(attr_name)) %>">
31
- <%= link_to(sanitized_order_params.merge(
32
- collection_presenter.order_params_for(attr_name)
31
+ <%= link_to(sanitized_order_params(page, collection_field_name).merge(
32
+ collection_presenter.order_params_for(attr_name, key: collection_field_name)
33
33
  )) do %>
34
34
  <%= t(
35
35
  "helpers.label.#{collection_presenter.resource_name}.#{attr_name}",
36
36
  default: attr_name.to_s,
37
37
  ).titleize %>
38
-
39
38
  <% if collection_presenter.ordered_by?(attr_name) %>
40
39
  <span class="cell-label__sort-indicator cell-label__sort-indicator--<%= collection_presenter.ordered_html_class(attr_name) %>">
41
40
  <svg aria-hidden="true">
@@ -56,19 +55,21 @@ to display a collection of resources in an HTML table.
56
55
  <tbody>
57
56
  <% resources.each do |resource| %>
58
57
  <tr class="js-table-row"
59
- tabindex="0"
60
- <% if valid_action? :show, collection_presenter.resource_name %>
61
- <%= %(role=link data-url=#{polymorphic_path([namespace, resource])}) %>
58
+ <% if show_action? :show, resource %>
59
+ <%= %(tabindex=0 role=link data-url=#{polymorphic_path([namespace, resource])}) %>
62
60
  <% end %>
63
61
  >
64
62
  <% collection_presenter.attributes_for(resource).each do |attribute| %>
65
63
  <td class="cell-data cell-data--<%= attribute.html_class %>">
66
64
  <% if show_action? :show, resource -%>
67
65
  <a href="<%= polymorphic_path([namespace, resource]) -%>"
66
+ tabindex="-1"
68
67
  class="action-show"
69
68
  >
70
69
  <%= render_field attribute %>
71
70
  </a>
71
+ <% else %>
72
+ <%= render_field attribute %>
72
73
  <% end -%>
73
74
  </td>
74
75
  <% end %>