cm-admin 1.1.7 → 1.1.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.vscode/settings.json +3 -0
  4. data/Gemfile.lock +1 -1
  5. data/app/assets/javascripts/cm_admin/scaffolds.js +1 -1
  6. data/app/assets/stylesheets/cm_admin/base/navbar.scss +13 -39
  7. data/app/assets/stylesheets/cm_admin/base/quicksearch.scss +3 -4
  8. data/app/assets/stylesheets/cm_admin/base/show.scss +4 -15
  9. data/app/assets/stylesheets/cm_admin/base/table.scss +2 -14
  10. data/app/assets/stylesheets/cm_admin/cm_admin.css.scss +1 -0
  11. data/app/assets/stylesheets/cm_admin/components/_buttons.scss +29 -135
  12. data/app/assets/stylesheets/cm_admin/dependency/bootstrap.min.css +4 -5
  13. data/app/assets/stylesheets/cm_admin/dependency/jquery-jgrowl.min.css +1 -0
  14. data/app/assets/stylesheets/cm_admin/helpers/_variable.scss +31 -30
  15. data/app/assets/stylesheets/cm_admin/pages/import_page.scss +3 -10
  16. data/app/controllers/cm_admin/resource_controller.rb +13 -9
  17. data/app/views/cm_admin/main/_actions_dropdown.html.slim +1 -3
  18. data/app/views/cm_admin/main/_associated_table.html.slim +1 -1
  19. data/app/views/cm_admin/main/_nested_fields.html.slim +2 -1
  20. data/app/views/cm_admin/main/_nested_table_form.html.slim +1 -1
  21. data/app/views/cm_admin/main/_tabs.html.slim +1 -1
  22. data/app/views/cm_admin/main/_top_navbar.html.slim +11 -17
  23. data/app/views/cm_admin/main/history.html.slim +3 -4
  24. data/app/views/cm_admin/main/import_form.html.slim +2 -2
  25. data/app/views/cm_admin/main/new.html.slim +1 -1
  26. data/app/views/cm_admin/main/show.html.slim +3 -4
  27. data/app/views/layouts/_cm_flash_message.html.slim +3 -3
  28. data/app/views/layouts/_quick_links.html.slim +2 -2
  29. data/app/views/layouts/cm_admin.html.slim +10 -12
  30. data/lib/cm_admin/models/filter.rb +55 -29
  31. data/lib/cm_admin/models/form_field.rb +18 -3
  32. data/lib/cm_admin/models/utils/helpers.rb +14 -0
  33. data/lib/cm_admin/version.rb +1 -1
  34. data/lib/cm_admin/view_helpers/filter_helper.rb +1 -1
  35. data/lib/cm_admin/view_helpers/form_field_helper.rb +16 -17
  36. data/lib/cm_admin/view_helpers/form_helper.rb +2 -1
  37. data/lib/cm_admin/view_helpers/manage_column_popup_helper.rb +2 -2
  38. data/lib/cm_admin/view_helpers/page_info_helper.rb +4 -4
  39. data/lib/cm_admin/view_helpers.rb +2 -1
  40. metadata +5 -2
