administrate 0.11.0 → 0.16.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 (114) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/administrate/components/associative.js +5 -0
  3. data/app/assets/javascripts/administrate/components/date_time_picker.js +6 -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 +4 -3
  8. data/app/assets/stylesheets/administrate/components/_buttons.scss +11 -0
  9. data/app/assets/stylesheets/administrate/components/_cells.scss +2 -0
  10. data/app/assets/stylesheets/administrate/components/_field-unit.scss +17 -4
  11. data/app/assets/stylesheets/administrate/components/_flashes.scss +0 -8
  12. data/app/assets/stylesheets/administrate/components/_main-content.scss +1 -0
  13. data/app/assets/stylesheets/administrate/components/_navigation.scss +2 -3
  14. data/app/assets/stylesheets/administrate/library/_variables.scss +10 -8
  15. data/app/controllers/administrate/application_controller.rb +32 -11
  16. data/app/controllers/concerns/administrate/punditize.rb +3 -3
  17. data/app/helpers/administrate/application_helper.rb +41 -15
  18. data/app/views/administrate/application/_collection.html.erb +6 -4
  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 +3 -3
  23. data/app/views/administrate/application/show.html.erb +1 -1
  24. data/app/views/fields/belongs_to/_form.html.erb +3 -3
  25. data/app/views/fields/date/_form.html.erb +24 -0
  26. data/app/views/fields/date/_index.html.erb +21 -0
  27. data/app/views/fields/date/_show.html.erb +21 -0
  28. data/app/views/fields/has_one/_index.html.erb +1 -1
  29. data/app/views/fields/has_one/_show.html.erb +4 -4
  30. data/app/views/fields/number/_form.html.erb +1 -1
  31. data/app/views/fields/polymorphic/_show.html.erb +1 -1
  32. data/app/views/fields/select/_form.html.erb +22 -10
  33. data/app/views/fields/string/_show.html.erb +2 -2
  34. data/app/views/fields/text/_show.html.erb +2 -3
  35. data/app/views/fields/time/_form.html.erb +3 -2
  36. data/app/views/fields/time/_index.html.erb +3 -1
  37. data/app/views/fields/time/_show.html.erb +3 -1
  38. data/app/views/fields/url/_form.html.erb +23 -0
  39. data/app/views/fields/url/_index.html.erb +20 -0
  40. data/app/views/fields/url/_show.html.erb +20 -0
  41. data/app/views/layouts/administrate/application.html.erb +2 -1
  42. data/config/locales/administrate.ar.yml +2 -0
  43. data/config/locales/administrate.bs.yml +2 -0
  44. data/config/locales/administrate.ca.yml +2 -0
  45. data/config/locales/administrate.da.yml +2 -0
  46. data/config/locales/administrate.de.yml +2 -0
  47. data/config/locales/administrate.en.yml +2 -0
  48. data/config/locales/administrate.es.yml +3 -1
  49. data/config/locales/administrate.fi.yml +30 -0
  50. data/config/locales/administrate.fr.yml +4 -2
  51. data/config/locales/administrate.id.yml +2 -0
  52. data/config/locales/administrate.it.yml +2 -0
  53. data/config/locales/administrate.ja.yml +2 -0
  54. data/config/locales/administrate.ko.yml +12 -10
  55. data/config/locales/administrate.nl.yml +7 -5
  56. data/config/locales/administrate.pl.yml +2 -0
  57. data/config/locales/administrate.pt-BR.yml +4 -2
  58. data/config/locales/administrate.pt.yml +4 -2
  59. data/config/locales/administrate.ru.yml +2 -0
  60. data/config/locales/{administrate.al.yml → administrate.sq.yml} +3 -1
  61. data/config/locales/administrate.sv.yml +2 -0
  62. data/config/locales/administrate.tr.yml +30 -0
  63. data/config/locales/administrate.uk.yml +2 -0
  64. data/config/locales/administrate.vi.yml +2 -0
  65. data/config/locales/administrate.zh-CN.yml +4 -2
  66. data/config/locales/administrate.zh-TW.yml +2 -0
  67. data/config/unicorn.rb +8 -13
  68. data/docs/adding_controllers_without_related_model.md +52 -0
  69. data/docs/adding_custom_field_types.md +3 -1
  70. data/docs/authentication.md +3 -1
  71. data/docs/authorization.md +5 -3
  72. data/docs/customizing_attribute_partials.md +5 -2
  73. data/docs/customizing_controller_actions.md +32 -2
  74. data/docs/customizing_dashboards.md +78 -29
  75. data/docs/customizing_page_views.md +18 -4
  76. data/docs/extending_administrate.md +27 -0
  77. data/docs/getting_started.md +49 -56
  78. data/docs/guides.md +5 -0
  79. data/docs/guides/hiding_dashboards_from_sidebar.md +19 -0
  80. data/docs/rails_api.md +45 -0
  81. data/lib/administrate.rb +19 -0
  82. data/lib/administrate/base_dashboard.rb +31 -9
  83. data/lib/administrate/custom_dashboard.rb +15 -0
  84. data/lib/administrate/engine.rb +8 -1
  85. data/lib/administrate/field/associative.rb +49 -5
  86. data/lib/administrate/field/base.rb +35 -9
  87. data/lib/administrate/field/belongs_to.rb +13 -3
  88. data/lib/administrate/field/date.rb +20 -0
  89. data/lib/administrate/field/deferred.rb +22 -3
  90. data/lib/administrate/field/has_many.rb +16 -3
  91. data/lib/administrate/field/has_one.rb +32 -12
  92. data/lib/administrate/field/number.rb +19 -2
  93. data/lib/administrate/field/polymorphic.rb +5 -5
  94. data/lib/administrate/field/select.rb +6 -1
  95. data/lib/administrate/field/url.rb +21 -0
  96. data/lib/administrate/namespace.rb +5 -1
  97. data/lib/administrate/order.rb +17 -7
  98. data/lib/administrate/page/base.rb +7 -5
  99. data/lib/administrate/page/form.rb +1 -1
  100. data/lib/administrate/resource_resolver.rb +2 -2
  101. data/lib/administrate/search.rb +107 -23
  102. data/lib/administrate/version.rb +1 -1
  103. data/lib/administrate/view_generator.rb +9 -3
  104. data/lib/generators/administrate/dashboard/dashboard_generator.rb +22 -16
  105. data/lib/generators/administrate/dashboard/templates/controller.rb.erb +35 -10
  106. data/lib/generators/administrate/dashboard/templates/dashboard.rb.erb +18 -6
  107. data/lib/generators/administrate/install/install_generator.rb +37 -1
  108. data/lib/generators/administrate/install/templates/application_controller.rb.erb +3 -3
  109. data/lib/generators/administrate/routes/routes_generator.rb +21 -26
  110. data/lib/generators/administrate/views/layout_generator.rb +1 -0
  111. data/lib/generators/administrate/views/views_generator.rb +5 -4
  112. metadata +49 -53
  113. data/app/assets/javascripts/administrate/components/has_many_form.js +0 -3
  114. data/config/secrets.yml +0 -14
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 11c705312ca68f68a80830fbe9088602b2d495fb4a4ee75ad86997a3ddb86c42
4
- data.tar.gz: 8f56b485d373c66777ef5d535916953a57b0d5416019504ddc45d4a0d5fc37fa
3
+ metadata.gz: b4919291c5352f8cfb68e629292b4cd85f89d1e8912bf75e6702ecee682383f7
4
+ data.tar.gz: 48212e43cd940b32a40f1d86c93f181cb808fbcfaa839459292ec258460c8b97
5
5
  SHA512:
