cm-admin 0.2.0 → 0.4.2

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 (132) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +12 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +6 -0
  5. data/Gemfile +7 -1
  6. data/Gemfile.lock +121 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +8 -19
  9. data/app/assets/images/logo.png +0 -0
  10. data/{lib/generators/cm_admin/templates/assets/stylesheets → app/assets/stylesheets/cm_admin}/base/auth.scss +4 -6
  11. data/app/assets/stylesheets/cm_admin/base/common.scss +237 -0
  12. data/app/assets/stylesheets/cm_admin/base/filters.scss +200 -0
  13. data/{lib/generators/cm_admin/templates/assets/stylesheets → app/assets/stylesheets/cm_admin}/base/form.scss +83 -11
  14. data/app/assets/stylesheets/cm_admin/base/main-nav.scss +47 -0
  15. data/app/assets/stylesheets/cm_admin/base/navbar.scss +65 -0
  16. data/app/assets/stylesheets/cm_admin/base/quicksearch.scss +76 -0
  17. data/app/assets/stylesheets/cm_admin/base/scaffold.scss +96 -0
  18. data/app/assets/stylesheets/cm_admin/base/show.scss +76 -0
  19. data/app/assets/stylesheets/cm_admin/base/sidebar.scss +225 -0
  20. data/app/assets/stylesheets/cm_admin/base/table.scss +320 -0
  21. data/app/assets/stylesheets/cm_admin/base/tabs.scss +26 -0
  22. data/app/assets/stylesheets/cm_admin/cm_admin.css.scss +26 -0
  23. data/app/assets/stylesheets/cm_admin/components/_alerts.scss +101 -0
  24. data/app/assets/stylesheets/cm_admin/components/_buttons.scss +135 -0
  25. data/app/assets/stylesheets/cm_admin/components/_dropdown-popup.scss +153 -0
  26. data/app/assets/stylesheets/cm_admin/components/_input.scss +274 -0
  27. data/app/assets/stylesheets/cm_admin/components/_modal.scss +34 -0
  28. data/app/assets/stylesheets/cm_admin/components/_range.scss +31 -0
  29. data/app/assets/stylesheets/cm_admin/components/_status-tag.scss +68 -0
  30. data/app/assets/stylesheets/cm_admin/components/index.scss +7 -0
  31. data/app/assets/stylesheets/cm_admin/dependency/bootstrap.min.css +7 -0
  32. data/app/assets/stylesheets/cm_admin/helpers/_mixins.scss +20 -0
  33. data/app/assets/stylesheets/cm_admin/helpers/_variable.scss +87 -0
  34. data/app/assets/stylesheets/cm_admin/helpers/index.scss +2 -0
  35. data/app/controllers/cm_admin/application_controller.rb +11 -0
  36. data/app/controllers/cm_admin/exports_controller.rb +16 -0
  37. data/app/controllers/cm_admin/static_controller.rb +12 -0
  38. data/app/helpers/cm_admin/application_helper.rb +11 -0
  39. data/app/helpers/cm_admin/custom_helper.rb +4 -0
  40. data/app/javascript/packs/cm_admin/application.js +22 -0
  41. data/app/javascript/packs/cm_admin/filters.js +347 -0
  42. data/app/javascript/packs/cm_admin/quick_search.js +67 -0
  43. data/app/javascript/packs/cm_admin/scaffolds.js +43 -0
  44. data/app/javascript/stylesheets/cm_admin/application.scss +3 -0
  45. data/app/views/cm_admin/main/_associated_table.html.slim +60 -0
  46. data/app/views/cm_admin/main/_cm_pagy_nav.html.slim +23 -0
  47. data/app/views/cm_admin/main/_filters.html.slim +1 -0
  48. data/app/views/cm_admin/main/_nested_fields.html.slim +7 -0
  49. data/app/views/cm_admin/main/_nested_table_form.html.slim +6 -0
  50. data/app/views/cm_admin/main/_table.html.slim +60 -0
  51. data/app/views/cm_admin/main/_tabs.html.slim +5 -0
  52. data/app/views/cm_admin/main/_top_navbar.html.slim +25 -0
  53. data/app/views/cm_admin/main/associated_index.html.slim +6 -0
  54. data/app/views/cm_admin/main/associated_show.html.slim +6 -0
  55. data/app/views/cm_admin/main/dashboard.html.slim +1 -0
  56. data/app/views/cm_admin/main/edit.html.slim +19 -0
  57. data/app/views/cm_admin/main/index.html.slim +12 -0
  58. data/app/views/cm_admin/main/new.html.slim +22 -0
  59. data/app/views/cm_admin/main/show.html.slim +12 -0
  60. data/app/views/cm_admin/static/error_401.html.slim +4 -0
  61. data/app/views/layouts/_left_sidebar_nav.html.slim +34 -0
  62. data/app/views/layouts/_quick_links.html.slim +25 -0
  63. data/app/views/layouts/cm_admin.html.slim +41 -0
  64. data/app/views/layouts/static.html.slim +18 -0
  65. data/bin/webpack +18 -0
  66. data/bin/webpack-dev-server +18 -0
  67. data/cm_admin.gemspec +21 -31
  68. data/config/.DS_Store +0 -0
  69. data/config/initializers/active_record_extension.rb +9 -0
  70. data/config/routes.rb +19 -0
  71. data/config/webpack/development.js +5 -0
  72. data/config/webpack/environment.js +13 -0
  73. data/config/webpack/production.js +5 -0
  74. data/config/webpack/test.js +5 -0
  75. data/config/webpacker.yml +92 -0
  76. data/lib/cm_admin/constants.rb +33 -0
  77. data/lib/cm_admin/engine.rb +38 -0
  78. data/lib/cm_admin/model.rb +152 -0
  79. data/lib/cm_admin/models/action.rb +36 -0
  80. data/lib/cm_admin/models/actions/blocks.rb +25 -0
  81. data/lib/cm_admin/models/blocks.rb +19 -0
  82. data/lib/cm_admin/models/cm_show_section.rb +20 -0
  83. data/lib/cm_admin/models/column.rb +61 -0
  84. data/lib/cm_admin/models/controller_method.rb +75 -0
  85. data/lib/cm_admin/models/dsl_method.rb +122 -0
  86. data/lib/cm_admin/models/export.rb +54 -0
  87. data/lib/cm_admin/models/field.rb +15 -0
  88. data/lib/cm_admin/models/filter.rb +95 -0
  89. data/lib/cm_admin/models/form_field.rb +21 -0
  90. data/lib/cm_admin/models/tab.rb +13 -0
  91. data/lib/cm_admin/utils.rb +67 -0
  92. data/lib/cm_admin/version.rb +1 -1
  93. data/lib/cm_admin/view_helpers/column_field_helper.rb +29 -0
  94. data/lib/cm_admin/view_helpers/field_display_helper.rb +65 -0
  95. data/lib/cm_admin/view_helpers/filter_helper.rb +190 -0
  96. data/lib/cm_admin/view_helpers/form_field_helper.rb +33 -0
  97. data/lib/cm_admin/view_helpers/form_helper.rb +65 -0
  98. data/lib/cm_admin/view_helpers/manage_column_popup_helper.rb +75 -0
  99. data/lib/cm_admin/view_helpers/navigation_helper.rb +34 -0
  100. data/lib/cm_admin/view_helpers/page_info_helper.rb +57 -0
  101. data/lib/cm_admin/view_helpers.rb +74 -0
  102. data/lib/cm_admin.rb +33 -2
  103. data/lib/generators/cm_admin/install_generator.rb +3 -13
  104. data/lib/tasks/webpack_install.rake +63 -0
  105. data/package.json +23 -0
  106. data/postcss.config.js +12 -0
  107. data/tmp/cache/webpacker/last-compilation-digest-development +1 -0
  108. data/yarn.lock +6933 -0
  109. metadata +155 -46
  110. data/lib/generators/cm_admin/USAGE +0 -8
  111. data/lib/generators/cm_admin/templates/assets/images/cm.png +0 -0
  112. data/lib/generators/cm_admin/templates/assets/stylesheets/application.css.scss +0 -33
  113. data/lib/generators/cm_admin/templates/assets/stylesheets/base/_variable.scss +0 -14
  114. data/lib/generators/cm_admin/templates/assets/stylesheets/base/input-styles.scss +0 -72
  115. data/lib/generators/cm_admin/templates/assets/stylesheets/base/main-nav.scss +0 -79
  116. data/lib/generators/cm_admin/templates/assets/stylesheets/base/scaffold.scss +0 -95
  117. data/lib/generators/cm_admin/templates/assets/stylesheets/base/show.scss +0 -88
  118. data/lib/generators/cm_admin/templates/assets/stylesheets/base/sidebar.scss +0 -69
  119. data/lib/generators/cm_admin/templates/assets/stylesheets/base/table.scss +0 -246
  120. data/lib/generators/cm_admin/templates/layouts/_navbar.html.slim +0 -8
  121. data/lib/generators/cm_admin/templates/layouts/_side_navbar.html.slim +0 -12
  122. data/lib/generators/cm_admin/templates/layouts/application.html.slim +0 -20
  123. data/lib/generators/cm_admin/templates/layouts/initializer.rb +0 -2
  124. data/lib/generators/cm_admin/templates/views/_form.erb +0 -67
  125. data/lib/generators/cm_admin/templates/views/_table.erb +0 -22
  126. data/lib/generators/cm_admin/templates/views/edit.erb +0 -10
  127. data/lib/generators/cm_admin/templates/views/index.erb +0 -11
  128. data/lib/generators/cm_admin/templates/views/new.erb +0 -10
  129. data/lib/generators/cm_admin/templates/views/reset_password.erb +0 -12
  130. data/lib/generators/cm_admin/templates/views/show.erb +0 -18
  131. data/lib/generators/cm_admin/templates/views/sign_in.erb +0 -18
  132. data/lib/generators/cm_admin/view_generator.rb +0 -78