@@ -0,0 +1 @@
1
+ .jGrowl{z-index:9999;color:#fff;font-size:12px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;position:fixed}.jGrowl.top-left{left:0;top:0}.jGrowl.top-right{right:0;top:0}.jGrowl.bottom-left{left:0;bottom:0}.jGrowl.bottom-right{right:0;bottom:0}.jGrowl.center{top:0;width:50%;left:25%}.jGrowl.center .jGrowl-closer,.jGrowl.center .jGrowl-notification{margin-left:auto;margin-right:auto}.jGrowl-notification{background-color:#000;opacity:.9;zoom:1;width:250px;padding:10px;margin:10px;text-align:left;display:none;border-radius:5px;min-height:40px}.jGrowl-notification .ui-state-highlight,.jGrowl-notification .ui-widget-content .ui-state-highlight,.jGrowl-notification .ui-widget-header .ui-state-highlight{border:1px solid #000;background:#000;color:#fff}.jGrowl-notification .jGrowl-header{font-weight:700;font-size:.85em}.jGrowl-notification .jGrowl-close{background-color:transparent;color:inherit;border:none;z-index:99;float:right;font-weight:700;font-size:1em;cursor:pointer}.jGrowl-closer{background-color:#000;opacity:.9;zoom:1;width:250px;padding:10px;margin:10px;text-align:left;display:none;border-radius:5px;padding-top:4px;padding-bottom:4px;cursor:pointer;font-size:.9em;font-weight:700;text-align:center}.jGrowl-closer .ui-state-highlight,.jGrowl-closer .ui-widget-content .ui-state-highlight,.jGrowl-closer .ui-widget-header .ui-state-highlight{border:1px solid #000;background:#000;color:#fff}@media print{.jGrowl{display:none}}
@@ -1,54 +1,55 @@
1
1
  /* ==== Color Variables ==== */
2
2
 
3
3
  /* Brand Color */
4
- $brand-color: #6554E0;
4
+ $brand-color: #6554e0;
5
+ $brand-hover-color: #e6e4fa;
5
6
 
6
7
  /* Semantic Color */
7
- $informative-clr: #2F80ED;
8
- $error-clr: #F83636;
9
- $warning-clr: #FFC845;
10
- $positive-clr: #30C39E;
11
- $disabled-clr: #9CA7AE;
8
+ $informative-clr: #2f80ed;
9
+ $error-clr: #f83636;
10
+ $warning-clr: #ffc845;
11
+ $positive-clr: #30c39e;
12
+ $disabled-clr: #9ca7ae;
12
13
 
13
14
  /* Blue Colors */
14
- $blue-regular-clr: #2F80ED;
15
- $blue-light-clr: #CDE1FB;
16
- $blue-lightest-clr: #EEF5FE;
15
+ $blue-regular-clr: #2f80ed;
16
+ $blue-light-clr: #cde1fb;
17
+ $blue-lightest-clr: #eef5fe;
17
18
 
18
19
  /* Red Colors */
19
- $red-regular-clr: #F83636;
20
- $red-light-clr: #FDCFCF;
21
- $red-lightest-clr: #FEEFEF;
20
+ $red-regular-clr: #f83636;
21
+ $red-light-clr: #fdcfcf;
22
+ $red-lightest-clr: #feefef;
22
23
 
23
24
  /* Yellow Colors */
24
- $yellow-regular-clr: #FFC845;
25
- $yellow-light-clr: #FFEFC7;
26
- $yellow-lightest-clr: #FFF8E9;
25
+ $yellow-regular-clr: #ffc845;
26
+ $yellow-light-clr: #ffefc7;
27
+ $yellow-lightest-clr: #fff8e9;
27
28
 
28
29
  /* Green Colors */
29
- $green-regular-clr: #30C39E;
30
- $green-light-clr: #C1EDE2;
31
- $green-lightest-clr: #EEFAF7;
30
+ $green-regular-clr: #30c39e;
31
+ $green-light-clr: #c1ede2;
32
+ $green-lightest-clr: #eefaf7;
32
33
 
33
34
  /* Grey Colors */
34
- $grey-regular-clr: #C7CED5;
35
- $grey-light-clr: #D9DEE3;
36
- $grey-lighter-clr: #F3F4F6;
37
- $grey-lightest-clr: #F8F9FA;
35
+ $grey-regular-clr: #c7ced5;
36
+ $grey-light-clr: #d9dee3;
37
+ $grey-lighter-clr: #f3f4f6;
38
+ $grey-lightest-clr: #f8f9fa;
38
39
  $grey-dark-clr: #828282;
39
40
 
40
41
  /* Ink Colors */
41
- $ink-regular-clr: #1D2129;
42
- $ink-light-clr: #3B4352;
43
- $ink-lighter-clr: #6B7586;
44
- $ink-lightest-clr: #9CA7AE;
42
+ $ink-regular-clr: #1d2129;
43
+ $ink-light-clr: #3b4352;
44
+ $ink-lighter-clr: #6b7586;
45
+ $ink-lightest-clr: #9ca7ae;
45
46
 
46
47
  /* Text Colors */
47
- $primary-text-clr: #1D2129;
48
- $subdued-text-clr: #D9DEE3;
48
+ $primary-text-clr: #1d2129;
49
+ $subdued-text-clr: #d9dee3;
49
50
 
50
51
  /* Common Colors */
51
- $white: #FFFFFF;
52
+ $white: #ffffff;
52
53
  $black: #000000;
53
54
 
54
55
  // Gradient Colors
@@ -56,7 +57,7 @@ $gradient-one: linear-gradient(270deg, $grey-lighter-clr 81.75%, rgba(243, 244,
56
57
  $cta-hover-gradient: linear-gradient(0deg, rgba(0, 0, 0, 0.24), rgba(0, 0, 0, 0.24)), $brand-color;
57
58
 
58
59
  /* Typography */
59
- $primary-font: 'Open Sans', sans-serif;
60
+ $primary-font: "Open Sans", sans-serif;
60
61
  $font-size: (
61
62
  24: 24px,
62
63
  18: 18px,
@@ -25,7 +25,7 @@
25
25
  line-height: 22px;
26
26
  margin-bottom: 0;
27
27
  }
28
- }
28
+ }
29
29
  &__body {
30
30
  padding: 16px 24px;
31
31
  .body-title {
@@ -63,9 +63,6 @@
63
63
 
64
64
  .actions-wrapper {
65
65
  margin-top: 32px;
66
- button {
67
- padding: 5px 10px;
68
- }
69
66
  }
70
67
 
71
68
  //form UI
@@ -90,7 +87,7 @@
90
87
  margin-bottom: 16px;
91
88
  text-transform: uppercase;
92
89
  }
93
- .steps-wrapper {
90
+ .steps-wrapper {
94
91
  .steps-title {
95
92
  @include font($size: size(16), $weight: bold);
96
93
  font-family: $primary-font;
@@ -116,10 +113,6 @@
116
113
  }
117
114
  }
118
115
  }
119
- .import-btn {
120
- padding: 5px 10px;
121
- }
122
116
  }
123
-
124
117
  }
