cm-admin 0.8.9 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/.stylelintrc.json +3 -0
  3. data/.github/workflows/linters.yml +31 -0
  4. data/Gemfile +5 -1
  5. data/Gemfile.lock +23 -10
  6. data/app/assets/stylesheets/cm_admin/base/auth.scss +1 -1
  7. data/app/assets/stylesheets/cm_admin/base/common.scss +3 -3
  8. data/app/assets/stylesheets/cm_admin/base/filters.scss +11 -17
  9. data/app/assets/stylesheets/cm_admin/base/form.scss +6 -12
  10. data/app/assets/stylesheets/cm_admin/base/main-nav.scss +3 -7
  11. data/app/assets/stylesheets/cm_admin/base/navbar.scss +3 -2
  12. data/app/assets/stylesheets/cm_admin/base/quicksearch.scss +4 -6
  13. data/app/assets/stylesheets/cm_admin/base/scaffold.scss +45 -2
  14. data/app/assets/stylesheets/cm_admin/base/show.scss +11 -9
  15. data/app/assets/stylesheets/cm_admin/base/sidebar.scss +9 -19
  16. data/app/assets/stylesheets/cm_admin/base/table.scss +258 -325
  17. data/app/assets/stylesheets/cm_admin/base/tabs.scss +1 -2
  18. data/app/assets/stylesheets/cm_admin/components/_buttons.scss +19 -6
  19. data/app/assets/stylesheets/cm_admin/components/_drawer.scss +4 -8
  20. data/app/assets/stylesheets/cm_admin/components/_dropdown-popup.scss +1 -2
  21. data/app/assets/stylesheets/cm_admin/components/_input.scss +1 -1
  22. data/app/assets/stylesheets/cm_admin/components/_status-tag.scss +3 -2
  23. data/app/assets/stylesheets/cm_admin/helpers/_variable.scss +4 -0
  24. data/app/assets/stylesheets/cm_admin/scaffold.scss +2 -2
  25. data/app/controllers/cm_admin/resource_controller.rb +4 -2
  26. data/app/javascript/packs/cm_admin/filters.js +1 -1
  27. data/app/javascript/packs/cm_admin/scaffolds.js +4 -1
  28. data/app/views/cm_admin/main/_actions_dropdown.html.slim +2 -2
  29. data/app/views/cm_admin/main/_associated_table.html.slim +20 -21
  30. data/app/views/cm_admin/main/_member_custom_action_modal.html.slim +1 -1
  31. data/app/views/cm_admin/main/_table.html.slim +13 -14
  32. data/app/views/cm_admin/main/associated_index.html.slim +4 -5
  33. data/app/views/cm_admin/main/index.html.slim +13 -14
  34. data/app/views/cm_admin/main/show.html.slim +2 -2
  35. data/app/views/layouts/cm_admin.html.slim +5 -5
  36. data/lib/cm_admin/model.rb +6 -1
  37. data/lib/cm_admin/models/action.rb +1 -1
  38. data/lib/cm_admin/models/column.rb +16 -3
  39. data/lib/cm_admin/models/dsl_method.rb +17 -4
  40. data/lib/cm_admin/models/field.rb +7 -1
  41. data/lib/cm_admin/models/utils/associations.rb +25 -0
  42. data/lib/cm_admin/version.rb +1 -1
  43. data/lib/cm_admin/view_helpers/field_display_helper.rb +21 -1
  44. data/lib/cm_admin/view_helpers/page_info_helper.rb +7 -3
  45. data/package-lock.json +2801 -158
  46. data/package.json +2 -0
  47. data/tmp/cache/webpacker/last-compilation-digest-development +1 -1
  48. data/yarn.lock +6949 -5133
  49. metadata +5 -2
@@ -1,14 +1,16 @@
1
1
  @import '../helpers/index.scss';
2
2
 
