semantic-administrate 0.1.1 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/administrate/components/date_time_picker.js +5 -1
  3. data/app/controllers/administrate/application_controller.rb +20 -12
  4. data/app/helpers/administrate/application_helper.rb +9 -3
  5. data/app/views/administrate/application/_collection.html.erb +2 -3
  6. data/app/views/administrate/application/_flashes.html.erb +1 -1
  7. data/app/views/administrate/application/index.html.erb +2 -0
  8. data/app/views/administrate/application/show.html.erb +1 -1
  9. data/app/views/fields/belongs_to/_index.html.erb +1 -1
  10. data/app/views/fields/belongs_to/_show.html.erb +1 -1
  11. data/app/views/fields/date_time/_form.html.erb +1 -1
  12. data/app/views/fields/date_time/_index.html.erb +1 -1
  13. data/app/views/fields/has_many/_form.html.erb +2 -2
  14. data/app/views/fields/has_many/_show.html.erb +8 -5
  15. data/app/views/fields/has_one/_form.html.erb +1 -1
  16. data/app/views/fields/password/_form.html.erb +23 -0
  17. data/app/views/fields/password/_index.html.erb +18 -0
  18. data/app/views/fields/password/_show.html.erb +18 -0
  19. data/app/views/fields/polymorphic/_form.html.erb +0 -3
  20. data/app/views/fields/time/_form.html.erb +22 -0
  21. data/app/views/fields/time/_index.html.erb +17 -0
  22. data/app/views/fields/time/_show.html.erb +17 -0
  23. data/config/locales/administrate.al.yml +28 -0
  24. data/config/locales/administrate.id.yml +28 -0
  25. data/config/locales/administrate.ja.yml +2 -2
  26. data/config/locales/administrate.ru.yml +2 -2
  27. data/config/locales/administrate.zh-TW.yml +4 -4
  28. data/docs/customizing_dashboards.md +71 -5
  29. data/docs/customizing_page_views.md +5 -1
  30. data/lib/administrate/base_dashboard.rb +7 -1
  31. data/lib/administrate/field/associative.rb +4 -4
  32. data/lib/administrate/field/belongs_to.rb +3 -1
  33. data/lib/administrate/field/date_time.rb +1 -1
  34. data/lib/administrate/field/deferred.rb +4 -0
  35. data/lib/administrate/field/has_many.rb +15 -8
  36. data/lib/administrate/field/password.rb +25 -0
  37. data/lib/administrate/field/polymorphic.rb +1 -1
  38. data/lib/administrate/field/time.rb +8 -0
  39. data/lib/administrate/namespace.rb +1 -1
  40. data/lib/administrate/order.rb +3 -1
  41. data/lib/administrate/page/base.rb +4 -0
  42. data/lib/administrate/page/collection.rb +5 -1
  43. data/lib/administrate/search.rb +39 -5
  44. data/lib/administrate/version.rb +1 -1
  45. data/lib/generators/administrate/dashboard/dashboard_generator.rb +1 -1
  46. metadata +18 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2123d47601bf83f82794fe639a592c0be68130e8
4
- data.tar.gz: 4f57f44bea647c725247c42fb9f18e21825ff7bc
3
+ metadata.gz: b0ef87476dd9f2165cc5bb4bc0fc2fbf48f21600
4
+ data.tar.gz: 882284666a8830d2483fd92dbb9a2e1d31571dd7
5
5
  SHA512:
6
- metadata.gz: c52c71169aed4dad7ea08c9f1873bdefa22e0b14a9dd6940cac3aa56f42dd29472744c9ec82f23bc7c2d908d44ed7e95b262900a331384c2b38200d12c144c64
7
- data.tar.gz: be36d780bdd94b43d132468d6498f68e40dcff40e3d8642744c8f77886083559fa0f05f570cbe4a19a0b008b3796e3e7e880f6bedba1d8d0040036f28ffe7028
6
+ metadata.gz: f2007d097c22eaf8609641345735db8bac5b2ca475efe7fbe5aa862e7410d3ccf0f9c9ad5babf12e1eadf0397ad9868f98a219ef1ba84e7778316e5f049a8868
7
+ data.tar.gz: 3c915b462dac24879e61935eedc02bd0672f3d1db3d54c0e04b42b6a83a006d7541a3f5319ed26cc34f6f50d436abbd4cfb87fc6f230665f6999e639e0874a48
@@ -1,5 +1,9 @@
1
1
  $(function () {
2
- $(".datetimepicker").datetimepicker({
2
+ $('[data-type="time"]').datetimepicker({
3
+ debug: false,
4
+ format: "HH:mm:ss",
5
+ });
6
+ $('[data-type="datetime"]').datetimepicker({
3
7
  debug: false,
4
8
  format: "YYYY-MM-DD HH:mm:ss",
5
9
  });
@@ -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_resource_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
 
@@ -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,18 @@ 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(
105
+ params.fetch(resource_name, {}).fetch(:order, nil),
106
+ params.fetch(resource_name, {}).fetch(:direction, nil),
107
+ )
102
108
  end
103
109
 
104
110
  def dashboard
105
- @_dashboard ||= dashboard_class.new
111
+ @dashboard ||= dashboard_class.new
106
112
  end
107
113
 
108
114
  def requested_resource
109
- @_requested_resource ||= find_resource(params[:id]).tap do |resource|
115
+ @requested_resource ||= find_resource(params[:id]).tap do |resource|
110
116
  authorize_resource(resource)
111
117
  end
112
118
  end
@@ -119,8 +125,10 @@ module Administrate
119
125
  resource_class.default_scoped
120
126
  end
121
127
 
122
- def resource_includes
123
- dashboard.association_includes
128
+ def apply_resource_includes(relation)
129
+ resource_includes = dashboard.association_includes
130
+ return relation if resource_includes.empty?
131
+ relation.includes(*resource_includes)
124
132
  end
125
133
 
126
134
  def resource_params
@@ -147,7 +155,7 @@ module Administrate
147
155
  helper_method :resource_name
148
156
 
149
157
  def resource_resolver
150
- @_resource_resolver ||=
158
+ @resource_resolver ||=
151
159
  Administrate::ResourceResolver.new(controller_path)
152
160
  end
153
161
 
@@ -160,11 +168,11 @@ module Administrate
160
168
 
161
169
  def show_search_bar?
162
170
  dashboard.attribute_types_for(
163
- dashboard.collection_attributes
171
+ dashboard.all_attributes,
164
172
  ).any? { |_name, attribute| attribute.searchable? }
165
173
  end
166
174
 
167
- def show_action?(action, resource)
175
+ def show_action?(_action, _resource)
168
176
  true
169
177
  end
170
178
  helper_method :show_action?
@@ -40,12 +40,18 @@ module Administrate
40
40
  ActiveModel::Naming.route_key(class_from_resource(resource_name))
41
41
  end
42
42
 
43
- def sanitized_order_params
44
- params.permit(:search, :id, :order, :page, :per_page, :direction, :orders)
43
+ def sanitized_order_params(page, current_field_name)
44
+ collection_names = page.association_includes + [current_field_name]
45
+ association_params = collection_names.map do |assoc_name|
46
+ { assoc_name => %i[order direction page per_page] }
47
+ end
48
+ params.permit(:search, :id, :page, :per_page, association_params)
45
49
  end
46
50
 
47
51
  def clear_search_params
48
- params.except(:search, :page).permit(:order, :direction, :per_page)
52
+ params.except(:search, :page).permit(
53
+ :per_page, resource_name => %i[order direction]
54
+ )
49
55
  end
50
56
  end
51
57
  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">
@@ -14,7 +14,7 @@ This partial renders flash messages on every page.
14
14
  <% if flash.any? %>
15
15
  <div class="flashes">
16
16
  <% flash.each do |key, value| -%>
17
- <div class="flash flash-<%= key %>"><%= value %></div>
17
+ <div class="flash flash-<%= key %>"><%= value.html_safe %></div>
18
18
  <% end -%>
19
19
  </div>
20
20
  <% end %>
@@ -58,6 +58,8 @@ It renders the `_table` partial to display details about the resources.
58
58
  <%= render(
59
59
  "collection",
60
60
  collection_presenter: page,
61
+ collection_field_name: resource_name,
62
+ page: page,
61
63
  resources: resources,
62
64
  table_title: "page-title"
63
65
  ) %>
@@ -43,7 +43,7 @@ as well as a link to its edit page.
43
43
  </dt>
44
44
 
45
45
  <dd class="attribute-data attribute-data--<%=attribute.html_class%>"
46
- ><%= render_field attribute %></dd>
46
+ ><%= render_field attribute, page: page %></dd>
47
47
  <% end %>
48
48
  </dl>
49
49
  </section>
@@ -16,7 +16,7 @@ By default, the relationship is rendered as a link to the associated object.
16
16
  %>
17
17
 
18
18
  <% if field.data %>
19
- <% if valid_action?(:show, field.attribute) %>
19
+ <% if valid_action?(:show, field.associated_class) %>
20
20
  <%= link_to(
21
21
  field.display_associated_resource,
22
22
  [namespace, field.data],
@@ -16,7 +16,7 @@ By default, the relationship is rendered as a link to the associated object.
16
16
  %>
17
17
 
18
18
  <% if field.data %>
19
- <% if valid_action?(:show, field.attribute) %>
19
+ <% if valid_action?(:show, field.associated_class) %>
20
20
  <%= link_to(
21
21
  field.display_associated_resource,
22
22
  [namespace, field.data],
@@ -20,5 +20,5 @@ By default, the input is a text field that is augmented with [DateTimePicker].
20
20
  <%= f.label field.attribute %>
21
21
  </div>
22
22
  <div class="field-unit__field">
23
- <%= f.text_field field.attribute, class: "datetimepicker" %>
23
+ <%= f.text_field field.attribute, data: { type: 'datetime' } %>
24
24
  </div>
@@ -17,5 +17,5 @@ as a localized date & time string.
17
17
  %>
18
18
 
19
19
  <% if field.data %>
20
- <%= field.date %>
20
+ <%= field.datetime %>
21
21
  <% end %>
@@ -1,7 +1,7 @@
1
1
  <%#
2
2
  # HasMany Form Partial
3
3
 
4
- This partial renders an input element for belongs_to relationships.
4
+ This partial renders an input element for has_many relationships.
5
5
  By default, the input is a collection select box
6
6
  that displays all possible records to associate with.
7
7
  The collection select box supports multiple inputs,
@@ -20,7 +20,7 @@ and is augmented with [Selectize].
20
20
  %>
21
21
 
22
22
  <div class="field-unit__label">
23
- <%= f.label field.attribute_key, field.attribute %>
23
+ <%= f.label field.attribute, for: "#{f.object_name}_#{field.attribute_key}" %>
24
24
  </div>
25
25
  <div class="field-unit__field">
26
26
  <%= f.select(field.attribute_key, nil, {}, multiple: true) do %>
@@ -19,15 +19,18 @@ from the associated resource class's dashboard.
19
19
  %>
20
20
 
21
21
  <% if field.resources.any? %>
22
+ <% order = field.order_from_params(params.fetch(field.name, {})) %>
23
+ <% page_number = params.fetch(field.name, {}).fetch(:page, nil) %>
22
24
  <%= render(
23
25
  "collection",
24
- collection_presenter: field.associated_collection,
25
- resources: field.resources(params[field.name]),
26
- table_title: field.name
26
+ collection_presenter: field.associated_collection(order),
27
+ collection_field_name: field.name,
28
+ page: page,
29
+ resources: field.resources(page_number, order),
30
+ table_title: field.name,
27
31
  ) %>
28
-
29
32
  <% if field.more_than_limit? %>
30
- <%= paginate field.resources(params[field.name]), param_name: "#{field.name}" %>
33
+ <%= paginate field.resources(page_number), param_name: "#{field.name}[page]" %>
31
34
  <% end %>
32
35
 
33
36
  <% else %>
@@ -18,7 +18,7 @@ The form will be rendered as nested_from to parent relationship.
18
18
 
19
19
  <%= f.fields_for field.attribute, field.data || field.nested_form.resource.class.new do |has_one_f| %>
20
20
  <fieldset class="field-unit--nested">
21
- <legend><%= field.nested_form.resource_name.titleize %></legend>
21
+ <legend><%= t "helpers.label.#{f.object_name}.#{field.nested_form.resource_name}", default: field.nested_form.resource_name.titleize %></legend>
22
22
  <% field.nested_form.attributes.each do |attribute| -%>
23
23
  <div class="field-unit field-unit--<%= attribute.html_class %>">
24
24
  <%= render_field attribute, f: has_one_f %>
@@ -0,0 +1,23 @@
1
+ <%#
2
+ # Password Form Partial
3
+
4
+ This partial renders an input element for a password attribute.
5
+ By default, the input is a password field.
6
+
7
+ ## Local variables:
8
+
9
+ - `f`:
10
+ A Rails form generator, used to help create the appropriate input fields.
11
+ - `field`:
12
+ An instance of [Administrate::Field::Password][1].
13
+ A wrapper around the Password.
14
+
15
+ [1]: http://www.rubydoc.info/gems/administrate/Administrate/Field/Password
16
+ %>
17
+
18
+ <div class="field-unit__label">
19
+ <%= f.label field.attribute %>
20
+ </div>
21
+ <div class="field-unit__field">
22
+ <%= f.password_field field.attribute, value: field.data %>
23
+ </div>
@@ -0,0 +1,18 @@
1
+ <%#
2
+ # Password Index Partial
3
+
4
+ This partial renders a password attribute
5
+ to be displayed on a resource's index page.
6
+
7
+ By default, the attribute is rendered as a truncated string.
8
+
9
+ ## Local variables:
10
+
11
+ - `field`:
12
+ An instance of [Administrate::Field::Password][1].
13
+ A wrapper around the Password.
14
+
15
+ [1]: http://www.rubydoc.info/gems/administrate/Administrate/Field/Password
16
+ %>
17
+
18
+ <%= field.truncate %>
@@ -0,0 +1,18 @@
1
+ <%#
2
+ # Password Show Partial
3
+
4
+ This partial renders a password attribute,
5
+ to be displayed on a resource's show page.
6
+
7
+ By default, the attribute is rendered as an truncate string.
8
+
9
+ ## Local variables:
10
+
11
+ - `field`:
12
+ An instance of [Administrate::Field::Password][1].
13
+ A wrapper around the Password.
14
+
15
+ [1]: http://www.rubydoc.info/gems/administrate/Administrate/Field/Password
16
+ %>
17
+
18
+ <%= field.truncate %>
@@ -3,9 +3,6 @@
3
3
 
4
4
  This partial renders an input element for polymorphic relationships.
5
5
 
6
- At the moment, polymorphic form fields are not supported,
7
- so this partial renders a message to that effect.
8
-
9
6
  ## Local variables:
10
7
 
11
8
  - `f`:
@@ -0,0 +1,22 @@
1
+ <%#
2
+ # Time Form Partial
3
+
4
+ This partial renders an input element for time attributes.
5
+ By default, the input is a select field for the time attributes.
6
+
7
+ ## Local variables:
8
+
9
+ - `f`:
10
+ A Rails form generator, used to help create the appropriate input fields.
11
+ - `field`:
12
+ An instance of [Administrate::Field::Time][1].
13
+ A wrapper around the tmie attributes pulled from the model.
14
+
15
+ %>
16
+
17
+ <div class="field-unit__label">
18
+ <%= f.label field.attribute %>
19
+ </div>
20
+ <div class="field-unit__field">
21
+ <%= f.text_field field.attribute, data: { type: 'time' } %>
22
+ </div>
@@ -0,0 +1,17 @@
1
+ <%#
2
+ # Time Index Partial
3
+
4
+ This partial renders an time attribute
5
+ to be displayed on a resource's index page.
6
+
7
+ By default, the attribute is rendered as a text tag.
8
+
9
+ ## Local variables:
10
+
11
+ - `field`:
12
+ An instance of [Administrate::Field::Time][1].
13
+ A wrapper around the time attributes pulled from the model.
14
+
15
+ %>
16
+
17
+ <%= field.data.strftime("%I:%M%p").to_s %>
@@ -0,0 +1,17 @@
1
+ <%#
2
+ # Time Show Partial
3
+
4
+ This partial renders an time attribute,
5
+ to be displayed on a resource's show page.
6
+
7
+ By default, the attribute is rendered as a text tag.
8
+
9
+ ## Local variables:
10
+
11
+ - `field`:
12
+ An instance of [Administrate::Field::Time][1].
13
+ A wrapper around the time attributes pulled from the model.
14
+
15
+ %>
16
+
17
+ <%= field.data.strftime("%I:%M%p").to_s %>
@@ -0,0 +1,28 @@
1
+ ---
2
+ al:
3
+ administrate:
4
+ actions:
5
+ confirm: A jeni te sigurtë?
6
+ destroy: Fshij
7
+ edit: Ndrysho
8
+ edit_resource: Ndrysho %{name}
9
+ show_resource: Trego %{name}
10
+ new_resource: Të re %{name}
11
+ back: Prapa
12
+ controller:
13
+ create:
14
+ success: "%{resource} është krijuar me sukses."
15
+ destroy:
16
+ success: "%{resource} është fshirë me sukses."
17
+ update:
18
+ success: "%{resource} është azhurnuar me sukses."
19
+ fields:
20
+ has_many:
21
+ more: Duke treguar %{count} nga %{total_count}
22
+ none: Asnjë
23
+ form:
24
+ error: gabim
25
+ errors: "%{pluralized_errors} nuk e lejoj %{resource_name} të ruhet:"
26
+ search:
27
+ clear: Pastro kërkimin
28
+ label: Kërko %{resource}
@@ -0,0 +1,28 @@
1
+ ---
2
+ id:
3
+ administrate:
4
+ actions:
5
+ confirm: Anda yakin?
6
+ destroy: Hapus
7
+ edit: Perbarui
8
+ edit_resource: Perbarui %{name}
9
+ show_resource: Tampilkan %{name}
10
+ new_resource: "%{name} baru"
11
+ back: Kembali
12
+ controller:
13
+ create:
14
+ success: "%{resource} telah berhasil dibuat."
15
+ destroy:
16
+ success: "%{resource} telah berhasil dihapus."
17
+ update:
18
+ success: "%{resource} telah berhasil diperbarui."
19
+ fields:
20
+ has_many:
21
+ more: Menampilkan %{count} dari %{total_count}
22
+ none: Kosong
23
+ form:
24
+ error: error
25
+ errors: "%{pluralized_errors} membuat %{resource_name} tidak bisa tersimpan:"
26
+ search:
27
+ clear: Kosongkan pencarian
28
+ label: Cari %{resource}
@@ -21,8 +21,8 @@ ja:
21
21
  more: "%{total_count} 件中 %{count} 件表示"
22
22
  none: データがありません
23
23
  form:
24
- error: error
25
- errors: "%{pluralized_errors} prohibited this %{resource_name} from being saved:"
24
+ error: エラー
25
+ errors: "%{pluralized_errors}のため%{resource_name}を保存できません。"
26
26
  search:
27
27
  clear: 検索をクリアする
28
28
  label: サーチ %{resource}
@@ -21,8 +21,8 @@ ru:
21
21
  more: "%{count} из %{total_count}"
22
22
  none: Нет
23
23
  form:
24
- error: error
25
- errors: "%{pluralized_errors} prohibited this %{resource_name} from being saved:"
24
+ error: Ошибка
25
+ errors: "При сохранении %{resource_name} произошли ошибки:"
26
26
  search:
27
27
  clear: Очистить поиск
28
28
  label: Поиск %{resource}
@@ -21,8 +21,8 @@ zh-TW:
21
21
  more: 顯示 %{total_count} 筆中的 %{count} 筆資料
22
22
  none: 無
23
23
  form:
24
- error: error
25
- errors: "%{pluralized_errors} prohibited this %{resource_name} from being saved:"
24
+ error: 錯誤
25
+ errors: "%{pluralized_errors} 導致此 %{resource_name} 不能被儲存:"
26
26
  search:
27
- clear: 清除搜索
28
- label: 搜索 %{resource}
27
+ clear: 清除搜尋
28
+ label: 搜尋 %{resource}
@@ -10,7 +10,7 @@ require "administrate/dashboard/base"
10
10
 
11
11
  class CustomerDashboard < Administrate::Dashboard::Base
12
12
  ATTRIBUTE_TYPES = {
13
- id: Field::Integer,
13
+ id: Field::Number,
14
14
  name: Field::String,
15
15
  email: Field::String,
16
16
  created_at: Field::DateTime,
@@ -62,6 +62,7 @@ specify, including:
62
62
  - `Field::Select`
63
63
  - `Field::String`
64
64
  - `Field::Text`
65
+ - `Field::Password`
65
66
 
66
67
  ## Customizing Fields
67
68
 
@@ -80,6 +81,30 @@ than one column. e.g.: `"name, email DESC"`.
80
81
  `:foreign_key` - Specifies the name of the foreign key directly.
81
82
  Defaults to `:#{attribute}_id`.
82
83
 
84
+ `:scope` - Specifies a custom scope inside a callable. Useful for preloading.
85
+ Example: `.with_options(scope: -> { MyModel.includes(:rel).limit(5) })`
86
+
87
+ `:class_name` - Specifies the name of the associated class.
88
+ Defaults to `:#{attribute}.to_s.singularize.camelcase`.
89
+
90
+ `:searchable` - Specify if the attribute should be considered when searching.
91
+ Default is `false`.
92
+
93
+ `searchable_field` - Specify which column to use on the search, only applies
94
+ if `searchable` is `true`
95
+
96
+ For example:
97
+
98
+ ```ruby
99
+ country: Field::BelongsTo.with_options(
100
+ searchable: true,
101
+ seachable_field: 'name',
102
+ )
103
+ ```
104
+
105
+ with this, you will be able to search through the column `name` from the
106
+ association `belongs_to :country`, from your model.
107
+
83
108
  **Field::HasMany**
84
109
 
85
110
  `:limit` - Set the number of resources to display in the show view. Default is
@@ -93,8 +118,38 @@ Defaults to `:#{attribute}_id`.
93
118
 
94
119
  `:foreign_key` - Specifies the name of the foreign key directly. Defaults to `:#{attribute}_id`
95
120
 
121
+ `:class_name` - Specifies the name of the associated class.
122
+ Defaults to `:#{attribute}.to_s.singularize.camelcase`.
123
+
124
+ **Field::HasOne**
125
+
126
+ `:class_name` - Specifies the name of the associated class.
127
+ Defaults to `:#{attribute}.to_s.singularize.camelcase`.
128
+
129
+ `:searchable` - Specify if the attribute should be considered when searching.
130
+ Default is `false`.
131
+
132
+ `searchable_field` - Specify which column to use on the search, only applies if
133
+ `searchable` is `true`
134
+
135
+ For example:
136
+
137
+ ```ruby
138
+ cities: Field::HasMany.with_options(
139
+ searchable: true,
140
+ searchable_field: 'name',
141
+ )
142
+ ```
143
+
144
+ with this, you will be able to search through the column `name` from the
145
+ association `has_many :cities`, from your model.
146
+
96
147
  **Field::Number**
97
148
 
149
+ `:searchable` - Specify if the attribute should be considered when searching.
150
+ Note that currently number fields are searched like text, which may yield
151
+ more results than expected. Default is `false`.
152
+
98
153
  `:decimals` - Set the number of decimals to display. Defaults to `0`.
99
154
 
100
155
  `:prefix` - Prefixes the number with a string. Defaults to `""`.
@@ -137,7 +192,7 @@ in.
137
192
 
138
193
  **Field::Select**
139
194
 
140
- `:collection` - Specify the array or range to select from. Defaults to `[]`.
195
+ `:collection` - Specify the array or range to select from. Defaults to `[]`.
141
196
 
142
197
  `:searchable` - Specify if the attribute should be considered when searching.
143
198
  Default is `true`.
@@ -158,6 +213,17 @@ Default is `false`.
158
213
  `:truncate` - Set the number of characters to display in the index view.
159
214
  Defaults to `50`.
160
215
 
216
+ **Field::Password**
217
+
218
+ `:searchable` - Specify if the attribute should be considered when searching.
219
+ Default is `false`.
220
+
221
+ `:truncate` - Set the number of characters to display in the views.
222
+ Defaults to `50`.
223
+
224
+ `:character` - Set the replace character.
225
+ Defaults to `•`.
226
+
161
227
  ### Defining Labels
162
228
 
163
229
  To change the user-facing label for an attribute,
@@ -180,11 +246,11 @@ Add this method to the dashboard for Users.
180
246
  Use whatever attribute or method you like.
181
247
  Example for *user*:
182
248
 
183
- ````ruby
249
+ ```ruby
184
250
  def display_resource(user)
185
251
  user.name
186
252
  end
187
- ````
253
+ ```
188
254
 
189
255
  [define your own]: /adding_custom_field_types
190
256
 
@@ -196,7 +262,7 @@ en:
196
262
  models:
197
263
  customer:
198
264
  one: Happy Customer
199
- others: Happy Customers
265
+ other: Happy Customers
200
266
  ```
201
267
 
202
268
  ## Customizing Actions
@@ -67,7 +67,7 @@ and will leave the show pages for other resources unchanged.
67
67
  ## Customizing layouts
68
68
 
69
69
  Many developers need to customize the layouts of their admin dashboard.
70
- It's so easy that pass in the "layout" key word to the view generators.
70
+ It's as easy as passing in the "layout" keyword to the view generators.
71
71
 
72
72
  ```bash
73
73
  rails generate administrate:views:layout
@@ -75,4 +75,8 @@ rails generate administrate:views:layout
75
75
  # -> app/views/admin/application/_navigation.html.erb
76
76
  # -> app/views/admin/application/_javascript.html.erb
77
77
  # -> app/views/admin/application/_flashes.html.erb
78
+
79
+ rails generate administrate:views:navigation
80
+ # It only generates the sidebar partial
81
+ # -> app/views/admin/application/_navigation.html.erb
78
82
  ```
@@ -9,6 +9,8 @@ require "administrate/field/polymorphic"
9
9
  require "administrate/field/select"
10
10
  require "administrate/field/string"
11
11
  require "administrate/field/text"
12
+ require "administrate/field/time"
13
+ require "administrate/field/password"
12
14
 
13
15
  module Administrate
14
16
  class BaseDashboard
@@ -30,6 +32,10 @@ module Administrate
30
32
  end
31
33
  end
32
34
 
35
+ def all_attributes
36
+ attribute_types.keys
37
+ end
38
+
33
39
  def form_attributes
34
40
  self.class::FORM_ATTRIBUTES
35
41
  end
@@ -59,7 +65,7 @@ module Administrate
59
65
  field = self.class::ATTRIBUTE_TYPES[key]
60
66
 
61
67
  next key if association_classes.include?(field)
62
- key if association_classes.include?(field.try :deferred_class)
68
+ key if association_classes.include?(field.try(:deferred_class))
63
69
  end.compact
64
70
  end
65
71
 
@@ -7,16 +7,16 @@ module Administrate
7
7
  associated_dashboard.display_resource(data)
8
8
  end
9
9
 
10
+ def associated_class
11
+ associated_class_name.constantize
12
+ end
13
+
10
14
  protected
11
15
 
12
16
  def associated_dashboard
13
17
  "#{associated_class_name}Dashboard".constantize.new
14
18
  end
15
19
 
16
- def associated_class
17
- associated_class_name.constantize
18
- end
19
-
20
20
  def associated_class_name
21
21
  options.fetch(:class_name, attribute.to_s.singularize.camelcase)
22
22
  end
@@ -24,8 +24,10 @@ module Administrate
24
24
  private
25
25
 
26
26
  def candidate_resources
27
+ scope = options[:scope] ? options[:scope].call : associated_class.all
28
+
27
29
  order = options.delete(:order)
28
- order ? associated_class.order(order) : associated_class.all
30
+ order ? scope.reorder(order) : scope
29
31
  end
30
32
 
31
33
  def display_candidate_resource(resource)
@@ -25,7 +25,7 @@ module Administrate
25
25
  end
26
26
 
27
27
  def timezone
28
- options.fetch(:timezone, "UTC")
28
+ options.fetch(:timezone, ::Time.zone.name || "UTC")
29
29
  end
30
30
  end
31
31
  end
@@ -25,6 +25,10 @@ module Administrate
25
25
  options.fetch(:searchable, deferred_class.searchable?)
26
26
  end
27
27
 
28
+ def searchable_field
29
+ options.fetch(:searchable_field)
30
+ end
31
+
28
32
  def permitted_attribute(attr, _options = nil)
29
33
  options.fetch(:foreign_key,
30
34
  deferred_class.permitted_attribute(attr, options))
@@ -11,8 +11,8 @@ module Administrate
11
11
  { "#{attr.to_s.singularize}_ids".to_sym => [] }
12
12
  end
13
13
 
14
- def associated_collection
15
- Administrate::Page::Collection.new(associated_dashboard)
14
+ def associated_collection(order = self.order)
15
+ Administrate::Page::Collection.new(associated_dashboard, order: order)
16
16
  end
17
17
 
18
18
  def attribute_key
@@ -39,7 +39,7 @@ module Administrate
39
39
  self.class.permitted_attribute(attribute)
40
40
  end
41
41
 
42
- def resources(page = 1)
42
+ def resources(page = 1, order = self.order)
43
43
  resources = order.apply(data).page(page).per(limit)
44
44
  includes.any? ? resources.includes(*includes) : resources
45
45
  end
@@ -49,7 +49,18 @@ module Administrate
49
49
  end
50
50
 
51
51
  def data
52
- @data ||= associated_class.none
52
+ @data ||= associated_class.none
53
+ end
54
+
55
+ def order_from_params(params)
56
+ Administrate::Order.new(
57
+ params.fetch(:order, sort_by),
58
+ params.fetch(:direction, direction),
59
+ )
60
+ end
61
+
62
+ def order
63
+ @order ||= Administrate::Order.new(sort_by, direction)
53
64
  end
54
65
 
55
66
  private
@@ -71,10 +82,6 @@ module Administrate
71
82
  associated_dashboard.display_resource(resource)
72
83
  end
73
84
 
74
- def order
75
- @_order ||= Administrate::Order.new(sort_by, direction)
76
- end
77
-
78
85
  def sort_by
79
86
  options[:sort_by]
80
87
  end
@@ -0,0 +1,25 @@
1
+ require_relative "base"
2
+
3
+ module Administrate
4
+ module Field
5
+ class Password < Field::Base
6
+ def self.searchable?
7
+ false
8
+ end
9
+
10
+ def truncate
11
+ data.to_s.gsub(/./, character)[0...truncation_length]
12
+ end
13
+
14
+ private
15
+
16
+ def truncation_length
17
+ options.fetch(:truncate, 50)
18
+ end
19
+
20
+ def character
21
+ options.fetch(:character, "•")
22
+ end
23
+ end
24
+ end
25
+ end
@@ -30,7 +30,7 @@ module Administrate
30
30
  end
31
31
 
32
32
  def classes
33
- options.fetch(:classes) || []
33
+ options.fetch(:classes, [])
34
34
  end
35
35
 
36
36
  private
@@ -0,0 +1,8 @@
1
+ require_relative "base"
2
+
3
+ module Administrate
4
+ module Field
5
+ class Time < Base
6
+ end
7
+ end
8
+ end
@@ -12,7 +12,7 @@ module Administrate
12
12
 
13
13
  def routes
14
14
  @routes ||= all_routes.select do |controller, _action|
15
- controller.starts_with?(namespace.to_s)
15
+ controller.starts_with?("#{namespace}/")
16
16
  end.map do |controller, action|
17
17
  [controller.gsub(/^#{namespace}\//, ""), action]
18
18
  end
@@ -9,7 +9,9 @@ module Administrate
9
9
  return order_by_association(relation) unless
10
10
  reflect_association(relation).nil?
11
11
 
12
- return relation.reorder("#{attribute} #{direction}") if
12
+ order = "#{relation.table_name}.#{attribute} #{direction}"
13
+
14
+ return relation.reorder(order) if
13
15
  relation.columns_hash.keys.include?(attribute.to_s)
14
16
 
15
17
  relation
@@ -15,6 +15,10 @@ module Administrate
15
15
  @resource_path ||= resource_name.gsub("/", "_")
16
16
  end
17
17
 
18
+ def association_includes
19
+ dashboard.try(:association_includes) || []
20
+ end
21
+
18
22
  protected
19
23
 
20
24
  def attribute_field(dashboard, resource, attribute_name, page)
@@ -21,7 +21,11 @@ module Administrate
21
21
  ordered_by?(attr) && order.direction
22
22
  end
23
23
 
24
- delegate :ordered_by?, :order_params_for, to: :order
24
+ delegate :ordered_by?, to: :order
25
+
26
+ def order_params_for(attr, key: resource_name)
27
+ { key => order.order_params_for(attr) }
28
+ end
25
29
 
26
30
  private
27
31
 
@@ -13,7 +13,7 @@ module Administrate
13
13
  if @term.blank?
14
14
  @scoped_resource.all
15
15
  else
16
- @scoped_resource.where(query, *search_terms)
16
+ @scoped_resource.joins(tables_to_join).where(query, *search_terms)
17
17
  end
18
18
  end
19
19
 
@@ -21,10 +21,10 @@ module Administrate
21
21
 
22
22
  def query
23
23
  search_attributes.map do |attr|
24
- table_name = ActiveRecord::Base.connection.
25
- quote_table_name(@scoped_resource.table_name)
26
- attr_name = ActiveRecord::Base.connection.quote_column_name(attr)
27
- "LOWER(TEXT(#{table_name}.#{attr_name})) LIKE ?"
24
+ table_name = query_table_name(attr)
25
+ attr_name = column_to_query(attr)
26
+
27
+ "LOWER(CAST(#{table_name}.#{attr_name} AS CHAR(256))) LIKE ?"
28
28
  end.join(" OR ")
29
29
  end
30
30
 
@@ -42,6 +42,40 @@ module Administrate
42
42
  @dashboard_class::ATTRIBUTE_TYPES
43
43
  end
44
44
 
45
+ def query_table_name(attr)
46
+ if association_search?(attr)
47
+ ActiveRecord::Base.connection.quote_table_name(attr.to_s.pluralize)
48
+ else
49
+ ActiveRecord::Base.connection.
50
+ quote_table_name(@scoped_resource.table_name)
51
+ end
52
+ end
53
+
54
+ def column_to_query(attr)
55
+ if association_search?(attr)
56
+ ActiveRecord::Base.connection.
57
+ quote_column_name(attribute_types[attr].searchable_field)
58
+ else
59
+ ActiveRecord::Base.connection.quote_column_name(attr)
60
+ end
61
+ end
62
+
63
+ def tables_to_join
64
+ attribute_types.keys.select do |attribute|
65
+ attribute_types[attribute].searchable? && association_search?(attribute)
66
+ end
67
+ end
68
+
69
+ def association_search?(attribute)
70
+ return unless attribute_types[attribute].respond_to?(:deferred_class)
71
+
72
+ [
73
+ Administrate::Field::BelongsTo,
74
+ Administrate::Field::HasMany,
75
+ Administrate::Field::HasOne,
76
+ ].include?(attribute_types[attribute].deferred_class)
77
+ end
78
+
45
79
  attr_reader :resolver, :term
46
80
  end
47
81
  end
@@ -1,3 +1,3 @@
1
1
  module Administrate
2
- VERSION = "0.1.1".freeze
2
+ VERSION = "0.10.0".freeze
3
3
  end
@@ -10,7 +10,7 @@ module Administrate
10
10
  enum: "Field::String",
11
11
  float: "Field::Number",
12
12
  integer: "Field::Number",
13
- time: "Field::DateTime",
13
+ time: "Field::Time",
14
14
  text: "Field::Text",
15
15
  string: "Field::String",
16
16
  }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: semantic-administrate
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nick Charlton
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2018-02-27 00:00:00.000000000 Z
12
+ date: 2018-08-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: actionpack
@@ -20,7 +20,7 @@ dependencies:
20
20
  version: '4.2'
21
21
  - - "<"
22
22
  - !ruby/object:Gem::Version
23
- version: '5.2'
23
+ version: '6.0'
24
24
  type: :runtime
25
25
  prerelease: false
26
26
  version_requirements: !ruby/object:Gem::Requirement
@@ -30,7 +30,7 @@ dependencies:
30
30
  version: '4.2'
31
31
  - - "<"
32
32
  - !ruby/object:Gem::Version
33
- version: '5.2'
33
+ version: '6.0'
34
34
  - !ruby/object:Gem::Dependency
35
35
  name: actionview
36
36
  requirement: !ruby/object:Gem::Requirement
@@ -40,7 +40,7 @@ dependencies:
40
40
  version: '4.2'
41
41
  - - "<"
42
42
  - !ruby/object:Gem::Version
43
- version: '5.2'
43
+ version: '6.0'
44
44
  type: :runtime
45
45
  prerelease: false
46
46
  version_requirements: !ruby/object:Gem::Requirement
@@ -50,7 +50,7 @@ dependencies:
50
50
  version: '4.2'
51
51
  - - "<"
52
52
  - !ruby/object:Gem::Version
53
- version: '5.2'
53
+ version: '6.0'
54
54
  - !ruby/object:Gem::Dependency
55
55
  name: activerecord
56
56
  requirement: !ruby/object:Gem::Requirement
@@ -60,7 +60,7 @@ dependencies:
60
60
  version: '4.2'
61
61
  - - "<"
62
62
  - !ruby/object:Gem::Version
63
- version: '5.2'
63
+ version: '6.0'
64
64
  type: :runtime
65
65
  prerelease: false
66
66
  version_requirements: !ruby/object:Gem::Requirement
@@ -70,7 +70,7 @@ dependencies:
70
70
  version: '4.2'
71
71
  - - "<"
72
72
  - !ruby/object:Gem::Version
73
- version: '5.2'
73
+ version: '6.0'
74
74
  - !ruby/object:Gem::Dependency
75
75
  name: autoprefixer-rails
76
76
  requirement: !ruby/object:Gem::Requirement
@@ -262,6 +262,9 @@ files:
262
262
  - app/views/fields/number/_form.html.erb
263
263
  - app/views/fields/number/_index.html.erb
264
264
  - app/views/fields/number/_show.html.erb
265
+ - app/views/fields/password/_form.html.erb
266
+ - app/views/fields/password/_index.html.erb
267
+ - app/views/fields/password/_show.html.erb
265
268
  - app/views/fields/polymorphic/_form.html.erb
266
269
  - app/views/fields/polymorphic/_index.html.erb
267
270
  - app/views/fields/polymorphic/_show.html.erb
@@ -274,8 +277,12 @@ files:
274
277
  - app/views/fields/text/_form.html.erb
275
278
  - app/views/fields/text/_index.html.erb
276
279
  - app/views/fields/text/_show.html.erb
280
+ - app/views/fields/time/_form.html.erb
281
+ - app/views/fields/time/_index.html.erb
282
+ - app/views/fields/time/_show.html.erb
277
283
  - app/views/layouts/administrate/application.html.erb
278
284
  - config/i18n-tasks.yml
285
+ - config/locales/administrate.al.yml
279
286
  - config/locales/administrate.ar.yml
280
287
  - config/locales/administrate.bs.yml
281
288
  - config/locales/administrate.ca.yml
@@ -284,6 +291,7 @@ files:
284
291
  - config/locales/administrate.en.yml
285
292
  - config/locales/administrate.es.yml
286
293
  - config/locales/administrate.fr.yml
294
+ - config/locales/administrate.id.yml
287
295
  - config/locales/administrate.it.yml
288
296
  - config/locales/administrate.ja.yml
289
297
  - config/locales/administrate.ko.yml
@@ -320,10 +328,12 @@ files:
320
328
  - lib/administrate/field/has_many.rb
321
329
  - lib/administrate/field/has_one.rb
322
330
  - lib/administrate/field/number.rb
331
+ - lib/administrate/field/password.rb
323
332
  - lib/administrate/field/polymorphic.rb
324
333
  - lib/administrate/field/select.rb
325
334
  - lib/administrate/field/string.rb
326
335
  - lib/administrate/field/text.rb
336
+ - lib/administrate/field/time.rb
327
337
  - lib/administrate/generator_helpers.rb
328
338
  - lib/administrate/namespace.rb
329
339
  - lib/administrate/namespace/resource.rb