125
- }
118
+ }
@@ -137,15 +137,19 @@ module CmAdmin
137
137
  data = @action.parent == "index" ? @ar_object.data : @ar_object
138
138
  format.html { render @action.partial }
139
139
  else
140
- response_object = @action.code_block.call(@response_object)
141
- if response_object.class == Hash
142
- format.json { render json: response_object }
143
- elsif response_object.errors.empty?
144
- redirect_url = @model.current_action.redirection_url || @action.redirection_url || request.referrer || "/cm_admin/#{@model.ar_model.table_name}/#{@response_object.id}"
145
- format.html { redirect_to redirect_url, notice: "#{@action.name.titleize} is successful" }
146
- else
147
- error_messages = response_object.errors.full_messages.map{|error_message| "<li>#{error_message}</li>"}.join
148
- format.html { redirect_to request.referrer, alert: "<b>#{@action.name.titleize} is unsuccessful</b><br /><ul>#{error_messages}</ul>" }
140
+ begin
141
+ response_object = @action.code_block.call(@response_object)
142
+ if response_object.class == Hash
143
+ format.json { render json: response_object }
144
+ elsif response_object.errors.empty?
145
+ redirect_url = @model.current_action.redirection_url || @action.redirection_url || request.referrer || "/cm_admin/#{@model.ar_model.table_name}/#{@response_object.id}"
146
+ format.html { redirect_to redirect_url, notice: "#{@action.name.titleize} is successful" }
147
+ else
148
+ error_messages = response_object.errors.full_messages.map{|error_message| "<li>#{error_message}</li>"}.join
149
+ format.html { redirect_to request.referrer, alert: "<b>#{@action.name.titleize} is unsuccessful</b><br /><ul>#{error_messages}</ul>" }
150
+ end
151
+ rescue => exception
152
+ format.html { redirect_to request.referrer, alert: "<b>#{@action.name.titleize} is unsuccessful</b><br /><p>#{exception.message}</p>" }
149
153
  end
150
154
  end
151
155
  end
@@ -5,11 +5,9 @@
5
5
  - if custom_actions.any? || edit_action.present? || destroy_action.present?
6
6
  td.row-action-cell
7
7
  .row-action-tool
8
- button.secondary-btn.tool-btn
8
+ button.btn-ghost.dropdown-toggle
9
9
  span
