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.
- checksums.yaml +4 -4
- data/.gitignore +12 -0
- data/.rspec +3 -0
- data/.travis.yml +6 -0
- data/Gemfile +7 -1
- data/Gemfile.lock +121 -0
- data/LICENSE.txt +21 -0
- data/README.md +8 -19
- data/app/assets/images/logo.png +0 -0
- data/{lib/generators/cm_admin/templates/assets/stylesheets → app/assets/stylesheets/cm_admin}/base/auth.scss +4 -6
- data/app/assets/stylesheets/cm_admin/base/common.scss +237 -0
- data/app/assets/stylesheets/cm_admin/base/filters.scss +200 -0
- data/{lib/generators/cm_admin/templates/assets/stylesheets → app/assets/stylesheets/cm_admin}/base/form.scss +83 -11
- data/app/assets/stylesheets/cm_admin/base/main-nav.scss +47 -0
- data/app/assets/stylesheets/cm_admin/base/navbar.scss +65 -0
- data/app/assets/stylesheets/cm_admin/base/quicksearch.scss +76 -0
- data/app/assets/stylesheets/cm_admin/base/scaffold.scss +96 -0
- data/app/assets/stylesheets/cm_admin/base/show.scss +76 -0
- data/app/assets/stylesheets/cm_admin/base/sidebar.scss +225 -0
- data/app/assets/stylesheets/cm_admin/base/table.scss +320 -0
- data/app/assets/stylesheets/cm_admin/base/tabs.scss +26 -0
- data/app/assets/stylesheets/cm_admin/cm_admin.css.scss +26 -0
- data/app/assets/stylesheets/cm_admin/components/_alerts.scss +101 -0
- data/app/assets/stylesheets/cm_admin/components/_buttons.scss +135 -0
- data/app/assets/stylesheets/cm_admin/components/_dropdown-popup.scss +153 -0
- data/app/assets/stylesheets/cm_admin/components/_input.scss +274 -0
- data/app/assets/stylesheets/cm_admin/components/_modal.scss +34 -0
- data/app/assets/stylesheets/cm_admin/components/_range.scss +31 -0
- data/app/assets/stylesheets/cm_admin/components/_status-tag.scss +68 -0
- data/app/assets/stylesheets/cm_admin/components/index.scss +7 -0
- data/app/assets/stylesheets/cm_admin/dependency/bootstrap.min.css +7 -0
- data/app/assets/stylesheets/cm_admin/helpers/_mixins.scss +20 -0
- data/app/assets/stylesheets/cm_admin/helpers/_variable.scss +87 -0
- data/app/assets/stylesheets/cm_admin/helpers/index.scss +2 -0
- data/app/controllers/cm_admin/application_controller.rb +11 -0
- data/app/controllers/cm_admin/exports_controller.rb +16 -0
- data/app/controllers/cm_admin/static_controller.rb +12 -0
- data/app/helpers/cm_admin/application_helper.rb +11 -0
- data/app/helpers/cm_admin/custom_helper.rb +4 -0
- data/app/javascript/packs/cm_admin/application.js +22 -0
- data/app/javascript/packs/cm_admin/filters.js +347 -0
- data/app/javascript/packs/cm_admin/quick_search.js +67 -0
- data/app/javascript/packs/cm_admin/scaffolds.js +43 -0
- data/app/javascript/stylesheets/cm_admin/application.scss +3 -0
- data/app/views/cm_admin/main/_associated_table.html.slim +60 -0
- data/app/views/cm_admin/main/_cm_pagy_nav.html.slim +23 -0
- data/app/views/cm_admin/main/_filters.html.slim +1 -0
- 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 +60 -0
- data/app/views/cm_admin/main/_tabs.html.slim +5 -0
- data/app/views/cm_admin/main/_top_navbar.html.slim +25 -0
- 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/dashboard.html.slim +1 -0
- data/app/views/cm_admin/main/edit.html.slim +19 -0
- data/app/views/cm_admin/main/index.html.slim +12 -0
- data/app/views/cm_admin/main/new.html.slim +22 -0
- data/app/views/cm_admin/main/show.html.slim +12 -0
- data/app/views/cm_admin/static/error_401.html.slim +4 -0
- data/app/views/layouts/_left_sidebar_nav.html.slim +34 -0
- data/app/views/layouts/_quick_links.html.slim +25 -0
- data/app/views/layouts/cm_admin.html.slim +41 -0
- data/app/views/layouts/static.html.slim +18 -0
- data/bin/webpack +18 -0
- data/bin/webpack-dev-server +18 -0
- data/cm_admin.gemspec +21 -31
- data/config/.DS_Store +0 -0
- data/config/initializers/active_record_extension.rb +9 -0
- data/config/routes.rb +19 -0
- data/config/webpack/development.js +5 -0
- data/config/webpack/environment.js +13 -0
- data/config/webpack/production.js +5 -0
- data/config/webpack/test.js +5 -0
- data/config/webpacker.yml +92 -0
- data/lib/cm_admin/constants.rb +33 -0
- data/lib/cm_admin/engine.rb +38 -0
- data/lib/cm_admin/model.rb +152 -0
- data/lib/cm_admin/models/action.rb +36 -0
- data/lib/cm_admin/models/actions/blocks.rb +25 -0
- data/lib/cm_admin/models/blocks.rb +19 -0
- data/lib/cm_admin/models/cm_show_section.rb +20 -0
- data/lib/cm_admin/models/column.rb +61 -0
- data/lib/cm_admin/models/controller_method.rb +75 -0
- data/lib/cm_admin/models/dsl_method.rb +122 -0
- data/lib/cm_admin/models/export.rb +54 -0
- data/lib/cm_admin/models/field.rb +15 -0
- data/lib/cm_admin/models/filter.rb +95 -0
- data/lib/cm_admin/models/form_field.rb +21 -0
- data/lib/cm_admin/models/tab.rb +13 -0
- data/lib/cm_admin/utils.rb +67 -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 +65 -0
- data/lib/cm_admin/view_helpers/filter_helper.rb +190 -0
- data/lib/cm_admin/view_helpers/form_field_helper.rb +33 -0
- data/lib/cm_admin/view_helpers/form_helper.rb +65 -0
- data/lib/cm_admin/view_helpers/manage_column_popup_helper.rb +75 -0
- data/lib/cm_admin/view_helpers/navigation_helper.rb +34 -0
- data/lib/cm_admin/view_helpers/page_info_helper.rb +57 -0
- data/lib/cm_admin/view_helpers.rb +74 -0
- data/lib/cm_admin.rb +33 -2
- data/lib/generators/cm_admin/install_generator.rb +3 -13
- data/lib/tasks/webpack_install.rake +63 -0
- data/package.json +23 -0
- data/postcss.config.js +12 -0
- data/tmp/cache/webpacker/last-compilation-digest-development +1 -0
- data/yarn.lock +6933 -0
- metadata +155 -46
- data/lib/generators/cm_admin/USAGE +0 -8
- data/lib/generators/cm_admin/templates/assets/images/cm.png +0 -0
- data/lib/generators/cm_admin/templates/assets/stylesheets/application.css.scss +0 -33
- data/lib/generators/cm_admin/templates/assets/stylesheets/base/_variable.scss +0 -14
- data/lib/generators/cm_admin/templates/assets/stylesheets/base/input-styles.scss +0 -72
- data/lib/generators/cm_admin/templates/assets/stylesheets/base/main-nav.scss +0 -79
- data/lib/generators/cm_admin/templates/assets/stylesheets/base/scaffold.scss +0 -95
- data/lib/generators/cm_admin/templates/assets/stylesheets/base/show.scss +0 -88
- data/lib/generators/cm_admin/templates/assets/stylesheets/base/sidebar.scss +0 -69
- data/lib/generators/cm_admin/templates/assets/stylesheets/base/table.scss +0 -246
- data/lib/generators/cm_admin/templates/layouts/_navbar.html.slim +0 -8
- data/lib/generators/cm_admin/templates/layouts/_side_navbar.html.slim +0 -12
- data/lib/generators/cm_admin/templates/layouts/application.html.slim +0 -20
- data/lib/generators/cm_admin/templates/layouts/initializer.rb +0 -2
- data/lib/generators/cm_admin/templates/views/_form.erb +0 -67
- data/lib/generators/cm_admin/templates/views/_table.erb +0 -22
- data/lib/generators/cm_admin/templates/views/edit.erb +0 -10
- data/lib/generators/cm_admin/templates/views/index.erb +0 -11
- data/lib/generators/cm_admin/templates/views/new.erb +0 -10
- data/lib/generators/cm_admin/templates/views/reset_password.erb +0 -12
- data/lib/generators/cm_admin/templates/views/show.erb +0 -18
- data/lib/generators/cm_admin/templates/views/sign_in.erb +0 -18
- 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,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
|
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,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
|