cm-admin 0.3.0 → 0.4.3
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.
- checksums.yaml +4 -4
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +2 -1
- data/Gemfile.lock +25 -24
- data/README.md +5 -3
- data/app/assets/stylesheets/cm_admin/base/auth.scss +0 -12
- data/app/assets/stylesheets/cm_admin/base/common.scss +1 -1
- data/app/assets/stylesheets/cm_admin/base/filters.scss +8 -7
- data/app/assets/stylesheets/cm_admin/base/form.scss +7 -73
- data/app/assets/stylesheets/cm_admin/base/navbar.scss +1 -3
- data/app/assets/stylesheets/cm_admin/base/quicksearch.scss +7 -0
- data/app/assets/stylesheets/cm_admin/base/scaffold.scss +39 -2
- data/app/assets/stylesheets/cm_admin/base/show.scss +24 -2
- data/app/assets/stylesheets/cm_admin/base/table.scss +270 -253
- data/app/assets/stylesheets/cm_admin/cm_admin.css.scss +1 -0
- data/app/assets/stylesheets/cm_admin/components/_dropdown-popup.scss +22 -10
- data/app/assets/stylesheets/cm_admin/components/_range.scss +13 -2
- data/app/assets/stylesheets/cm_admin/components/_status-tag.scss +7 -6
- data/app/assets/stylesheets/cm_admin/helpers/_variable.scss +1 -0
- data/app/assets/stylesheets/cm_admin/scaffold.scss +14 -0
- data/app/controllers/cm_admin/application_controller.rb +5 -0
- data/app/controllers/cm_admin/exports_controller.rb +1 -1
- data/app/controllers/cm_admin/static_controller.rb +12 -0
- data/app/helpers/cm_admin/custom_helper.rb +4 -0
- data/app/javascript/packs/cm_admin/application.js +15 -1
- data/app/javascript/packs/cm_admin/filters.js +331 -16
- data/app/javascript/packs/cm_admin/quick_search.js +67 -0
- data/app/javascript/packs/cm_admin/scaffolds.js +30 -1
- data/app/javascript/stylesheets/cm_admin/application.scss +4 -0
- data/app/views/cm_admin/main/_associated_table.html.slim +60 -0
- data/app/views/cm_admin/main/_cm_pagy_nav.html.slim +6 -6
- data/app/views/cm_admin/main/_filters.html.slim +1 -10
- data/app/views/cm_admin/main/_nested_fields.html.slim +7 -0
- data/app/views/cm_admin/main/_nested_table_form.html.slim +6 -0
- data/app/views/cm_admin/main/_table.html.slim +9 -20
- data/app/views/cm_admin/main/_tabs.html.slim +5 -0
- data/app/views/cm_admin/main/_top_navbar.html.slim +12 -6
- data/app/views/cm_admin/main/associated_index.html.slim +6 -0
- data/app/views/cm_admin/main/associated_show.html.slim +6 -0
- data/app/views/cm_admin/main/edit.html.slim +10 -7
- data/app/views/cm_admin/main/index.html.slim +11 -8
- data/app/views/cm_admin/main/show.html.slim +12 -13
- data/app/views/cm_admin/static/error_401.html.slim +4 -0
- data/app/views/layouts/_flash_message.html.slim +9 -0
- data/app/views/layouts/_left_sidebar_nav.html.slim +7 -3
- data/app/views/layouts/_quick_links.html.slim +25 -0
- data/app/views/layouts/cm_admin.html.slim +25 -1
- data/app/views/layouts/static.html.slim +18 -0
- data/bin/console +0 -1
- data/cm_admin.gemspec +2 -1
- data/config/routes.rb +2 -1
- data/config/webpack/environment.js +3 -2
- data/lib/.DS_Store +0 -0
- data/lib/cm_admin/constants.rb +3 -0
- data/lib/cm_admin/model.rb +66 -167
- data/lib/cm_admin/models/action.rb +18 -2
- data/lib/cm_admin/models/cm_show_section.rb +20 -0
- data/lib/cm_admin/models/column.rb +49 -4
- data/lib/cm_admin/models/controller_method.rb +76 -0
- data/lib/cm_admin/models/custom_action.rb +13 -0
- data/lib/cm_admin/models/dsl_method.rb +122 -0
- data/lib/cm_admin/models/export.rb +16 -5
- data/lib/cm_admin/models/field.rb +2 -1
- data/lib/cm_admin/models/filter.rb +67 -2
- data/lib/cm_admin/models/form_field.rb +21 -0
- data/lib/cm_admin/models/tab.rb +13 -0
- data/lib/cm_admin/version.rb +1 -1
- data/lib/cm_admin/view_helpers/column_field_helper.rb +29 -0
- data/lib/cm_admin/view_helpers/field_display_helper.rb +71 -0
- data/lib/cm_admin/view_helpers/filter_helper.rb +190 -0
- data/lib/cm_admin/view_helpers/form_field_helper.rb +21 -4
- data/lib/cm_admin/view_helpers/form_helper.rb +22 -12
- data/lib/cm_admin/view_helpers/manage_column_popup_helper.rb +75 -0
- data/lib/cm_admin/view_helpers/navigation_helper.rb +22 -6
- data/lib/cm_admin/view_helpers/page_info_helper.rb +36 -0
- data/lib/cm_admin/view_helpers.rb +3 -1
- data/lib/cm_admin.rb +3 -1
- data/lib/generators/cm_admin/install_generator.rb +20 -8
- data/package.json +7 -1
- data/tmp/cache/webpacker/last-compilation-digest-development +1 -0
- data/yarn.lock +52 -17
- metadata +46 -9
- data/app/controllers/cm_admin/main_controller.rb +0 -8
- data/lib/c.png +0 -0
- data/lib/cm_admin/view_helpers/field_column_helper.rb +0 -23
- data/lib/generators/cm_admin/templates/cm_admin_initializer.rb +0 -4
- data/yarn-error.log +0 -44
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
module CmAdmin
|
|
2
2
|
module Models
|
|
3
3
|
class Filter
|
|
4
|
-
attr_accessor :db_column_name, :filter_type, :placeholder, :collection
|
|
4
|
+
attr_accessor :db_column_name, :filter_type, :placeholder, :collection
|
|
5
5
|
|
|
6
|
-
VALID_FILTER_TYPES = Set[:
|
|
6
|
+
VALID_FILTER_TYPES = Set[:date, :multi_select, :range, :search, :single_select].freeze
|
|
7
7
|
|
|
8
8
|
def initialize(db_column_name:, filter_type:, options: {})
|
|
9
9
|
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)
|
|
@@ -25,6 +25,71 @@ module CmAdmin
|
|
|
25
25
|
end
|
|
26
26
|
[db_column_name, filter_type]
|
|
27
27
|
end
|
|
28
|
+
|
|
29
|
+
# Methods to filter the records based on the filter type.
|
|
30
|
+
class << self
|
|
31
|
+
def filtered_data(filter_params, records, filters)
|
|
32
|
+
if filter_params
|
|
33
|
+
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?
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
records
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def cm_search_filter(scope_value, records, filters)
|
|
48
|
+
return nil if scope_value.blank?
|
|
49
|
+
table_name = records.table_name
|
|
50
|
+
|
|
51
|
+
filters.select{|x| x if x.filter_type.eql?(:search)}.each do |filter|
|
|
52
|
+
terms = scope_value.downcase.split(/\s+/)
|
|
53
|
+
terms = terms.map { |e|
|
|
54
|
+
(e.gsub('*', '%').prepend('%') + '%').gsub(/%+/, '%')
|
|
55
|
+
}
|
|
56
|
+
sql = ""
|
|
57
|
+
filter.db_column_name.each.with_index do |column, i|
|
|
58
|
+
sql.concat("#{table_name}.#{column} ILIKE ?")
|
|
59
|
+
sql.concat(' OR ') unless filter.db_column_name.size.eql?(i+1)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
records = records.where(
|
|
63
|
+
terms.map { |term|
|
|
64
|
+
sql
|
|
65
|
+
}.join(' AND '),
|
|
66
|
+
*terms.map { |e| [e] * filter.db_column_name.size }.flatten
|
|
67
|
+
)
|
|
68
|
+
end
|
|
69
|
+
records
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def cm_date_and_range_filter(scope_value, records, filters)
|
|
73
|
+
return nil if scope_value.nil?
|
|
74
|
+
scope_value.each do |key, value|
|
|
75
|
+
if value.present?
|
|
76
|
+
value = value.split(' to ')
|
|
77
|
+
from = value[0].presence
|
|
78
|
+
to = value[1].presence
|
|
79
|
+
records = records.where(key => from..to)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
records
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def cm_dropdown_filter(scope_value, records, filters)
|
|
86
|
+
return nil if scope_value.nil?
|
|
87
|
+
scope_value.each do |key, value|
|
|
88
|
+
records = records.where(key => value) if value.present?
|
|
89
|
+
end
|
|
90
|
+
records
|
|
91
|
+
end
|
|
92
|
+
end
|
|
28
93
|
end
|
|
29
94
|
end
|
|
30
95
|
end
|
|
@@ -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
|
data/lib/cm_admin/version.rb
CHANGED
|
@@ -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,71 @@
|
|
|
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 :enum
|
|
43
|
+
ar_object.send(field.field_name).to_s.titleize
|
|
44
|
+
when :tag
|
|
45
|
+
content_tag :span, class: "status-tag default-#{ar_object.send(field.field_name.to_s + '_before_type_cast')}" do
|
|
46
|
+
ar_object.send(field.field_name).to_s.titleize
|
|
47
|
+
end
|
|
48
|
+
when :attachment
|
|
49
|
+
concat show_attachment_value(ar_object, field)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def show_attachment_value(ar_object, field)
|
|
55
|
+
if ar_object.send(field.field_name).attached?
|
|
56
|
+
if ar_object.send(field.field_name).class.name.include?('One')
|
|
57
|
+
content_tag :a, href: rails_blob_path(ar_object.send(field.field_name), disposition: "attachment") do
|
|
58
|
+
ar_object.send(field.field_name).filename.to_s
|
|
59
|
+
end
|
|
60
|
+
elsif ar_object.send(field.field_name).class.name.include?('Many')
|
|
61
|
+
ar_object.send(field.field_name).map do |asset|
|
|
62
|
+
content_tag :a, href: rails_blob_path(asset, disposition: "attachment") do
|
|
63
|
+
asset.filename.to_s
|
|
64
|
+
end
|
|
65
|
+
end.join("\n").html_safe
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
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
|
|
@@ -2,13 +2,30 @@ module CmAdmin
|
|
|
2
2
|
module ViewHelpers
|
|
3
3
|
module FormFieldHelper
|
|
4
4
|
def input_field_for_column(f, field)
|
|
5
|
-
|
|
5
|
+
value = field.custom_value || f.object.send(field.field_name)
|
|
6
|
+
case field.input_type
|
|
6
7
|
when :integer
|
|
7
|
-
return f.
|
|
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'}
|
|
8
11
|
when :string
|
|
9
|
-
return f.text_field field.
|
|
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'}
|
|
10
21
|
when :text
|
|
11
|
-
return f.text_area field.
|
|
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
|
|
12
29
|
end
|
|
13
30
|
end
|
|
14
31
|
end
|
|
@@ -16,7 +16,7 @@ module CmAdmin
|
|
|
16
16
|
if cm_model.available_fields[action].empty?
|
|
17
17
|
return form_with_all_fields(resource, method)
|
|
18
18
|
else
|
|
19
|
-
return form_with_mentioned_fields(resource, cm_model.available_fields[
|
|
19
|
+
return form_with_mentioned_fields(resource, cm_model.available_fields[action], method)
|
|
20
20
|
end
|
|
21
21
|
end
|
|
22
22
|
|
|
@@ -29,22 +29,32 @@ module CmAdmin
|
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
def form_with_mentioned_fields(resource, available_fields, method)
|
|
32
|
-
columns = resource.class.columns.select { |i| available_fields.include?(i.name.to_sym) }
|
|
32
|
+
# columns = resource.class.columns.select { |i| available_fields.map(&:field_name).include?(i.name.to_sym) }
|
|
33
33
|
table_name = resource.class.table_name
|
|
34
|
-
columns.reject! { |i| REJECTABLE.include?(i.name) }
|
|
34
|
+
# columns.reject! { |i| REJECTABLE.include?(i.name) }
|
|
35
35
|
url = CmAdmin::Engine.mount_path + "/#{table_name}/#{resource.id}"
|
|
36
|
-
set_form_for_fields(resource,
|
|
36
|
+
set_form_for_fields(resource, available_fields, url, method)
|
|
37
37
|
end
|
|
38
38
|
|
|
39
|
-
def set_form_for_fields(resource,
|
|
39
|
+
def set_form_for_fields(resource, available_fields_hash, url, method)
|
|
40
40
|
form_for(resource, url: url, method: method) do |f|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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
|
|
48
58
|
end
|
|
49
59
|
concat tag.br
|
|
50
60
|
concat f.submit 'Save', class: 'cta-btn mt-3'
|
|
@@ -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
|
|
@@ -3,16 +3,32 @@ module CmAdmin
|
|
|
3
3
|
module ViewHelpers
|
|
4
4
|
module NavigationHelper
|
|
5
5
|
include Pagy::Frontend
|
|
6
|
-
def
|
|
6
|
+
def navigation_links(navigation_type)
|
|
7
7
|
CmAdmin.cm_admin_models.map { |model|
|
|
8
8
|
path = CmAdmin::Engine.mount_path + '/' + model.name.underscore.pluralize
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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
|
|
13
30
|
}.join.html_safe
|
|
14
31
|
end
|
|
15
|
-
|
|
16
32
|
end
|
|
17
33
|
end
|
|
18
34
|
end
|
|
@@ -5,6 +5,42 @@ module CmAdmin
|
|
|
5
5
|
@action.title || @model.title || "#{@model.ar_model.name} | #{@action.name&.titleize} | Admin"
|
|
6
6
|
end
|
|
7
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
|
+
|
|
8
44
|
def page_url(action_name=@action.name, ar_object=nil)
|
|
9
45
|
base_path = CmAdmin::Engine.mount_path + '/' + @model.name.downcase.pluralize
|
|
10
46
|
case action_name
|