10
10
  i.fa.fa-bars.bolder
11
- span
12
- i.fa.fa-angle-down
13
11
  .popup-card.table-export-popup.hidden
14
12
  - if edit_action.present?
15
13
  = link_to cm_admin.send("#{current_model.name.underscore}_edit_path", ar_object.id) do
@@ -8,7 +8,7 @@
8
8
  - association = @ar_object.class.reflect_on_all_associations.select{|x| x.name == @associated_model.name.tableize.to_sym }.first
9
9
  - polymorphic_name = (association && association.inverse_of && association.inverse_of.options[:polymorphic]) ? association.inverse_of.name : ''
10
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
11
+ button.btn-secondary Add
12
12
  / button.secondary-btn.column-btn data-target="#columnActionModal" data-toggle="modal" type="button"
13
13
  / span
14
14
  / i.fa.fa-columns.bolder
@@ -15,7 +15,8 @@
15
15
  | Chapter 1
16
16
  .field-remove-action
17
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'
18
+ .accordion-delete-btn
19
+ = link_to_remove_association "", f, class: 'fa fa-trash btn-ghost'
19
20
  div.accordion-collapse.collapse.show[aria-labelledby="headingOne" id="#{assoc_name}-#{f.object.id}"]
20
21
  .accordion-body
21
22
  - fields.each do |field|
@@ -7,4 +7,4 @@
7
7
  = render partial: '/cm_admin/main/nested_fields', locals: { f: record, assoc_name: assoc_name, section: section }
8
8
  - if @reflections.select {|x| x if x.name == assoc_name}.first.macro == :has_many
9
9
  .links
10
- = link_to_add_association "+ Add #{assoc_name.to_s.titleize}", f, table_name, partial: '/cm_admin/main/nested_fields', render_options: {locals: { assoc_name: assoc_name, section: section }}, class: 'd-inline-block secondary-btn mt-2'
10
+ = link_to_add_association "+ Add #{assoc_name.to_s.titleize}", f, table_name, partial: '/cm_admin/main/nested_fields', render_options: {locals: { assoc_name: assoc_name, section: section }}, class: 'd-inline-block btn-secondary mt-2'
@@ -1,4 +1,4 @@
1
- ul.nav.nav-pills
1
+ ul.tabs
2
2
  - @model.available_tabs.each do |nav_item|
3
3
  - if nav_item.display_if.call(@ar_object)
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}?"))
@@ -1,33 +1,27 @@
1
- .cm-navbar
2
- .cm-navbar__lhs
1
+ .entity-header
2
+ .entity-header__info
3
3
  - if cm_admin.method_defined?(:"#{@model.name.underscore}_index_path") && (@model.current_action.name == 'show' || @model.current_action.layout_type.present?)
4
- .bread-crumb-area
5
- .breadcrumb-text
6
- = link_to "#{@model.name.titleize.pluralize} /", cm_admin.send(:"#{@model.name.underscore}_index_path")
7
- .nav-title-area
8
- p.title-text = action_title
9
- p.title-sub-text = action_description
10
- .cm-navbar__rhs
4
+ .breadcrumb
5
+ = link_to "#{@model.name.titleize.pluralize} /", cm_admin.send(:"#{@model.name.underscore}_index_path"), class: 'text-reset'
6
+ h4 = action_title
7
+ p.mb-0.text-body-secondary = action_description
8
+ .entity-header__actions
11
9
  - if @model.current_action.name == 'index'
12
10
  - if has_valid_policy(@model.name, :exportable)
13
11
  .export-container
14
12
  .dropdown
15
- button.secondary-btn data-bs-toggle='dropdown'
16
- span
13
+ button.btn-secondary.dropdown-toggle data-bs-toggle='dropdown'
17
14
  i.fa.fa-arrow-down
18
- span
19
15
  | Export
20
- span
21
- i.fa.fa-angle-down
22
16
  ul.dropdown-menu.export-popup
23
17
  li
24
18
  .popup-option.pointer data-bs-toggle='modal' data-bs-target='#exportmodal'
25
19
  span Export
26
20
  - if @model.importer && has_valid_policy(@model.name, :importable)