@@ -0,0 +1,21 @@
1
+ module CmAdmin
2
+ module Models
3
+ class FormField
4
+ attr_accessor :field_name, :label, :header, :input_type, :collection, :custom_value, :disabled
5
+ VALID_INPUT_TYPES = [:integer, :decimal, :string, :single_select, :multi_select, :date, :date_time, :text, :single_file_upload, :multi_file_upload, :hidden].freeze
6
+
7
+ def initialize(field_name, input_type, attributes = {})
8
+ raise ArgumentError, "Kindly select a valid filter type like #{VALID_INPUT_TYPES.sort.to_sentence(last_word_connector: ', or ')} instead of #{input_type} for column #{field_name}" unless VALID_INPUT_TYPES.include?(input_type.to_sym)
9
+ @field_name = field_name
10
+ set_default_values
11
+ attributes.each do |key, value|
12
+ self.send("#{key.to_s}=", value)
13
+ end
14
+ end
15
+
16
+ def set_default_values
17
+ self.disabled = false
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,13 @@
1
+ module CmAdmin
2
+ module Models
3
+ class Tab
4
+
5
+ attr_accessor :nav_item_name, :custom_action
6
+
7
+ def initialize(nav_item_name, custom_action)
8
+ @nav_item_name = nav_item_name
9
+ @custom_action = custom_action
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,67 @@
1
+ module CmAdmin::Utils
2
+ class << self
3
+ def serialize_csv_columns(*columns, **hashes)
4
+ # Turns an arbitrary list of args and kwargs into a list of params to be used in a form
5
+ # For example, turns CmAdmin::Utils.serialize_csv_columns(:a, :b, c: [:d, e: :h], f: :g)
6
+ # into [:a, :b, "c/d", "c/e/h", "f/g"]
7
+ columns.map(&:to_s) + hashes.map do |key, value|
8
+ serialize_csv_columns(*value).map do |column|
9
+ "#{key}/#{column}"
10
+ end
11
+ end.reduce([], :+)
12
+ end
13
+
14
+ def deserialize_csv_columns(list, method)
15
+ # Does the opposite operation of serialize_csv_columns
16
+ list.reduce(recursive_hash) do |acc, item|
17
+ tokens = item.to_s.split('/')
18
+ send(method, acc, tokens.shift, tokens)
19
+ end
20
+ end
21
+
22
+ def recursive_hash
23
+ func = ->(h, k) { h[k] = Hash.new(&func) }
24
+ # This hash creates a new hash, infinitely deep, whenever a value is not found
25
+ # recursive_hash[:a][:b][:c][:d] will never fail
26
+ Hash.new(&func)
27
+ end
28
+
29
+ def as_json_params(hash, key, tokens)
30
+ hash.empty? && hash = { only: [], methods: [], include: recursive_hash }
31
+ if tokens.empty?
32
+ # base case
33
+ hash[:methods] << key
34
+ else
35
+ # recursive case
36
+ # hash[:associations] ||= {}
37
+ hash[:include][key] = as_json_params(hash[:include][key], tokens.shift, tokens)
38
+ end
39
+ hash
40
+ end
41
+
42
+ def flatten_hash(hash, prefix="", separator="_")
43
+ hash.reduce({}) do |acc, item|
44
+ case item[1]
45
+ when Hash
46
+ acc.merge(flatten_hash(item[1], "#{prefix}#{item[0]}#{separator}"))
47
+ else
48
+ acc.merge("#{prefix}#{item[0]}" => item[1])
49
+ end
50
+ end
51
+ end
52
+
53
+ def base(hash, key, tokens) # recursive
54
+ hash.empty? && hash = { columns: [], associations: recursive_hash }
55
+ if tokens.empty?
56
+ # base case
57
+ hash[:columns] << key
58
+ else
59
+ # recursive case
60
+ # hash[:associations] ||= {}
61
+ hash[:associations][key] = base(hash[:associations][key], tokens.shift, tokens)
62
+ end
63
+ hash
64
+ end
65
+
66
+ end
67
+ end
@@ -1,3 +1,3 @@
1
1
  module CmAdmin