6
- metadata.gz: 3eefe2c7ff3dd30bcf5f58ee2bdfe8ad86645f6e34f1b8d0a6fd74094bedaff76c96c0526b839dca435a4e1acda2f71c8687aaae27b62be301a1d087420bdcb2
7
- data.tar.gz: 5fb275186d046fd0daa165b994f84df4d4f944c56128e7c9309c9070e4d1e4a9ebecaf2d1c22b8d5677c8493bfcffda9414ecb819673ed8216bc9d74c745bd09
6
+ metadata.gz: 839bab4d2832921f6a6f7fcc06cbc8f8a5e18017e9de81d7d0c5d22360567ba9b9a427a68223c5b6fe600cb07dbb176404476a51fecb56f07f559a1461da0c4c
7
+ data.tar.gz: 7b356066b5c0dbe9d82bdc65eefe6563111e30592b827b94fdd03196f01a29e167fb5d22cee9ec907c7e57c29913f12ba75a922aef7f8172a0130b964527c2d8
@@ -0,0 +1,5 @@
1
+ $(function() {
2
+ $('.field-unit--belongs-to select').selectize({});
3
+ $(".field-unit--has-many select").selectize({});
4
+ $('.field-unit--polymorphic select').selectize({});
5
+ });
@@ -1,10 +1,14 @@
1
1
  $(function () {
2
2
  $('[data-type="time"]').datetimepicker({
3
3
  debug: false,
4
- format: "HH:mm:ss",
4
+ format: 'HH:mm:ss',
5
5
  });
6
6
  $('[data-type="datetime"]').datetimepicker({
7
7
  debug: false,
8
- format: "YYYY-MM-DD HH:mm:ss",
8
+ format: 'YYYY-MM-DD HH:mm:ss',
9
+ });
10
+ $('[data-type="date"]').datetimepicker({
11
+ debug: false,
12
+ format: 'YYYY-MM-DD',
9
13
  });
10
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,9 +3,9 @@
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
- width: calc(15% - 1rem);
8
+ width: calc(20% - 1rem);
9
9
  }
10
10
 
11
11
  .preserve-whitespace {
@@ -17,7 +17,8 @@
17
17
  float: left;
18
18
  margin-bottom: $base-spacing;
19
19
  margin-left: 2rem;
20
- width: calc(85% - 1rem);
20
+ width: calc(80% - 1rem);
21
+ word-break: break-word;
21
22
  }
22
23
 
23
24
  .attribute--nested {
@@ -41,3 +41,14 @@ 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
+ }
51
+
52
+ .button--nav {
53
+ margin-bottom: $base-spacing;
54
+ }
@@ -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,33 @@
17
17
  .field-unit__field {
18
18
  float: left;
19
19
  margin-left: 2rem;
20
- width: 45%;
20
+ max-width: 50rem;
21
+ width: 100%;
22
+
23
+ .optgroup-header {
24
+ font-weight: $bold-font-weight;
25
+ }
21
26
  }
22
27
 
23
28
  .field-unit--nested {
24
29
  border: $base-border;
25
30
  margin-left: 7.5%;
31
+ max-width: 60rem;
26
32
  padding: $small-spacing;
27
- width: 50%;
33
+ width: 100%;
28
34
 
29
35
  .field-unit__field {
30
- width: calc(75% - 1rem);
36
+ width: 100%;
31
37
  }
32
38
 
33
39
  .field-unit__label {
34
- width: calc(25% - 1rem);
40
+ width: 10rem;
41
+ }
42
+ }
43
+
44
+ .field-unit--required {
45
+ label::after {
46
+ color: $red;
47
+ content: " *";
35
48
  }
36
49
  }
@@ -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;
@@ -5,6 +5,7 @@
5
5
  0 2px 2px rgba($black, 0.2);
6
6
  flex: 1 1 100%;
7
7
  padding-bottom: 10vh;
8
+ min-width: 800px;
8
9
  }