27
- = link_to 'Import', cm_admin.send(:"#{@model.name.underscore}_import_path"), class: 'primary-btn ml-2'
21
+ = link_to 'Import', cm_admin.send(:"#{@model.name.underscore}_import_path"), class: 'btn-primary ml-2'
28
22
  - new_action = @model.available_actions.select{|act| act if act.action_type.eql?(:default) && act.name.eql?('new')}
29
23
  - if new_action.any? && policy([:cm_admin, @model.name.classify.constantize]).new?
30
- = link_to 'Add', cm_admin.send(:"#{@model.name.underscore}_new_path"), class: 'primary-btn ml-2'
24
+ = link_to 'Add', cm_admin.send(:"#{@model.name.underscore}_new_path"), class: 'btn-primary ml-2'
31
25
  - @model.available_actions.select{|act| act if act.route_type == 'collection'}.each do |custom_action|
32
26
  = custom_action_items(custom_action, 'index')
33
27
  - elsif @model.current_action.name == 'show'
@@ -36,4 +30,4 @@
36
30
 
37
31
  - edit_action = @model.available_actions.select{|act| act if act.action_type.eql?(:default) && act.name.eql?('edit')}
38
32
  - if edit_action.any? && policy([:cm_admin, @model.name.classify.constantize]).edit?
39
- = link_to "Edit #{@model.name.titleize.pluralize}", cm_admin.send(:"#{@model.name.underscore}_edit_path", @ar_object), class: 'primary-btn ml-2'
33
+ = link_to "Edit #{@model.name.titleize.pluralize}", cm_admin.send(:"#{@model.name.underscore}_edit_path", @ar_object), class: 'btn-primary ml-2'
@@ -1,8 +1,7 @@
1
1
  .show-page.cm-page-container
2
- .show-page__tabs.sticky-container.page-top-bar
3
- .cm-tabs-bar
4
- == render 'cm_admin/main/top_navbar'
5
- == render 'cm_admin/main/tabs'
2
+ .show-page__header.sticky-container.page-top-bar
3
+ == render 'cm_admin/main/top_navbar'
4
+ == render 'cm_admin/main/tabs'
6
5
  .show-page__inner.scrollable
7
6
  .history-box
8
7
  - @ar_object.action_trails.each do |at|
@@ -12,7 +12,7 @@
12
12
  p.success-msg Your file has been uploaded and it will be processed soon.
13
13
  / p.success-msg-info An email will be sent once the process is completed. If there are any problems with the import, we'll let you know through an email.
14
14
  .actions-wrapper
15
- a.secondary-btn href="#{cm_admin.send(:"#{@model.name.underscore}_import_path")}" Import new data
15
+ a.btn-secondary href="#{cm_admin.send(:"#{@model.name.underscore}_import_path")}" Import new data
16
16
  / button.cta-btn.ml-2 Back to Page_Name
17
17
  - else
18
18
  = simple_form_for(FileImport.new, url: "/admin/#{@model.ar_model.table_name}/import", method: :post, html: { class: "csv-import-form" }) do |f|
@@ -32,4 +32,4 @@
32
32
  li Add your data on the file without changing the format
33
33
  li Save the file as a csv
34
34
  li Upload the file in the field above
35
- = f.button :submit, class: "cta-btn import-btn", value: 'Import data'
35
+ = f.button :submit, class: "btn-cta", value: 'Import data'
@@ -16,4 +16,4 @@
16
16
  - @ar_object.errors.full_messages.each do |error_message|
17
17
  li = error_message
18
18
 
19
- = generate_form(@ar_object.class.name.constantize.new, @model)
19
+ = generate_form(@ar_object, @model)
@@ -1,8 +1,7 @@
1
1
  .show-page.cm-page-container
2
- .show-page__tabs.sticky-container.page-top-bar
3
- .cm-tabs-bar
4
- == render 'cm_admin/main/top_navbar'
5
- == render 'cm_admin/main/tabs'
2
+ .show-page__header.sticky-container.page-top-bar
3
+ == render 'cm_admin/main/top_navbar'
4
+ == render 'cm_admin/main/tabs'
6
5
  .show-page__inner.scrollable
7
6
  - if @action.partial
