cm-admin 0.8.9 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) 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 +24 -11
  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 +119 -50
  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 +47 -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 +34 -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/_nested_fields.html.slim +26 -9
  32. data/app/views/cm_admin/main/_nested_table_form.html.slim +9 -10
  33. data/app/views/cm_admin/main/_table.html.slim +13 -14
  34. data/app/views/cm_admin/main/_tabs.html.slim +1 -1
  35. data/app/views/cm_admin/main/associated_index.html.slim +4 -5
  36. data/app/views/cm_admin/main/index.html.slim +13 -14
  37. data/app/views/cm_admin/main/show.html.slim +2 -2
  38. data/app/views/layouts/cm_admin.html.slim +5 -5
  39. data/lib/cm_admin/model.rb +6 -1
  40. data/lib/cm_admin/models/action.rb +1 -1
  41. data/lib/cm_admin/models/column.rb +16 -3
  42. data/lib/cm_admin/models/dsl_method.rb +17 -4
  43. data/lib/cm_admin/models/field.rb +7 -1
  44. data/lib/cm_admin/models/filter.rb +1 -1
  45. data/lib/cm_admin/models/utils/associations.rb +25 -0
  46. data/lib/cm_admin/version.rb +1 -1
  47. data/lib/cm_admin/view_helpers/field_display_helper.rb +21 -1
  48. data/lib/cm_admin/view_helpers/page_info_helper.rb +11 -3
  49. data/package-lock.json +2868 -229
  50. data/package.json +2 -0
  51. data/tmp/cache/webpacker/last-compilation-digest-development +1 -1
  52. data/yarn.lock +1656 -48
  53. 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,34 @@ $(document).on('click', '.drawer-close', function(e) {
70
73
  setTimeout(() => {
71
74
  $('.cm-drawer').addClass('hidden');
72
75
  }, 300);
73
- });
76
+ });
77
+
78
+ $(document).on('cocoon:after-insert', '.nested-field-wrapper', function(e) {
79
+ e.stopPropagation();
80
+ replaceAccordionTitle($(this))
81
+ });
82
+
83
+ $(document).on('cocoon:after-remove', '.nested-field-wrapper', function(e) {
84
+ e.stopPropagation();
85
+ replaceAccordionTitle($(this))
86
+ });
87
+
88
+ $(document).ready( function () {
89
+ $('.nested-field-wrapper').each(function() {
90
+ replaceAccordionTitle($(this))
91
+ })
92
+ });
93
+
94
+ var replaceAccordionTitle = function(element) {
95
+ var i = 0;
96
+ var table_name = $(element).data('table-name')
97
+ var model_name = $(element).data('model-name')
98
+ $(element).find('.accordion-item:visible').each(function() {
99
+ i++;
100
+ var accordion_title = model_name + ' ' + i
101
+ var accordion_id = table_name + '-' + i
102
+ $(this).find('.accordion-button').text(accordion_title);
103
+ $(this).find('.accordion-button').attr('data-bs-target', '#' + accordion_id);
104
+ $(this).find('.accordion-collapse').attr('id', accordion_id);
105
+ });
106
+ }
@@ -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,9 +1,26 @@
1
- .nested-fields class=assoc_name
2
- - @model.available_fields[ action(action_name) ][assoc_name].each do |field|
3
- .row
4
- .col-sm-10
5
- = input_field_for_column(f, field)
6
- .col-sm-2
7
- - unless field.input_type == :hidden
8
- - if @reflections.select {|x| x if x.name == assoc_name}.first.macro == :has_many
9
- = link_to_remove_association "x", f
1
+ - fields = @model.available_fields[ action(action_name) ][assoc_name]
2
+ - if fields.count == 1
3
+ .nested-single-field.nested-fields
4
+ - fields.each do |field|
5
+ .field-input
6
+ = input_field_for_column(f, field)
7
+ .field-remove-action
8
+ - unless field.input_type == :hidden
9
+ - if @reflections.select {|x| x if x.name == assoc_name}.first.macro == :has_many
10
+ = link_to_remove_association "", f, class: 'fa fa-times'
11
+ - else
12
+ .accordion-item.nested-fields
13
+ h2#headingOne.accordion-header
14
+ button.accordion-button[type="button" data-bs-toggle="collapse" data-bs-target="##{assoc_name}-#{f.object.id}" aria-expanded="true" aria-controls="collapseOne"]
15
+ | Chapter 1
16
+ .field-remove-action
17
+ - if @reflections.select {|x| x if x.name == assoc_name}.first.macro == :has_many
18
+ = link_to_remove_association "", f, class: 'fa fa-trash ghost-btn accordion-delete-btn'
19
+ div.accordion-collapse.collapse.show[aria-labelledby="headingOne" id="#{assoc_name}-#{f.object.id}"]
20
+ .accordion-body
21
+ - fields.each do |field|
22
+ .form-field
23
+ .field-label-wrapper
24
+ label.field-label = field.field_name.to_s.titleize
25
+ .field-input-wrapper
26
+ = input_field_for_column(f, field)
@@ -1,10 +1,9 @@
1
- .nested-field-wrapper
2
- label.field-label = table_name.to_s.titleize
3
- - initialized_record_count = 1
4
- = f.fields_for table_name do |record|
5
- - if record.object.persisted? || initialized_record_count == 1
6
- = render partial: '/cm_admin/main/nested_fields', locals: { f: record, assoc_name: table_name }
7
- - initialized_record_count += 1 if record.object.new_record?
8
- - if @reflections.select {|x| x if x.name == table_name}.first.macro == :has_many
9
- .links
10
- = link_to_add_association "+ Add #{table_name.to_s.titleize}", f, table_name, partial: '/cm_admin/main/nested_fields', render_options: {locals: { assoc_name: table_name }}
1
+ .nested-field-wrapper data-table-name=table_name data-model-name=table_name.to_s.classify
2
+ label.nested-field-label = table_name.to_s.titleize
3
+ .accordion.nested-form-accordion
4
+ = f.fields_for table_name do |record|
5
+ - if record.object.persisted?
6
+ = render partial: '/cm_admin/main/nested_fields', locals: { f: record, assoc_name: table_name }
7
+ - if @reflections.select {|x| x if x.name == table_name}.first.macro == :has_many
8
+ .links
9
+ = link_to_add_association "+ Add #{table_name.to_s.titleize}", f, table_name, partial: '/cm_admin/main/nested_fields', render_options: {locals: { assoc_name: table_name }}, class: 'd-inline-block secondary-btn mt-2'
@@ -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 }
@@ -4,4 +4,4 @@ ul.nav.nav-pills
4
4
  - if nav_item.custom_action.empty? || (nav_item.custom_action.present? && policy([:cm_admin, @model.name.classify.constantize]).send(:"#{nav_item.custom_action}?"))
5
5
  li.nav-item
6
6
  - nav_item_action_name = nav_item.custom_action.present? ? nav_item.custom_action : 'show'
7
- = link_to nav_item.nav_item_name.to_s.titleize, cm_admin.send("#{@ar_object.model_name.singular}_#{nav_item_action_name}_path", @ar_object.id), class: "nav-link #{ nav_item_action_name == action_name ? 'active' : ''}"
7
+ = link_to tab_display_name(nav_item.nav_item_name), cm_admin.send("#{@ar_object.model_name.singular}_#{nav_item_action_name}_path", @ar_object.id), class: "nav-link #{ nav_item_action_name == action_name ? 'active' : ''}"
@@ -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