3
3
  .cta-btn {
4
- padding: 8px 16px;
4
+ padding: 5px 10px;
5
5
  @include font($size: $t4-text, $color: $white, $weight: bold);
6
6
  background-color: $brand-color;
7
7
  border: none;
8
8
  border-radius: $radius-4;
9
9
  transition: all .2s linear;
10
10
  &:hover {
11
- background-color: #4D40AA;
11
+ color: $white;
12
+ background: $cta-hover-gradient;
13
+ transform: scale(1.05);
12
14
  }
13
15
  &:focus {
14
16
  outline: 3px auto rgba(47, 128, 237, 0.3);
@@ -25,14 +27,16 @@
25
27
  }
26
28
 
27
29
  .primary-btn {
28
- padding: 8px 16px;
30
+ padding: 5px 10px;
29
31
  @include font($size: $t4-text, $color: $brand-color, $weight: bold);
30
32
  background-color: $white;
31
33
  border: 1px solid $brand-color;
32
34
  border-radius: $radius-4;
33
35
  transition: all .2s linear;
34
36
  &:hover {
37
+ color: $brand-color;
35
38
  background-color: #E6E4FA;
39
+ transform: scale(1.05);
36
40
  }
37
41
  &:focus {
38
42
  outline: 3px auto rgba(47, 128, 237, 0.3);
@@ -50,14 +54,16 @@
50
54
  }
51
55
 
52
56
  .secondary-btn {
53
- padding: 8px 16px;
57
+ padding: 5px 10px;
54
58
  @include font($size: $t4-text, $color: $primary-text-clr, $weight: bold);
55
59
  background-color: $white;
56
60
  border: 1px solid $ink-regular-clr;
57
61
  border-radius: $radius-4;
58
62
  transition: all .2s linear;
59
63
  &:hover {
64
+ color: $primary-text-clr;
60
65
  background-color: $grey-light-clr;
66
+ transform: scale(1.05);
61
67
  }
62
68
  &:focus {
63
69
  outline: 3px auto rgba(47, 128, 237, 0.3);
@@ -75,17 +81,22 @@
75
81
  span:nth-child(2) {
76
82
  margin: 0 4px 0 8px;
77
83
  }
84
+ span:nth-child(3) {
85
+ @include font($size: 10px, $color: $ink-lighter-clr, $weight: bold);
86
+ }
78
87
  }
79
88
 
80
89
  .gray-border-btn {
81
- padding: 7px 16px;
90
+ padding: 5px 10px;
82
91
  @include font($size: $t4-text, $color: $primary-text-clr, $weight: bold);
83
92
  background-color: $white;
84
93
  border: 1px solid $ink-regular-clr;
85
94
  border-radius: $radius-4;
86
95
  transition: all .2s linear;
87
96
  &:hover {
97
+ color: $primary-text-clr;
88
98
  background-color: $grey-light-clr;
99
+ transform: scale(1.05);
89
100
  }
90
101
  &:focus {
91
102
  outline: 3px auto rgba(47, 128, 237, 0.3);
@@ -103,14 +114,16 @@
103
114
  }
104
115
 
105
116
  .ghost-btn {
106
- padding: 8px 16px;
117
+ padding: 5px 10px;
107
118
  @include font($size: $t4-text, $color: $primary-text-clr, $weight: bold);
108
119
  background-color: transparent;
109
120
  border: none;
110
121
  border-radius: $radius-4;
111
122
  transition: all .2s linear;
112
123
  &:hover {
124
+ color: $primary-text-clr;
113
125
  background: $grey-light-clr;
126
+ transform: scale(1.05);
114
127
  }
115
128
  &:focus {
116
129
  outline: 3px auto rgba(47, 128, 237, 0.3);
@@ -21,21 +21,18 @@
21
21
  align-items: center;
22
22
  justify-content: space-between;
23
23
  padding: 24px;
24
- background: #F8F9FA;
24
+ background: $grey-lightest-clr;
25
25
  &__lhs {
26
26
  .title {
27
+ @include font($size: $t1-text, $color: $primary-text-clr, $weight: 600);
27
28
  font-family: $primary-font;
28
- font-size: $t1-text;
29
- font-weight: 600;
30
29
  line-height: 28px;
31
- color: $primary-text-clr;
32
30
  margin-bottom: 8px;
33
31
  }
34
32
  .description {
33
+ @include font($size: $t4-text, $color: $primary-text-clr);
35
34
  font-family: $primary-font;
36
- font-size: $t4-text;
37
35
  line-height: 22px;
38
- color: $primary-text-clr;
39
36
  margin-bottom: 0;
40
37
  }
41
38
  }
@@ -46,10 +43,9 @@
46
43
  .body {
47
44
  padding: 24px;
48
45
  .info-text {
46
+ @include font($size: $t4-text, $color: $primary-text-clr);
49
47
  font-family: $primary-font;
50
- font-size: $t4-text;
51
48
  line-height: 22px;
52
- color: $primary-text-clr;
53
49
  }
54
50
  }
55
51
  }
@@ -143,9 +143,8 @@
143
143
  }
144
144
  }
145
145
  .cannot-sort {
146
- font-size: $t6-text;
146
+ @include font($size: $t6-text, $color: $ink-lightest-clr);
147
147
  line-height: 16px;
148
- color: $ink-lightest-clr;
149
148
  margin-bottom: 9px;
150
149
  padding: 0 16px;
151
150
  }
@@ -38,7 +38,7 @@
38
38
  .search-input {
39
39
  position: relative;
40
40
  width: 100%;
41
- padding: 8px 0 8px 40px;
41
+ padding: 5px 0 5px 38px;
42
42
  @include font($size: $t4-text, $color: $primary-text-clr);
43
43
  line-height: 22px;
44
44
  background-color: $white;
@@ -6,6 +6,7 @@
6
6
  padding: 4px;
7
7
  color: $primary-text-clr;
8
8
  background: $grey-lighter-clr;
9
+ border-radius: 2px;
9
10
  &.success {
10
11
  color: $green-regular-clr;
11
12
  background: $green-lightest-clr;
@@ -25,7 +26,7 @@
25
26
  cursor: pointer;
26
27
  user-select: none;
27
28
  &:hover {
28
- background-color: #F3F4F6;
29
+ background-color: $grey-lighter-clr;
29
30
  .filter-chip-remove {
30
31
  display: block;
31
32
  }
@@ -42,7 +43,7 @@
42
43
  top: 0;
43
44
  right: 0;
44
45
  padding: 4px 16px;
45
- background: linear-gradient(270deg, #F3F4F6 81.75%, rgba(243, 244, 246, 0) 100%);
46
+ background: $gradient-one;
46
47
  border-radius: $radius-4;
47
48
  i {
48
49
  font-size: 10px;
@@ -51,6 +51,10 @@ $subdued-text-clr: #D9DEE3;
51
51
  $white: #FFFFFF;
52
52
  $black: #000000;
53
53
 
54
+ // Gradient Colors
55
+ $gradient-one: linear-gradient(270deg, $grey-lighter-clr 81.75%, rgba(243, 244, 246, 0) 100%);
56
+ $cta-hover-gradient: linear-gradient(0deg, rgba(0, 0, 0, 0.24), rgba(0, 0, 0, 0.24)), $brand-color;
57
+
54
58
  /* Typography */
55
59
  $primary-font: 'Open Sans', sans-serif;
56
60
  $font-size: (
@@ -2,7 +2,7 @@
2
2
 
3
3
  .jGrowl {
4
4
  color: $ink-regular-clr !important;
5
- font-size: 14px !important;
5
+ font-size: $t4-text !important;
6
6
  .success{
7
7
  background-color: $green-light-clr !important;
8
8
  }
@@ -17,7 +17,7 @@
17
17
 
18
18
  .nested-field-wrapper {
19
19
  label {
20
- font-size: 14px;
20
+ font-size: $t4-text;
21
21
  margin-bottom: 16px;
22
22
  }
23
23
  .nested-fields {
@@ -193,7 +193,9 @@ module CmAdmin
193
193
  end
194
194
 
195
195
  def resource_params(params)
196
- permittable_fields = @permitted_fields || @model.ar_model.columns.map(&:name).reject { |i| CmAdmin::REJECTABLE_FIELDS.include?(i) }.map(&:to_sym)
196
+ columns = @model.ar_model.column_names
197
+ columns += @model.ar_model.stored_attributes.values.flatten
198
+ permittable_fields = @model.additional_permitted_fields + columns.reject { |i| CmAdmin::REJECTABLE_FIELDS.include?(i) }.map(&:to_sym)
197
199
  permittable_fields += @model.ar_model.name.constantize.reflect_on_all_associations.map {|x|
198
200
  next if x.options[:polymorphic]
199
201
  if x.class.name.include?('HasOne')
@@ -207,7 +209,7 @@ module CmAdmin
207
209
  nested_fields = nested_tables.uniq.map {|table|
208
210
  Hash[
209
211
  table.to_s + '_attributes',
210
- table.to_s.classify.constantize.columns.map(&:name).reject { |i| CmAdmin::REJECTABLE_FIELDS.include?(i) }.map(&:to_sym) + [:id, :_destroy]
212
+ table.to_s.classify.constantize.column_names.reject { |i| CmAdmin::REJECTABLE_FIELDS.include?(i) }.map(&:to_sym) + [:id, :_destroy]
211
213
  ]
212
214
  }
213
215
  permittable_fields += nested_fields
@@ -54,7 +54,7 @@ var getFilteredData = function(filterType, filterValue, filterColumn=null) {
54
54
  success: function(data) {
55
55
  var queryParam = jQuery.param(queryString)
56
56
  window.history.pushState("", "", url + '?' + queryParam);
57
- $('.index-page__table-container').html(data);
57
+ $('.cm-index-page__table-container').html(data);
58
58
  },
59
59
  error: function(jqxhr, textStatus, errorThrown) {
60
60
  console.log(errorThrown, textStatus);
@@ -16,6 +16,9 @@ $(document).on('turbolinks:load', function () {
16
16
  animation: 150
17
17
  });
18
18
  }
19
+ var headerElemHeight = $('.page-top-bar').height() + 64
20
+ var calculatedHeight = "calc(100vh - " + headerElemHeight+"px"+")"
21
+ $('.new-admin-table').css("maxHeight", calculatedHeight);
19
22
  });
20
23
 
21
24
  $(document).on("keypress keyup blur", "[data-behaviour='decimal-only'], [data-behaviour='filter'][data-filter-type='range']", function (e) {
@@ -70,4 +73,4 @@ $(document).on('click', '.drawer-close', function(e) {
70
73
  setTimeout(() => {
71
74
  $('.cm-drawer').addClass('hidden');
72
75
  }, 300);
73
- });
76
+ });
@@ -38,10 +38,10 @@
38
38
  .popup-option
39
39
  span
40
40
  i class="#{custom_action.icon_name}"
41
- = custom_action.name.humanize
41
+ = custom_action_title(custom_action)
42
42
  - when :modal
43
43
  = link_to '', data: { bs_toggle: 'modal', bs_target: "##{custom_action.name.classify}Modal-#{ar_object.id.to_s}" } do
44
44
  .popup-option
45
45
  span
46
46
  i class="#{custom_action.icon_name}"
47
- = custom_action.name.humanize
47
+ = custom_action_title(custom_action)
@@ -1,20 +1,19 @@
1
- .admin-table-index
2
- .table-top
3
- - if @associated_model.filters.present? && @action.partial.nil?
4
- .index-page__filters
5
- == render partial: 'cm_admin/main/filters', locals: { filters: @associated_model.filters }
6
- p.table-top__total-count = "#{humanized_ar_collection_count(@associated_ar_object.pagy.count, @action.child_records.to_s)}"
7
- .table-top__column-action
8
- - if @associated_model && @associated_model.available_actions.map(&:name).include?('new') && has_valid_policy(@associated_model.name, 'new')
9
- - association = @ar_object.class.reflect_on_all_associations.select{|x| x.name == @associated_model.name.tableize.to_sym }.first
10
- - polymorphic_name = (association && association.inverse_of && association.inverse_of.options[:polymorphic]) ? association.inverse_of.name : ''
11
- a href="#{CmAdmin::Engine.mount_path}/#{@associated_model.name.tableize}/new?associated_id=#{@ar_object.id}&associated_class=#{@ar_object.class.name.underscore}&polymorphic_name=#{polymorphic_name}&referrer=#{request.path}"
12
- button.secondary-btn.column-btn Add
13
- / button.secondary-btn.column-btn data-target="#columnActionModal" data-toggle="modal" type="button"
14
- / span
15
- / i.fa.fa-columns.bolder
16
- / span
17
- / i.fa.fa-angle-down
1
+ .table-top
2
+ - if @associated_model.filters.present? && @action.partial.nil?
3
+ .cm-index-page__filters
4
+ == render partial: 'cm_admin/main/filters', locals: { filters: @associated_model.filters }
5
+ p.table-top__total-count = "#{humanized_ar_collection_count(@associated_ar_object.pagy.count, @action.child_records.to_s)}"
6
+ .table-top__column-action
7
+ - if @associated_model && @associated_model.available_actions.map(&:name).include?('new') && has_valid_policy(@associated_model.name, 'new')
8
+ - association = @ar_object.class.reflect_on_all_associations.select{|x| x.name == @associated_model.name.tableize.to_sym }.first
9
+ - polymorphic_name = (association && association.inverse_of && association.inverse_of.options[:polymorphic]) ? association.inverse_of.name : ''
10
+ a href="#{CmAdmin::Engine.mount_path}/#{@associated_model.name.tableize}/new?associated_id=#{@ar_object.id}&associated_class=#{@ar_object.class.name.underscore}&polymorphic_name=#{polymorphic_name}&referrer=#{request.path}"
11
+ button.secondary-btn.column-btn Add
12
+ / button.secondary-btn.column-btn data-target="#columnActionModal" data-toggle="modal" type="button"
13
+ / span
14
+ / i.fa.fa-columns.bolder
15
+ / span
16
+ / i.fa.fa-angle-down
18
17
 
19
18
  .new-admin-table.scrollable
20
19
  table.cm-table
@@ -46,9 +45,9 @@
46
45
  - if @associated_model
47
46
  == render partial: 'cm_admin/main/actions_dropdown', locals: { cm_model: @associated_model, ar_object: ar_object }
48
47
 
49
- .cm-pagination
50
- .cm-pagination__lhs Showing #{@associated_ar_object.pagy.from} to #{@associated_ar_object.pagy.to} out of #{@associated_ar_object.pagy.count}
51
- .cm-pagination__rhs
52
- == render partial: 'cm_admin/main/cm_pagy_nav', locals: { pagy: @associated_ar_object.pagy }
48
+ .cm-pagination
49
+ .cm-pagination__lhs Showing #{@associated_ar_object.pagy.from} to #{@associated_ar_object.pagy.to} out of #{@associated_ar_object.pagy.count}
50
+ .cm-pagination__rhs
51
+ == render partial: 'cm_admin/main/cm_pagy_nav', locals: { pagy: @associated_ar_object.pagy }
53
52
 
54
53
  = render partial: 'cm_admin/main/member_custom_action_modal', locals: { cm_model: @associated_model, ar_collection: @associated_ar_object }
@@ -7,7 +7,7 @@
7
7
  .modal-dialog
8
8
  .modal-content
9
9
  .modal-header
10
- h5.modal-title id="#{custom_action.name.classify}ModalLabel" = custom_action.name.classify
10
+ h5.modal-title id="#{custom_action.name.classify}ModalLabel" = custom_action_title(custom_action)
11
11
  button.btn-close aria-label='Close' data-bs-dismiss='modal'
12
12
  .modal-body
13
13
  = render partial: custom_action.partial, locals: { ar_object: ar_object }
@@ -1,13 +1,12 @@
1
- .admin-table-index
2
- .table-top
3
- p.table-top__total-count = "#{humanized_ar_collection_count(@ar_object.pagy.count, @model.ar_model.table_name)}"
4
- // .table-top__column-action
5
- // button.secondary-btn.column-btn data-bs-target="#columnActionModal" data-bs-toggle="modal"
6
- // span
7
- // i.fa.fa-columns.bolder
8
- // span
9
- // i.fa.fa-angle-down
10
- .new-admin-table.scrollable
1
+ .table-top
2
+ p.table-top__total-count = "#{humanized_ar_collection_count(@ar_object.pagy.count, @model.ar_model.table_name)}"
3
+ // .table-top__column-action
4
+ // button.secondary-btn.column-btn data-bs-target="#columnActionModal" data-bs-toggle="modal"
5
+ // span
6
+ // i.fa.fa-columns.bolder
7
+ // span
8
+ // i.fa.fa-angle-down
9
+ .new-admin-table
11
10
  table.cm-table
12
11
  thead.cm-table__header
13
12
  tr.header-row
@@ -37,9 +36,9 @@
37
36
  - if @model
38
37
  == render partial: 'cm_admin/main/actions_dropdown', locals: { cm_model: @model, ar_object: ar_object }
39
38
 
40
- .cm-pagination
41
- .cm-pagination__lhs Showing #{@ar_object.pagy.from} to #{@ar_object.pagy.to} out of #{@ar_object.pagy.count}
42
- .cm-pagination__rhs
43
- == render partial: 'cm_admin/main/cm_pagy_nav', locals: { pagy: @ar_object.pagy }
39
+ .cm-pagination
40
+ .cm-pagination__lhs Showing #{@ar_object.pagy.from} to #{@ar_object.pagy.to} out of #{@ar_object.pagy.count}
41
+ .cm-pagination__rhs
42
+ == render partial: 'cm_admin/main/cm_pagy_nav', locals: { pagy: @ar_object.pagy }
44
43
 
45
44
  = render partial: 'cm_admin/main/member_custom_action_modal', locals: { cm_model: @model, ar_collection: @ar_object }
@@ -1,6 +1,5 @@
1
- .cm-index-page
2
- .index-page
3
- .index-page__table-container
4
- == render partial: 'cm_admin/main/associated_table'
1
+ .cm-index-page.associated-index
2
+ .cm-index-page__table-container
3
+ == render partial: 'cm_admin/main/associated_table'
5
4
 
6
- // = column_pop_up(@associated_model)
5
+ // = column_pop_up(@associated_model)
@@ -1,16 +1,15 @@
1
- .cm-index-page
2
- .index-page.page-container
3
- .sticky-container
4
- == render 'cm_admin/main/top_navbar'
5
- - if @model.filters.present? && @action.partial.nil?
6
- .index-page__filters
7
- == render partial: 'cm_admin/main/filters', locals: { filters: @model.filters }
8
- .index-page__table-container
9
- - if @action.partial
10
- == render @action.partial
11
- - else
12
- == render 'cm_admin/main/table'
1
+ .cm-index-page.cm-page-container
2
+ .sticky-container.page-top-bar
3
+ == render 'cm_admin/main/top_navbar'
4
+ - if @model.filters.present? && @action.partial.nil?
5
+ .cm-index-page__filters
6
+ == render partial: 'cm_admin/main/filters', locals: { filters: @model.filters }
7
+ .cm-index-page__table-container
8
+ - if @action.partial
9
+ == render @action.partial
10
+ - else
11
+ == render 'cm_admin/main/table'
13
12
 
14
- = column_pop_up(@model)
15
- = manage_column_pop_up(@model)
13
+ = column_pop_up(@model)
14
+ = manage_column_pop_up(@model)
16
15
 
@@ -1,5 +1,5 @@
1
- .show-page.page-container
2
- .show-page__tabs.sticky-container
1
+ .show-page.cm-page-container
2
+ .show-page__tabs.sticky-container.page-top-bar
3
3
  .cm-tabs-bar
4
4
  == render 'cm_admin/main/top_navbar'
5
5
  == render 'cm_admin/main/tabs'
@@ -19,21 +19,21 @@ html
19
19
  = render 'layouts/left_sidebar_nav'
20
20
  .panel-area
21
21
  - if defined?(@action) && (@action&.layout_type.to_s == 'cm_association_show' || @action.parent == "show")
22
- .show-page.page-container
23
- .show-page__tabs.sticky-container
22
+ .show-page.cm-page-container
23
+ .show-page__tabs.sticky-container.page-top-bar
24
24
  .cm-tabs-bar
25
25
  == render 'cm_admin/main/top_navbar'
26
26
  == render 'cm_admin/main/tabs'
27
27
  .show-page__inner.scrollable
28
28
  = yield
29
29
  - elsif defined?(@action) && (@action&.layout_type.to_s == 'cm_association_index' || @action.parent == "index")
30
- .show-page.page-container
31
- .show-page__tabs.sticky-container
30
+ .show-page.cm-page-container
31
+ .show-page__tabs.sticky-container.page-top-bar
32
32
  .cm-tabs-bar
33
33
  == render 'cm_admin/main/top_navbar'
34
34
  == render 'cm_admin/main/tabs'
35
35
  - if @associated_model && @associated_model.filters.present?
36
- .index-page__filters
36
+ .filters-bar
37
37
  == render partial: 'cm_admin/main/filters', locals: { filters: @associated_model.filters }
38
38
  = yield
39
39
  - else
@@ -23,7 +23,7 @@ module CmAdmin
23
23
  include Pagy::Backend
24
24
  include Models::Blocks
25
25
  include Models::DslMethod
26
- attr_accessor :available_actions, :actions_set, :available_fields, :permitted_fields,
26
+ attr_accessor :available_actions, :actions_set, :available_fields, :additional_permitted_fields,
27
27
  :current_action, :params, :filters, :available_tabs, :icon_name
28
28
  attr_reader :name, :ar_model, :is_visible_on_sidebar, :importer
29
29
 
@@ -33,6 +33,7 @@ module CmAdmin
33
33
  @is_visible_on_sidebar = true
34
34
  @icon_name = 'fa fa-th-large'
35
35
  @available_actions ||= []
36
+ @additional_permitted_fields ||= []
36
37
  @current_action = nil
37
38
  @available_tabs ||= []
38
39
  @available_fields ||= {index: [], show: [], edit: {fields: []}, new: {fields: []}}
@@ -94,6 +95,10 @@ module CmAdmin
94
95
  @icon_name = name
95
96
  end
96
97
 
98
+ def permit_additional_fields(fields=[])
99
+ @additional_permitted_fields = fields
100
+ end
101
+
97
102
  # Shared between export controller and resource controller
98
103
  def filter_params(params)
99
104
  # OPTIMIZE: Need to check if we can permit the filter_params in a better way
@@ -4,7 +4,7 @@ module CmAdmin
4
4
  module Models
5
5
  class Action
6
6
  include Actions::Blocks
7
- attr_accessor :name, :verb, :layout_type, :layout, :partial, :path, :page_title, :page_description,
7
+ attr_accessor :name, :display_name, :verb, :layout_type, :layout, :partial, :path, :page_title, :page_description,
8
8
  :child_records, :is_nested_field, :nested_table_name, :parent, :display_if, :route_type, :code_block,
9
9
  :display_type, :action_type, :redirection_url, :sort_direction, :sort_column, :icon_name
10
10
 
@@ -1,8 +1,13 @@
1
+ require_relative 'utils/associations'
2
+
1
3
  module CmAdmin
2
4
  module Models
3
5
  class Column
6
+ include Utils::Associations
7
+
4
8
  attr_accessor :field_name, :field_type, :header, :format, :prefix, :suffix, :exportable, :round, :height, :width,
5
- :cm_css_class, :link, :url, :custom_method, :helper_method, :managable, :lockable, :drawer_partial, :tag_class, :display_if
9
+ :cm_css_class, :link, :url, :custom_method, :helper_method, :managable, :lockable, :drawer_partial, :tag_class,
10
+ :display_if, :association_name, :association_type
6
11
 
7
12
  def initialize(field_name, attributes = {})
8
13
  @field_name = field_name
@@ -16,11 +21,20 @@ module CmAdmin
16
21
  self.height = 50 if self.field_type == :image && self.height.nil?
17
22
  self.width = 50 if self.field_type == :image && self.width.nil?
18
23
  self.display_if = lambda { |arg| return true } if self.display_if.nil?
24
+
25
+ validation_for_association
19
26
  end
20
27
 
21
28
  #returns a string value as a header (either field_name or value present in header attribute)
22
29
  def format_header
23
- self.header.present? ? self.header.to_s.gsub(/_/, ' ')&.upcase : self.field_name.to_s.gsub(/_/, ' ').upcase
30
+ header_value = if self.header.present?
31
+ self.header
32
+ elsif self.field_type.to_s == 'association'
33
+ self.association_name
34
+ else
35
+ self.field_name
36
+ end
37
+ header_value.to_s.titleize.upcase
24
38
  end
25
39
 
26
40
  def set_default_values
@@ -35,7 +49,6 @@ module CmAdmin
35
49
  model.available_fields.find { |i| i.name == search_hash[:name] }
36
50
  end
37
51
  end
38
-
39
52
  end
40
53
  end
41
54
  end
@@ -77,10 +77,23 @@ module CmAdmin
77
77
  def column(field_name, options={})
78
78
  @available_fields[@current_action.name.to_sym] ||= []
79
79
  if @available_fields[@current_action.name.to_sym].select{|x| x.lockable}.size > 0 && options[:lockable]
80
- raise "Only one column can be locked in a table."
80
+ raise 'Only one column can be locked in a table.'
81
81
  end
82
82
 
83
- unless @available_fields[@current_action.name.to_sym].map{|x| x.field_name.to_sym}.include?(field_name)
83
+ duplicate_columns = @available_fields[@current_action.name.to_sym].filter{|x| x.field_name.to_sym == field_name}
84
+ terminate = false
85
+
86
+ if duplicate_columns.size.positive?
87
+ duplicate_columns.each do |column|
88
+ if options[:field_type].to_s != 'association'
89
+ terminate = true
90
+ elsif options[:field_type].to_s == 'association' && column.association_name.to_s == options[:association_name].to_s
91
+ terminate = true
92
+ end
93
+ end
94
+ end
95
+
96
+ unless terminate
84
97
  @available_fields[@current_action.name.to_sym] << CmAdmin::Models::Column.new(field_name, options)
85
98
  end
86
99
  end
@@ -107,9 +120,9 @@ module CmAdmin
107
120
  # end
108
121
  # end
109
122
  # end
110
- def custom_action(name: nil, verb: nil, layout: nil, layout_type: nil, partial: nil, path: nil, display_type: nil, display_if: lambda { |arg| return true }, route_type: nil, icon_name: 'fa fa-th-large', &block)
123
+ def custom_action(name: nil, display_name: nil, verb: nil, layout: nil, layout_type: nil, partial: nil, path: nil, display_type: nil, display_if: lambda { |arg| return true }, route_type: nil, icon_name: 'fa fa-th-large', &block)
111
124
  action = CmAdmin::Models::CustomAction.new(
112
- name: name, verb: verb, layout: layout, layout_type: layout_type, partial: partial, path: path,
125
+ name: name, display_name: display_name, verb: verb, layout: layout, layout_type: layout_type, partial: partial, path: path,
113
126
  parent: self.current_action.name, display_type: display_type, display_if: display_if,
114
127
  action_type: :custom, route_type: route_type, icon_name: icon_name, &block)
115
128
  @available_actions << action
@@ -1,9 +1,13 @@
1
+ require_relative 'utils/associations'
2
+
1
3
  module CmAdmin
2
4
  module Models
3
5
  class Field
6
+ include Utils::Associations
4
7
 
5
8
  attr_accessor :field_name, :label, :header, :field_type, :format, :precision, :height,
6
- :width, :helper_method, :preview, :custom_link, :precision, :prefix, :suffix, :tag_class, :display_if
9
+ :width, :helper_method, :preview, :custom_link, :prefix, :suffix, :tag_class,
10
+ :display_if, :association_name, :association_type
7
11
 
8
12
  def initialize(field_name, attributes = {})
9
13
  @field_name = field_name
@@ -14,6 +18,8 @@ module CmAdmin
14
18
  self.height = 50 if self.field_type == :image && self.height.nil?
15
19
  self.width = 50 if self.field_type == :image && self.width.nil?
16
20
  self.display_if = lambda { |arg| return true } if self.display_if.nil?
21
+
22
+ validation_for_association
17
23
  end
18
24
 
19
25
  def set_default_values
@@ -0,0 +1,25 @@
1
+ module CmAdmin
2
+ module Models
3
+ module Utils
4
+ module Associations
5
+ extend ActiveSupport::Concern
6
+
7
+ def validation_for_association
8
+ return unless field_type.to_s == "association"
9
+
10
+ raise ArgumentError, 'Expected association_name and association_type to be present' if association_name.nil? || association_type.nil?
11
+
12
+ if association_type.to_s == 'polymorphic'
13
+ raise ArgumentError, "Expected field_name - #{field_name} - to be an array of hash. Eg, [{table_name_1: 'column_name_1'}, {table_name_2: 'column_name_2'}]" unless field_name.is_a?(Array)
14
+
15
+ field_name.each do |element|
16
+ raise ArgumentError, "Expected element #{element} to be a hash. Eg, [{table_name_1: 'column_name_1'}, {table_name_2: 'column_name_2'}]" unless element.is_a?(Hash)
17
+ end
18
+ elsif ['belongs_to', 'has_one'].include? association_type.to_s
19
+ raise ArgumentError, "Expected field_name - #{field_name} to be a String or Symbol" unless field_name.is_a?(Symbol) || field_name.is_a?(String)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -1,3 +1,3 @@
1
1
  module CmAdmin
2
- VERSION = '0.8.9'
2
+ VERSION = '0.9.0'
3
3
  end