8
7
  == render @action.partial
@@ -1,9 +1,9 @@
1
1
  - if flash[:notice].present?
2
2
  javascript:
3
- $.jGrowl("#{flash[:notice]}", {theme: 'notice'})
3
+ $.jGrowl("#{flash[:notice]}", { theme: 'notice' })
4
4
  - elsif flash[:success].present?
5
5
  javascript:
6
- $.jGrowl("#{flash[:success]}", {theme: 'success'})
6
+ $.jGrowl("#{flash[:success]}", { theme: 'success' })
7
7
  - elsif flash[:alert].present?
8
8
  javascript:
9
- $.jGrowl("#{flash[:alert].html_safe}", {theme: 'error'})
9
+ $.jGrowl("#{flash[:alert].html_safe}", { theme: 'error' })
@@ -19,7 +19,7 @@
19
19
  span.move-arrow
20
20
  i.fa.fa-long-arrow-down
21
21
  span Select
22
- button.text-btn.enter-btn
22
+ p.enter-text
23
23
  | ENTER
24
- button.text-btn.open-btn
24
+ p.open-text
25
25
  | open
@@ -25,22 +25,20 @@ html
25
25
  .panel-area
26
26
  - if defined?(@action) && (@action&.layout_type.to_s == 'cm_association_show' || @action.parent == "show")
27
27
  .show-page.cm-page-container
28
- .show-page__tabs.sticky-container.page-top-bar
29
- .cm-tabs-bar
30
- == render 'cm_admin/main/top_navbar'
31
- == render 'cm_admin/main/tabs'
28
+ .show-page__header.sticky-container.page-top-bar
29
+ == render 'cm_admin/main/top_navbar'
30
+ == render 'cm_admin/main/tabs'
32
31
  .show-page__inner.scrollable
33
32
  = yield
34
33
  - elsif defined?(@action) && (@action&.layout_type.to_s == 'cm_association_index' || @action.parent == "index")
35
34
  .show-page.cm-page-container
36
- .show-page__tabs.sticky-container.page-top-bar
37
- .cm-tabs-bar
38
- == render 'cm_admin/main/top_navbar'
39
- - if @ar_object.model_name
40
- == render 'cm_admin/main/tabs'
41
- - if @associated_model && @associated_model.filters.present?
42
- .filters-bar
43
- == render partial: 'cm_admin/main/filters', locals: { filters: @associated_model.filters }
35
+ .show-page__header.sticky-container.page-top-bar
36
+ == render 'cm_admin/main/top_navbar'
37
+ - if @ar_object.model_name
38
+ == render 'cm_admin/main/tabs'
39
+ - if @associated_model && @associated_model.filters.present?
40
+ .filters-bar
41
+ == render partial: 'cm_admin/main/filters', locals: { filters: @associated_model.filters }
44
42
  = yield
45
43
  - else
46
44
  = yield
@@ -1,6 +1,10 @@
1
+ require_relative 'utils/helpers'
2
+
1
3
  module CmAdmin
2
4
  module Models
3
5
  class Filter
6
+ include Utils::Helpers
7
+
4
8
  attr_accessor :db_column_name, :filter_type, :placeholder, :collection
5
9
 
6
10
  VALID_FILTER_TYPES = Set[:date, :multi_select, :range, :search, :single_select].freeze
@@ -8,37 +12,55 @@ module CmAdmin
8
12
  def initialize(db_column_name:, filter_type:, options: {})
9
13
  raise TypeError, "Can't have array of multiple columns for #{filter_type} filter" if db_column_name.is_a?(Array) && db_column_name.size > 1 && !filter_type.to_sym.eql?(:search)
10
14
  raise ArgumentError, "Kindly select a valid filter type like #{VALID_FILTER_TYPES.sort.to_sentence(last_word_connector: ', or ')} instead of #{filter_type} for column #{db_column_name}" unless VALID_FILTER_TYPES.include?(filter_type.to_sym)
15
+
11
16
  @db_column_name, @filter_type = structure_data(db_column_name, filter_type)
17
+ set_default_values
12
18
  options.each do |key, value|
13
- self.send("#{key.to_s}=", value)
19
+ send("#{key}=", value)
14
20
  end