9
10
 
10
11
  .main-content__header,
@@ -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;
@@ -3,13 +3,14 @@ module Administrate
3
3
  protect_from_forgery with: :exception
4
4
 
5
5
  def index
6
+ authorize_resource(resource_class)
6
7
  search_term = params[:search].to_s.strip
7
8
  resources = Administrate::Search.new(scoped_resource,
8
9
  dashboard_class,
9
10
  search_term).run
10
- resources = apply_resource_includes(resources)
11
+ resources = apply_collection_includes(resources)
11
12
  resources = order.apply(resources)
12
- resources = resources.page(params[:page]).per(records_per_page)
13
+ resources = resources.page(params[:_page]).per(records_per_page)
13
14
  page = Administrate::Page::Collection.new(dashboard, order: order)
14
15
 
15
16
  render locals: {
@@ -27,7 +28,7 @@ module Administrate
27
28
  end
28
29
 
29
30
  def new
30
- resource = resource_class.new
31
+ resource = new_resource
31
32
  authorize_resource(resource)
32
33
  render locals: {
33
34
  page: Administrate::Page::Form.new(dashboard, resource),
@@ -52,7 +53,7 @@ module Administrate
52
53
  else
53
54
  render :new, locals: {
54
55
  page: Administrate::Page::Form.new(dashboard, resource),
55
- }
56
+ }, status: :unprocessable_entity
56
57
  end
57
58
  end
58
59
 
@@ -65,7 +66,7 @@ module Administrate
65
66
  else
66
67
  render :edit, locals: {
67
68
  page: Administrate::Page::Form.new(dashboard, requested_resource),
68
- }
69
+ }, status: :unprocessable_entity
69
70
  end