2
- VERSION = "0.2.0"
2
+ VERSION = "0.4.2"
3
3
  end
@@ -0,0 +1,29 @@
1
+ module CmAdmin
2
+ module ViewHelpers
3
+ module ColumnFieldHelper
4
+
5
+ #adds prefix and suffix to a value
6
+ def add_prefix_and_suffix_helper(value, prefix, suffix)
7
+ "#{prefix} #{value} #{suffix}"
8
+ end
9
+
10
+ #formats the column value a field
11
+ def column_for_field_helper(ar_object, column)
12
+ value = ar_object.send(column.db_column_name)
13
+ formatted_value = CmAdmin::Models::Column.format_data_type(column, value)
14
+ formatted_value = add_prefix_and_suffix_helper(formatted_value, column.prefix, column.suffix)
15
+ formatted_value = link_url_value_helper(column, value, formatted_value)
16
+ return formatted_value
17
+ end
18
+
19
+ #column's value is either linked with 'url' attribute's value or its own value
20
+ def link_url_value_helper(column, value, formatted_value)
21
+ return formatted_value unless column.column_type.to_s == 'link'
22
+ link_url_value = column.url.present? ? column.url : value
23
+ final_value = "<a href=#{link_url_value}>#{formatted_value}</a>".html_safe
24
+ return final_value
25
+ end
26
+
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,65 @@
1
+ module CmAdmin
2
+ module ViewHelpers
3
+ module FieldDisplayHelper
4
+
5
+ def show_field(ar_object, field)
6
+ content_tag(:div, class: "info-split") do
7
+ concat show_field_label(ar_object, field)
8
+ concat show_field_value(ar_object, field)
9
+ end
10
+ end
11
+
12
+ def show_field_label(ar_object, field)
13
+ content_tag(:div, class: "info-split__lhs") do
14
+ p = field.label.present? ? field.label.to_s : field.field_name.to_s.titleize
15
+ end
16
+ end
17
+
18
+ def show_field_value(ar_object, field)
19
+ content_tag(:div, class: "info-split__rhs") do
20
+ case field.field_type || :string
21
+ when :integer
22
+ ar_object.send(field.field_name).to_s
23
+ when :decimal
24
+ ar_object.send(field.field_name).to_f.round(field.precision).to_s if ar_object.send(field.field_name)
25
+ when :string
26
+ ar_object.send(field.field_name).to_s
27
+ when :datetime
28
+ ar_object.send(field.field_name).strftime(field.format || "%d/%m/%Y").to_s if ar_object.send(field.field_name)
29
+ when :text
30
+ ar_object.send(field.field_name)
31
+ when :custom
32
+ send(field.helper_method, ar_object, field.field_name)
33
+ when :link
34
+ if field.custom_link
35
+ link = field.custom_link
36
+ else
37
+ link = ar_object.send(field.field_name)
38
+ end
39
+ content_tag :a, href: link do
40
+ ar_object.send(field.field_name).to_s
41
+ end
42
+ when :attachment
43
+ concat show_attachment_value(ar_object, field)
44
+ end
45
+ end
46
+ end
47
+
48
+ def show_attachment_value(ar_object, field)
49
+ if ar_object.send(field.field_name).attached?
50
+ if ar_object.send(field.field_name).class.name.include?('One')
51
+ content_tag :a, href: rails_blob_path(ar_object.send(field.field_name), disposition: "attachment") do
52
+ ar_object.send(field.field_name).filename.to_s
53
+ end
54
+ elsif ar_object.send(field.field_name).class.name.include?('Many')
55
+ ar_object.send(field.field_name).map do |asset|
56
+ content_tag :a, href: rails_blob_path(asset, disposition: "attachment") do
57
+ asset.filename.to_s
58
+ end
59
+ end.join("\n").html_safe
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,190 @@
1
+ module CmAdmin
2
+ module ViewHelpers
3
+ module FilterHelper
4
+
5
+ def generate_filters(filters)
6
+ search_filter = filters.select{ |x| x.filter_type.eql?(:search) }.last
7
+ other_filters = filters.reject{ |x| x.filter_type.eql?(:search) }
8
+ concat(content_tag(:div, class: 'cm-filters-v2') do
9
+ concat(content_tag(:div, class: 'cm-filters-v2__inner') do
10
+ concat add_search_filter(search_filter) if search_filter
11
+ if other_filters.any?
12
+ concat filter_ui(other_filters)
13
+ concat add_filters_dropdown(other_filters)
14
+ end
15
+ concat clear_filters
16
+ end)
17
+ end)
18
+ return
19
+ end
20
+
21
+ def add_filters_dropdown(filters)
22
+ concat(content_tag(:div, class: 'dropdown add-filter-btn', data: {bs_toggle: 'dropdown'}) do
23
+ tag.span '+ Add filter'
24
+ end)
25
+
26
+ concat(content_tag(:div, class: 'dropdown-menu dropdown-popup') do
27
+ concat(content_tag(:div, class: 'popup-base') do
28
+ concat(content_tag(:div, class: 'popup-inner') do
29
+ concat(content_tag(:div, class: 'search-area') do
30
+ concat tag.input placeholder: 'Search for filter', data: {behaviour: 'dropdown-filter-search'}
31
+ end)
32
+ concat(content_tag(:div, class: 'list-area') do
33
+ filters.each do |filter|
34
+ concat(content_tag(:div, class: 'pointer list-item', data: {behaviour: 'filter-option', filter_type: "#{filter.filter_type}", db_column: "#{filter.db_column_name}"}) do
35
+ tag.span filter.db_column_name.to_s.titleize
36
+ end)
37
+ end
38
+ end)
39
+ end)
40
+ end)
41
+ end)
42
+ return
43
+ end
44
+
45
+ def clear_filters
46
+ concat(content_tag(:div, class: "clear-btn #{params.dig(:filters) ? '' : 'hidden'}") do
47
+ tag.span 'Clear all'
48
+ end)
49
+ return
50
+ end
51
+
52
+ def filter_ui(filters)
53
+ filters.each do |filter|
54
+ case filter.filter_type
55
+ when :date
56
+ concat add_date_filter(filter)
57
+ when :range
58
+ concat add_range_filter(filter)
59
+ when :single_select
60
+ concat add_single_select_filter(filter)
61
+ when :multi_select
62
+ concat add_multi_select_filter(filter)
63
+ end
64
+ end
65
+ return
66
+ end
67
+
68
+ def filter_chip(value, filter)
69
+ data_hash = {behaviour: 'filter-input', filter_type: "#{filter.filter_type}", db_column: "#{filter.db_column_name}"}
70
+ data_hash.merge!(bs_toggle: 'dropdown') if filter.filter_type.to_s.eql?('single_select')
71
+
72
+ if value && filter.filter_type.to_s.eql?('multi_select')
73
+ truncated_value = value[0]
74
+ truncated_value += " + #{value.size - 1} more" if truncated_value.size > 1
75
+ end
76
+
77
+ concat(content_tag(:div, class: "filter-chip #{filter.filter_type.to_s.eql?('single_select') ? 'dropdown' : ''}", data: data_hash) do
78
+ concat tag.span "#{filter.db_column_name.to_s.titleize} is "
79
+ concat tag.span "#{filter.filter_type.to_s.eql?('multi_select') ? truncated_value : value}"
80
+ concat(content_tag(:div, class: "filter-chip-remove #{value ? '' : 'hidden'}") do
81
+ tag.i class: 'fa fa-times bolder'
82
+ end)
83
+ end)
84
+ return
85
+ end
86
+
87
+ def add_search_filter(filter)
88
+ tag.div class: 'filter-search mr-3' do
89
+ tag.div class: 'form-field' do
90
+ tag.div class: 'field-input-wrapper' do
91
+ concat(content_tag(:input, class: 'search-input', value: "#{params.dig(:filters, :search)}", placeholder: "#{filter.placeholder}", data: {behaviour: 'input-search'}) do
92
+ tag.span class: 'search-input-icon' do
93
+ tag.i class: 'fa fa-search'
94
+ end
95
+ end)
96
+ end
97
+ end
98
+ end
99
+ end
100
+
101
+ def add_range_filter(filter)
102
+ value = params.dig(:filters, :range, :"#{filter.db_column_name}")
103
+ concat(content_tag(:div, class: "position-relative mr-3 #{value ? '' : 'hidden'}") do
104
+ concat filter_chip(value, filter)
105
+
106
+ concat(content_tag(:div, class: 'position-absolute mt-2 range-container hidden') do
107
+ concat tag.input type: 'number', min: '0', step: '1', class: 'range-item', value: "#{value ? value.split(' to ')[0] : ''}", placeholder: 'From', data: {behaviour: 'filter', filter_type: "#{filter.filter_type}", db_column: "#{filter.db_column_name}"}
108
+ concat tag.input type: 'number', min: '0', step: '1', class: 'range-item', value: "#{value ? value.split(' to ')[1] : ''}", placeholder: 'To', data: {behaviour: 'filter', filter_type: "#{filter.filter_type}", db_column: "#{filter.db_column_name}"}
109
+ end)
110
+ end)
111
+ return
112
+ end
113
+
114
+ def add_date_filter(filter)
115
+ value = params.dig(:filters, :date, :"#{filter.db_column_name}")
116
+ concat(content_tag(:div, class: "position-relative mr-3 #{value ? '' : 'hidden'}") do
117
+ concat filter_chip(value, filter)
118
+
119
+ concat(content_tag(:div, class: 'date-filter-wrapper w-100') do
120
+ concat tag.input class: 'w-100 pb-1', value: "#{value ? value : ''}", data: {behaviour: 'filter', filter_type: "#{filter.filter_type}", db_column: "#{filter.db_column_name}"}
121
+ end)
122
+ end)
123
+ return
124
+ end
125
+
126
+ def add_single_select_filter(filter)
127
+ value = params.dig(:filters, :"#{filter.filter_type}", :"#{filter.db_column_name}")
128
+ concat(content_tag(:div, class: "position-relative mr-3 #{value ? '' : 'hidden'}") do
129
+ concat filter_chip(value, filter)
130
+
131
+ concat(content_tag(:div, class: 'dropdown-menu dropdown-popup') do
132
+ concat(content_tag(:div, class: 'popup-base') do
133
+ concat(content_tag(:div, class: 'popup-inner') do
134
+ concat(content_tag(:div, class: 'search-area') do
135
+ concat tag.input placeholder: "#{filter.placeholder}", data: {behaviour: 'dropdown-filter-search'}
136
+ end)
137
+ concat(content_tag(:div, class: 'list-area') do
138
+ filter.collection.each do |val|
139
+ concat(content_tag(:div, class: "pointer list-item #{(value.present? && value.eql?(val)) ? 'selected' : ''}", data: {behaviour: 'select-option', filter_type: "#{filter.filter_type}", db_column: "#{filter.db_column_name}", value: val}) do
140
+ concat tag.span val.to_s
141
+ end)
142
+ end
143
+ end)
144
+ end)
145
+ end)
146
+ end)
147
+ end)
148
+ return
149
+ end
150
+
151
+ def add_multi_select_filter(filter)
152
+ value = params.dig(:filters, :"#{filter.filter_type}", :"#{filter.db_column_name}")
153
+
154
+ concat(content_tag(:div, class: "position-relative mr-3 #{value ? '' : 'hidden'}") do
155
+ concat filter_chip(value, filter)
156
+
157
+ concat(content_tag(:div, class: 'position-absolute mt-2 dropdown-popup hidden') do
158
+ concat(content_tag(:div, class: 'popup-base') do
159
+ concat(content_tag(:div, class: 'popup-inner') do
160
+ concat(content_tag(:div, class: "#{value ? 'search-with-chips' : 'search-area'}") do
161
+ if value
162
+ value.each do |val|
163
+ concat(content_tag(:div, class: 'chip') do
164
+ concat tag.span val
165
+ concat(content_tag(:span, data: { behaviour: 'selected-chip' }) do
166
+ tag.i class: 'fa fa-times'
167
+ end)
168
+ end)
169
+ end
170
+ end
171
+ concat tag.input placeholder: "#{filter.placeholder}", data: {behaviour: 'dropdown-filter-search'}
172
+ end)
173
+ concat(content_tag(:div, class: 'list-area') do
174
+ filter.collection.each do |val|
175
+ concat(content_tag(:div, class: "pointer list-item #{(value && value.eql?(val)) ? 'selected' : ''}", data: {behaviour: 'select-option', filter_type: "#{filter.filter_type}", db_column: "#{filter.db_column_name}", value: val}) do
176
+ concat tag.input class: 'cm-checkbox', type: 'checkbox', checked: value ? value.include?(val) : false
177
+ concat tag.label val.to_s.titleize, class: 'pointer'
178
+ end)
179
+ end
180
+ end)
181
+ concat tag.div 'Apply', class: "apply-area #{value ? 'active' : ''}"
182
+ end)
183
+ end)
184
+ end)
185
+ end)
186
+ return
187
+ end
188
+ end
189
+ end
190
+ end
@@ -0,0 +1,33 @@
1
+ module CmAdmin
2
+ module ViewHelpers
3
+ module FormFieldHelper
4
+ def input_field_for_column(f, field)
5
+ value = field.custom_value || f.object.send(field.field_name)
6
+ case field.input_type
7
+ when :integer
8
+ return f.text_field field.field_name, class: 'normal-input', disabled: field.disabled, value: value, data: {behaviour: 'integer-only'}
9
+ when :decimal
10
+ return f.number_field field.field_name, class: 'normal-input', disabled: field.disabled, value: value, data: {behaviour: 'decimal-only'}
11
+ when :string
12
+ return f.text_field field.field_name, class: 'normal-input', disabled: field.disabled, value: value
13
+ when :single_select
14
+ return f.select field.field_name, options_for_select(field.collection || []), {}, class: 'normal-input select-2', disabled: field.disabled
15
+ when :multi_select
16
+ return f.select field.field_name, options_for_select(field.collection || []), {}, class: 'normal-input select-2', disabled: field.disabled, multiple: true
17
+ when :date
18
+ return f.text_field field.field_name, class: 'normal-input', disabled: field.disabled, value: value, data: {behaviour: 'date-only'}
19
+ when :date_time
20
+ return f.text_field field.field_name, class: 'normal-input', disabled: field.disabled, value: value, data: {behaviour: 'date-time'}
21
+ when :text
22
+ return f.text_area field.field_name, class: 'normal-input'
23
+ when :single_file_upload
24
+ return f.file_field field.field_name, class: 'normal-input'
25
+ when :multi_file_upload
26
+ return f.file_field field.field_name, multiple: true, class: 'normal-input'
27
+ when :hidden
28
+ return f.hidden_field field.field_name, value: field.custom_value
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,65 @@
1
+ require_relative 'form_field_helper'
2
+ module CmAdmin
3
+ module ViewHelpers
4
+ module FormHelper
5
+ include FormFieldHelper
6
+ REJECTABLE = %w(id created_at updated_at)
7
+
8
+ def generate_form(resource, cm_model)
9
+ if resource.new_record?
10
+ action = :new
11
+ method = :post
12
+ else
13
+ action = :edit
14
+ method = :patch
15
+ end
16
+ if cm_model.available_fields[action].empty?
17
+ return form_with_all_fields(resource, method)
18
+ else
19
+ return form_with_mentioned_fields(resource, cm_model.available_fields[action], method)
20
+ end
21
+ end
22
+
23
+ def form_with_all_fields(resource, method)
24
+ columns = resource.class.columns.dup
25
+ table_name = resource.class.table_name
26
+ columns.reject! { |i| REJECTABLE.include?(i.name) }
27
+ url = CmAdmin::Engine.mount_path + "/#{table_name}/#{resource.id}"
28
+ set_form_for_fields(resource, columns, url, method)
29
+ end
30
+
31
+ def form_with_mentioned_fields(resource, available_fields, method)
32
+ # columns = resource.class.columns.select { |i| available_fields.map(&:field_name).include?(i.name.to_sym) }
33
+ table_name = resource.class.table_name
34
+ # columns.reject! { |i| REJECTABLE.include?(i.name) }
35
+ url = CmAdmin::Engine.mount_path + "/#{table_name}/#{resource.id}"
36
+ set_form_for_fields(resource, available_fields, url, method)
37
+ end
38
+
39
+ def set_form_for_fields(resource, available_fields_hash, url, method)
40
+ form_for(resource, url: url, method: method) do |f|
41
+ available_fields_hash.each do |key, fields_array|
42
+ if key == :fields
43
+ fields_array.each do |field|
44
+ if field.input_type.eql?(:hidden)
45
+ concat input_field_for_column(f, field)
46
+ else
47
+ concat f.label field.field_name, class: 'field-label'
48
+ concat tag.br
49
+ concat(content_tag(:div, class: "datetime-wrapper") do
50
+ concat input_field_for_column(f, field)
51
+ end)
52
+ concat tag.p resource.errors[field.field_name].first if resource.errors[field.field_name].present?
53
+ end
54
+ end
55
+ else
56
+ concat(render partial: '/cm_admin/main/nested_table_form', locals: {f: f, table_name: key})
57
+ end
58
+ end
59
+ concat tag.br
60
+ concat f.submit 'Save', class: 'cta-btn mt-3'
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,75 @@
1
+ module CmAdmin
2
+ module ViewHelpers
3
+ module ManageColumnPopupHelper
4
+
5
+ def manage_column_pop_up(klass)
6
+ tag.div class: 'modal fade form-modal table-column-modal', id: 'columnActionModal', role: 'dialog' do
7
+ tag.div class: 'modal-dialog', role: 'document' do
8
+ tag.div class: 'modal-content' do
9
+ tag.div do
10
+ concat manage_column_header
11
+ concat manage_column_body(klass)
12
+ concat manage_column_footer
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+
19
+ def manage_column_header
20
+ concat(content_tag(:div, class: 'modal-header') do
21
+ concat(content_tag(:button, class: 'close', data: {bs_dismiss: 'modal'}) do
22
+ tag.span 'X'
23
+ end)
24
+ concat tag.h5 'Manage columns', class: 'modal-title'
25
+ end)
26
+ return
27
+ end
28
+
29
+ def manage_column_body(klass)
30
+ tag.div class: 'modal-body' do
31
+ tag.div class: 'columns-list' do
32
+ klass.available_fields[:index].each do |column_name|
33
+ concat manage_column_body_list(column_name)
34
+ end
35
+ end
36
+ end
37
+ end
38
+
39
+ def manage_column_body_list(column_name)
40
+ tag.div class: 'column-item' do
41
+ concat manage_column_dragger(column_name.field_name)
42
+ concat manage_column_item_name(column_name)
43
+ concat manage_column_item_pointer(column_name.field_name)
44
+ end
45
+ end
46
+
47
+ def manage_column_dragger(default_column_name)
48
+ return if default_column_name == :id
49
+ tag.div class: 'dragger' do
50
+ tag.i class: 'fa fa-bars bolder'
51
+ end
52
+ end
53
+
54
+ def manage_column_item_name(column_name)
55
+ tag.div class: 'column-item__name' do
56
+ tag.p column_name.field_name.to_s.gsub('/', '_').humanize
57
+ end
58
+ end
59
+
60
+ def manage_column_item_pointer(default_column_name)
61
+ tag.div class: "column-item__action #{'pointer' if default_column_name != :id}" do
62
+ tag.i class: "fa #{default_column_name == :id ? 'fa-lock' : 'fa-times-circle'} bolder"
63
+ end
64
+ end
65
+
66
+ def manage_column_footer
67
+ concat(content_tag(:div, class: 'modal-footer') do
68
+ concat tag.button 'Close', class: 'gray-border-btn', data: {bs_dismiss: 'modal'}
69
+ concat tag.button 'Save', class: 'cta-btn'
70
+ end)
71
+ return
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,34 @@
1
+ require 'pagy'
2
+ module CmAdmin
3
+ module ViewHelpers
4
+ module NavigationHelper
5
+ include Pagy::Frontend
6
+ def navigation_links(navigation_type)
7
+ CmAdmin.cm_admin_models.map { |model|
8
+ path = CmAdmin::Engine.mount_path + '/' + model.name.underscore.pluralize
9
+ if navigation_type == "sidebar"
10
+ content_tag(:a, href: path) do
11
+ content_tag(:div, class: 'menu-item') do
12
+ content_tag(:span, class: 'menu-icon') do
13
+ concat tag.i class: 'fa fa-th-large'
14
+ end +
15
+ model.name
16
+ end
17
+ end
18
+ elsif navigation_type == "quick_links"
19
+ content_tag(:a, href: path, class: 'visible') do
20
+ content_tag(:div, class: 'result-item') do
21
+ content_tag(:span) do
22
+ concat tag.i class: 'fa fa-th-large'
23
+ end +
24
+ content_tag(:span) do
25
+ model.name
26
+ end
27
+ end
28
+ end
29
+ end
30
+ }.join.html_safe
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,57 @@
1
+ module CmAdmin
2
+ module ViewHelpers
3
+ module PageInfoHelper
4
+ def page_title
5
+ @action.title || @model.title || "#{@model.ar_model.name} | #{@action.name&.titleize} | Admin"
6
+ end
7
+
8
+ def action_title
9
+ if @model.current_action.page_title
10
+ title = @model.current_action.page_title
11
+ else
12
+ title = "#{@model.name}"
13
+ case action_name
14
+ when 'index'
15
+ title + " list record"
16
+ when 'show'
17
+ title + " detail"
18
+ when 'new'
19
+ title + " create record"
20
+ when 'edit'
21
+ title + " edit record"
22
+ end
23
+ end
24
+ end
25
+
26
+ def action_description
27
+ if @model.current_action.page_description
28
+ title = @model.current_action.page_description
29
+ else
30
+ title = "#{@model.name}"
31
+ case action_name
32
+ when 'index'
33
+ title + " list record"
34
+ when 'show'
35
+ title + " detail"
36
+ when 'new'
37
+ title + " new record"
38
+ when 'edit'
39
+ title + " edit record"
40
+ end
41
+ end
42
+ end
43
+
44
+ def page_url(action_name=@action.name, ar_object=nil)
45
+ base_path = CmAdmin::Engine.mount_path + '/' + @model.name.downcase.pluralize
46
+ case action_name
47
+ when 'index'
48
+ base_path
49
+ when 'new'
50
+ base_path + '/new'
51
+ when 'edit'
52
+ base_path + "/#{ar_object.id}" + '/edit'
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end