15
21
  end
16
22
 
17
23
  def structure_data(db_column_name, filter_type)
18
24
  filter_type = filter_type.is_a?(Array) ? filter_type[0].to_sym : filter_type.to_sym
19
25
 
20
- case filter_type
21
- when :search
22
- db_column_name = (Array.new << db_column_name).flatten.map{|x| x.class.eql?(Hash) ? x : x.to_sym}
23
- else
24
- db_column_name = db_column_name.is_a?(Array) ? db_column_name[0].to_sym : db_column_name.to_sym
25
- end
26
+ db_column_name = case filter_type
27
+ when :search
28
+ ([] << db_column_name).flatten.map { |x| x.instance_of?(Hash) ? x : x.to_sym }
29
+ else
30
+ db_column_name.is_a?(Array) ? db_column_name[0].to_sym : db_column_name.to_sym
31
+ end
26
32
  [db_column_name, filter_type]
27
33
  end
28
34
 
35
+ # Set default placeholder for the filter.
36
+ # Date and range filter will not have any placeholder.
37
+ # Else condition is added for fallback.
38
+ def set_default_values
39
+ placeholder = case filter_type
40
+ when :search
41
+ 'Search'
42
+ when :single_select, :multi_select
43
+ "Select/search #{humanized_field_value(db_column_name)}"
44
+ else
45
+ "Enter #{humanized_field_value(db_column_name)}"
46
+ end
47
+ self.placeholder = placeholder
48
+ end
49
+
29
50
  # Methods to filter the records based on the filter type.
30
51
  class << self
31
52
  def filtered_data(filter_params, records, filters)
32
53
  if filter_params
33
54
  filter_params.each do |scope_type, scope_value|
34
- scope_name = if scope_type.eql?('date') || scope_type.eql?('range')
35
- 'date_and_range'
36
- elsif scope_type.eql?('single_select') || scope_type.eql?('multi_select')
37
- 'dropdown'
38
- else
39
- scope_type
40
- end
41
- records = self.send("cm_#{scope_name}_filter", scope_value, records, filters) if scope_value.present?
55
+ scope_name = case scope_type
56
+ when 'date', 'range'
57
+ 'date_and_range'
58
+ when 'single_select', 'multi_select'
59
+ 'dropdown'
60
+ else
61
+ scope_type
62
+ end
63
+ records = send("cm_#{scope_name}_filter", scope_value, records, filters) if scope_value.present?
42
64
  end
43
65
  end
44
66
  records
@@ -46,15 +68,17 @@ module CmAdmin
46
68
 
47
69
  def cm_search_filter(scope_value, records, filters)
48
70
  return nil if scope_value.blank?
71
+
49
72
  table_name = records.table_name
50
- filters.select{|x| x if x.filter_type.eql?(:search)}.each do |filter|
73
+ filters.select { |x| x if x.filter_type.eql?(:search) }.each do |filter|
51
74
  query_variables = []
52
75
  filter.db_column_name.each do |col|
53
- if col.is_a?(Symbol)
76
+ case col
77
+ when Symbol
54
78
  query_variables << "#{table_name.pluralize}.#{col}"
55
- elsif col.is_a?(Hash)
79
+ when Hash
56
80
  col.map do |key, value|
57
- value.map {|val| query_variables << "#{key.to_s.pluralize}.#{val}" }
81
+ value.map { |val| query_variables << "#{key.to_s.pluralize}.#{val}" }
58
82
  end
59
83
  end
60
84
  end
@@ -62,14 +86,14 @@ module CmAdmin
62
86
  terms = terms.map { |e|
63
87
  (e.gsub('*', '%').prepend('%') + '%').gsub(/%+/, '%')
64
88
  }
65
- sql = ""
89
+ sql = ''
66
90
  query_variables.each.with_index do |column, i|
67
91
  sql.concat("#{column} ILIKE ?")
68
- sql.concat(' OR ') unless query_variables.size.eql?(i+1)
92
+ sql.concat(' OR ') unless query_variables.size.eql?(i + 1)
69
93
  end
70
94
 