70
71
  end
71
72
 
@@ -101,10 +102,27 @@ module Administrate
101
102
  end
102
103
 
103
104
  def order
104
- @order ||= Administrate::Order.new(
105
- params.fetch(resource_name, {}).fetch(:order, nil),
106
- params.fetch(resource_name, {}).fetch(:direction, nil),
107
- )
105
+ @order ||= Administrate::Order.new(sorting_attribute, sorting_direction)
106
+ end
107
+
108
+ def sorting_attribute
109
+ sorting_params.fetch(:order) { default_sorting_attribute }
110
+ end
111
+
112
+ def default_sorting_attribute
113
+ nil
114
+ end
115
+
116
+ def sorting_direction
117
+ sorting_params.fetch(:direction) { default_sorting_direction }
118
+ end
119
+
120
+ def default_sorting_direction
121
+ nil
122
+ end
123
+
124
+ def sorting_params
125
+ Hash.try_convert(request.query_parameters[resource_name]) || {}
108
126
  end
109
127
 
110
128
  def dashboard
@@ -125,8 +143,8 @@ module Administrate
125
143
  resource_class.default_scoped
126
144
  end
127
145
 
128
- def apply_resource_includes(relation)
129
- resource_includes = dashboard.association_includes
146
+ def apply_collection_includes(relation)
147
+ resource_includes = dashboard.collection_includes
130
148
  return relation if resource_includes.empty?
131
149
  relation.includes(*resource_includes)
132
150
  end
@@ -144,6 +162,8 @@ module Administrate
144
162
  else
145
163
  raise "Unrecognised param data: #{data.inspect}"
146
164
  end
165
+ elsif data.is_a?(ActionController::Parameters)
166
+ data.transform_values { |v| read_param_value(v) }
147
167
  else
148
168
  data
149
169
  end
@@ -153,6 +173,7 @@ module Administrate
153
173
  to: :resource_resolver
154
174
  helper_method :namespace
155
175
  helper_method :resource_name
176
+ helper_method :resource_class
156
177
 
157
178
  def resource_resolver
158
179
  @resource_resolver ||=
@@ -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
 
@@ -1,23 +1,39 @@
1
1
  module Administrate
2
2
  module ApplicationHelper
3
3
  PLURAL_MANY_COUNT = 2.1
4
+ SINGULAR_COUNT = 1
5
+
6
+ def application_title
7
+ if Rails::VERSION::MAJOR <= 5
8
+ Rails.application.class.parent_name.titlecase
9
+ else
10
+ Rails.application.class.module_parent_name.titlecase
11
+ end
12
+ end
4
13
 
5
14
  def render_field(field, locals = {})
6
- locals.merge!(field: field)
15
+ locals[:field] = field
7
16
  render locals: locals, partial: field.to_partial_path