71
- if filter.db_column_name.map{|x| x.is_a?(Hash)}.include?(true)
72
- associations_hash = filter.db_column_name.select{|x| x if x.is_a?(Hash)}.last
95
+ if filter.db_column_name.map { |x| x.is_a?(Hash) }.include?(true)
96
+ associations_hash = filter.db_column_name.select { |x| x if x.is_a?(Hash) }.last
73
97
  records = records.left_joins(associations_hash.keys).distinct
74
98
  end
75
99
 
@@ -85,19 +109,21 @@ module CmAdmin
85
109
 
86
110
  def cm_date_and_range_filter(scope_value, records, filters)
87
111
  return nil if scope_value.nil?
112
+
88
113
  scope_value.each do |key, value|
89
- if value.present?
90
- value = value.split(' to ')
91
- from = value[0].presence
92
- to = value[1].presence
93
- records = records.where(key => from..to)
94
- end
114
+ next unless value.present?
115
+
116
+ value = value.split(' to ')
117
+ from = value[0].presence
118
+ to = value[1].presence
119
+ records = records.where(key => from..to)
95
120
  end
96
121
  records
97
122
  end
98
123
 
99
124
  def cm_dropdown_filter(scope_value, records, filters)
100
125
  return nil if scope_value.nil?
126
+
101
127
  scope_value.each do |key, value|
102
128
  records = records.where(key => value) if value.present?
103
129
  end
@@ -1,6 +1,10 @@
1
+ require_relative 'utils/helpers'
2
+
1
3
  module CmAdmin
2
4
  module Models
3
5
  class FormField
6
+ include Utils::Helpers
7
+
4
8
  attr_accessor :field_name, :label, :header, :input_type, :collection, :disabled, :helper_method,
5
9
  :placeholder, :display_if, :html_attr, :target
6
10
 
@@ -13,9 +17,10 @@ module CmAdmin
13
17
  @field_name = field_name
14
18
  set_default_values
15
19
  attributes.each do |key, value|
16
- self.send("#{key.to_s}=", value)
20
+ send("#{key}=", value)
17
21
  end
18
- self.display_if = lambda { |arg| return true } if self.display_if.nil?
22
+ set_default_placeholder
23
+ self.display_if = lambda { |arg| return true } if display_if.nil?
19
24
  raise ArgumentError, "Kindly select a valid input type like #{VALID_INPUT_TYPES.sort.to_sentence(last_word_connector: ', or ')} instead of #{self.input_type} for form field #{field_name}" unless VALID_INPUT_TYPES.include?(self.input_type.to_sym)
20
25
  end
21
26
 
@@ -23,10 +28,20 @@ module CmAdmin
23
28
  self.disabled = false
24
29
  self.label = self.field_name.to_s.titleize
25
30
  self.input_type = :string
26
- self.placeholder = "Enter #{self.field_name.to_s.downcase.gsub('_', ' ')}"
27
31
  self.html_attr = {}
28
32
  self.target = {}
29
33
  end
34
+
35
+ def set_default_placeholder
36
+ return unless placeholder.nil?
37
+
38
+ self.placeholder = case input_type&.to_sym
39
+ when :single_select, :multi_select, :date, :date_time
40
+ "Select #{humanized_field_value(field_name)}"
41
+ else
42
+ "Enter #{humanized_field_value(field_name)}"
43
+ end
44
+ end
30
45
  end
31
46
  end
32
47
  end
@@ -0,0 +1,14 @@
1
+ module CmAdmin
2
+ module Models
3
+ module Utils
4
+ module Helpers
5
+ extend ActiveSupport::Concern
6
+
7
+ # Returns the humanized value of the field.
8
+ def humanized_field_value(name, capitalize: false)
9
+ name.to_s.humanize(capitalize: capitalize)
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -1,3 +1,3 @@
1
1
  module CmAdmin
2
- VERSION = '1.1.7'
2
+ VERSION = '1.1.9'
3
3
  end
@@ -169,7 +169,7 @@ module CmAdmin
169
169
  else
170
170
  value_mapped_text = value
171
171
  end
172
-
172
+
173
173
  concat(content_tag(:div, class: "position-relative mr-3 #{value ? '' : 'hidden'}") do
174
174
  concat filter_chip(value_mapped_text, filter)
175
175