8
17
  end
9
18
 
10
- def class_from_resource(resource_name)
11
- resource_name.to_s.classify.constantize
19
+ def requireness(field)
20
+ field.required? ? "required" : "optional"
21
+ end
22
+
23
+ def dashboard_from_resource(resource_name)
24
+ "#{resource_name.to_s.singularize}_dashboard".classify.constantize
25
+ end
26
+
27
+ def model_from_resource(resource_name)
28
+ dashboard = dashboard_from_resource(resource_name)
29
+ dashboard.try(:model) || resource_name.to_sym
12
30
  end
13
31
 
14
- 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
- )
32
+ def display_resource_name(resource_name, opts = {})
33
+ dashboard_from_resource(resource_name).resource_name(
34
+ count: opts[:singular] ? SINGULAR_COUNT : PLURAL_MANY_COUNT,
35
+ default: default_resource_name(resource_name, opts),
36
+ )
21
37
  end
22
38
 
23
39
  def sort_order(order)
@@ -28,22 +44,32 @@ module Administrate
28
44
  end
29
45
  end
30
46
 
31
- def resource_index_route_key(resource_name)
32
- ActiveModel::Naming.route_key(class_from_resource(resource_name))
47
+ def resource_index_route(resource_name)
48
+ url_for(
49
+ action: "index",
50
+ controller: "/#{namespace}/#{resource_name}",
51
+ )
33
52
  end
34
53
 
35
54
  def sanitized_order_params(page, current_field_name)
36
- collection_names = page.association_includes + [current_field_name]
55
+ collection_names = page.item_includes + [current_field_name]
37
56
  association_params = collection_names.map do |assoc_name|
38
57
  { assoc_name => %i[order direction page per_page] }
39
58
  end
40
- params.permit(:search, :id, :page, :per_page, association_params)
59
+ params.permit(:search, :id, :_page, :per_page, association_params)
41
60
  end
42
61
 
43
62
  def clear_search_params
44
- params.except(:search, :page).permit(
63
+ params.except(:search, :_page).permit(
45
64
  :per_page, resource_name => %i[order direction]
46
65
  )
47
66
  end
67
+
68
+ private
69
+
70
+ def default_resource_name(name, opts = {})
71
+ resource_name = (opts[:singular] ? name.to_s : name.to_s.pluralize)
72
+ resource_name.gsub("/", "_").titleize
73
+ end
48
74
  end
49
75
  end
@@ -33,7 +33,7 @@ to display a collection of resources in an HTML table.
33
33
  )) do %>
34
34
  <%= t(
35
35
  "helpers.label.#{collection_presenter.resource_name}.#{attr_name}",
36
- default: attr_name.to_s,
36
+ default: resource_class.human_attribute_name(attr_name),
37
37
  ).titleize %>
38
38
  <% if collection_presenter.ordered_by?(attr_name) %>
39
39
  <span class="cell-label__sort-indicator cell-label__sort-indicator--<%= collection_presenter.ordered_html_class(attr_name) %>">
@@ -55,19 +55,21 @@ to display a collection of resources in an HTML table.
55
55
  <tbody>
56
56
  <% resources.each do |resource| %>
57
57
  <tr class="js-table-row"
58
- tabindex="0"
59
- <% if valid_action? :show, collection_presenter.resource_name %>
60
- <%= %(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])}) %>
61
60
  <% end %>
62
61
  >
63
62
  <% collection_presenter.attributes_for(resource).each do |attribute| %>
64
63
  <td class="cell-data cell-data--<%= attribute.html_class %>">
65
64
  <% if show_action? :show, resource -%>
66
65
  <a href="<%= polymorphic_path([namespace, resource]) -%>"
66
+ tabindex="-1"
67
67
  class="action-show"
68
68
  >
69
69
  <%= render_field attribute %>
70
70
  </a>
71
+ <% else %>
72
+ <%= render_field attribute %>
71
73
  <% end -%>
72
74
  </td>
73
75
  <% end %>