Module: CmAdmin::Models::DslMethod
- Extended by:
- ActiveSupport::Concern
- Defined in:
- lib/cm_admin/models/dsl_method.rb
Instance Method Summary collapse
-
#action_group(name, icon_name: 'fa fa-list', icon_style: nil) ⇒ Object
Create a new group for actions.
-
#alert_box(header: nil, body: nil, type: nil, icon_name: nil, partial: nil, display_if: ->(_arg) { true }, html_attrs: {}) ⇒ Object
Adds a new alert to the current section.
-
#all_db_columns(options = {}) ⇒ Object
Get all columns for a model for index layout.
-
#bulk_action(name: nil, display_name: nil, display_if: ->(_) { true }, redirection_url: nil, icon_name: nil, verb: nil, display_type: nil, modal_configuration: {}, route_type: nil, partial: nil, icon_style: nil, execution_mode: :individual, success_message: ->(_arg) { nil }, error_message: ->(_arg) { nil }, alert_type: :banner, &block) ⇒ Object
Create a new bulk action for model.
-
#cm_edit(display_name: 'Edit', page_title: nil, page_description: nil, partial: nil, redirect_to: nil, display_if: ->(_arg) { true }) ⇒ Object
Create a form for edit action.
-
#cm_index(display_name: nil, page_title: nil, page_description: nil, partial: nil, view_type: :table) ⇒ Object
Create a table for index page with pagination.
-
#cm_new(display_name: 'Add', page_title: nil, page_description: nil, partial: nil, redirect_to: nil, allow_create_action: -> { true }) ⇒ Object
Create a form for new action.
- #cm_section(section_name, display_if: nil, col_size: nil, html_attrs: nil, partial: nil, dynamic_fields: nil, &block) ⇒ Object
-
#cm_show(display_name: nil, page_title: nil, page_description: nil, partial: nil) ⇒ Object
Create a view for show page.
-
#cm_show_section(section_name, display_if: nil, html_attrs: nil, partial: nil, &block) ⇒ Object
deprecated
Deprecated.
Use #cm_section instead of this method
-
#column(field_name, options = {}) ⇒ Object
Create a new column on index layout.
-
#custom_action(name: nil, page_title: nil, page_description: nil, display_name: nil, verb: nil, layout: nil, layout_type: nil, partial: nil, path: nil, display_type: nil, redirect_to: nil, modal_configuration: {}, url_params: {}, display_if: ->(_) { true }, route_type: nil, icon_name: 'fa fa-th-large', icon_style: nil, group_name: nil, success_message: ->(_) { nil }, error_message: ->(_, _) { nil }, alert_type: :flash, &block) ⇒ Object
Create a new custom action for model custom_action name: ‘change_password’, route_type: ‘member’, verb: ‘get’, icon_name: ‘fa-solid fa-key’, page_title: ‘Change Password’, path: ‘:id/change_password’, display_type: :form_modal do form do cm_section ‘Password Details’ do form_field :username form_field :age_group_id, input_type: :single_select, helper_method: :age_group_type_collection form_field :cultural_background_ids, input_type: :multi_select, helper_method: :cultural_background_type_collection form_field :language, input_type: :single_select, helper_method: :language_collection end end on_submit do @customer = ::Customer.find(params) @customer.update!(gender_id: params[:age_group_id]) @customer end end Note: The form block is mandatory for form modal and form page.
-
#eager_load_associations(associations = []) ⇒ Object
Configure Eager load associations for action This will help us avoid N+1 queries.
-
#filter(db_column_name, filter_type = nil, options = {}) ⇒ Object
Create a new filter for model.
-
#kanban_view(column_name, exclude: [], only: []) ⇒ Object
Set kanban view for current action.
-
#page_description(description) ⇒ Object
Set page description for current action.
-
#page_title(title) ⇒ Object
Set page title for current action.
-
#row(display_if: nil, html_attrs: nil, &block) ⇒ Object
Create a new row on page or form.
-
#scope_list(scopes = []) ⇒ Object
Set scopes for current action.
-
#sort_column(column = :created_at) ⇒ Object
@deprecated: use #sortable_columns instead of this method Set sort column for filters.
-
#sort_direction(direction = :desc) ⇒ Object
@deprecated: use #sortable_columns instead of this method Set sort direction for filters.
-
#sortable_columns(columns) ⇒ Object
Configure sortable columns for model verified_at is a JSONB column, so we need to specify the sort_datatype sortable_columns([‘id’, display_name: ‘ID’, default: true, default_direction: ‘desc’, ‘updated_at’, display_name: ‘Last Updated At’, ‘verified_at’, display_name: ‘Verified At’, sort_datatype: ‘TIMESTAMP’]).
-
#tab(tab_name, action_name, associated_model: nil, layout_type: nil, layout: nil, partial: nil, display_if: nil, show_count: true, view_type: nil, associated_model_name: nil, allow_create_action: -> { true }, &block) ⇒ Object
Create a new tab on show page.
Instance Method Details
#action_group(name, icon_name: 'fa fa-list', icon_style: nil) ⇒ Object
Create a new group for actions
298 299 300 301 302 |
# File 'lib/cm_admin/models/dsl_method.rb', line 298 def action_group(name, icon_name: 'fa fa-list', icon_style: nil) @current_group = { name:, icon_name:, icon_style: } yield @current_group = nil end |
#alert_box(header: nil, body: nil, type: nil, icon_name: nil, partial: nil, display_if: ->(_arg) { true }, html_attrs: {}) ⇒ Object
Alerts cannot be placed inside nested sections. If added within a nested section, the alert will appear on the wrapped cm_show_section.
Only the specified types (info, success, danger, warning) are supported. Any other type will default to a standard div.
Adds a new alert to the current section.
534 535 536 |
# File 'lib/cm_admin/models/dsl_method.rb', line 534 def alert_box(header: nil, body: nil, type: nil, icon_name: nil, partial: nil, display_if: ->(_arg) { true }, html_attrs: {}) @current_action.alerts << CmAdmin::Models::Alert.new(header:, body:, type:, icon_name:, partial:, display_if:, html_attrs:) end |
#all_db_columns(options = {}) ⇒ Object
Get all columns for a model for index layout.
277 278 279 280 281 282 283 284 285 286 |
# File 'lib/cm_admin/models/dsl_method.rb', line 277 def all_db_columns( = {}) field_names = instance_variable_get(:@ar_model)&.columns&.map { |x| x.name.to_sym } if .include?(:exclude) && field_names excluded_fields = ([] << [:exclude]).flatten.map(&:to_sym) field_names -= excluded_fields end field_names.each do |field_name| column field_name end end |
#bulk_action(name: nil, display_name: nil, display_if: ->(_) { true }, redirection_url: nil, icon_name: nil, verb: nil, display_type: nil, modal_configuration: {}, route_type: nil, partial: nil, icon_style: nil, execution_mode: :individual, success_message: ->(_arg) { nil }, error_message: ->(_arg) { nil }, alert_type: :banner, &block) ⇒ Object
Create a new bulk action for model
429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 |
# File 'lib/cm_admin/models/dsl_method.rb', line 429 def bulk_action(name: nil, display_name: nil, display_if: ->(_) { true }, redirection_url: nil, icon_name: nil, verb: nil, display_type: nil, modal_configuration: {}, route_type: nil, partial: nil, icon_style: nil, execution_mode: :individual, success_message: ->(_arg) { nil }, error_message: ->(_arg) { nil }, alert_type: :banner, &block) bulk_action = CmAdmin::Models::BulkAction.new( name:, display_name:, display_if:, modal_configuration:, redirection_url:, icon_name:, action_type: :bulk_action, execution_mode:, verb:, display_type:, route_type:, partial:, icon_style:, success_message:, error_message:, alert_type:, &block ) if display_type == :form_modal @action = bulk_action @current_action = @action @current_action.verb = :post @available_actions << @action define_singleton_method(:on_submit) do |&code_block| @action.code_block = code_block end yield else @available_actions << bulk_action end end |
#cm_edit(display_name: 'Edit', page_title: nil, page_description: nil, partial: nil, redirect_to: nil, display_if: ->(_arg) { true }) ⇒ Object
Create a form for edit action
Create a form field for form
@param form_field [String] the name of field
@param input_type [Symbol] the type of field, +:integer+, +:decimal+, +:string+, +:single_select+, +:multi_select+, +:date+, +:date_time+, +:text+, +:switch+, +:custom_single_select+, +:checkbox_group+, +:radio_button+, +:custom_string+, +:custom_date+, +:radio_button_group+
@param is_required [Boolean] the field is required or not, or can be set automatically based on model validation
@param collection [Array] the collection of field, use with single_select or multi_select
For understanding difference between switch and check_box, refer to https://blog.uxtweak.com/checkbox-vs-toggle-switch/
74 75 76 77 78 79 80 |
# File 'lib/cm_admin/models/dsl_method.rb', line 74 def cm_edit(display_name: 'Edit', page_title: nil, page_description: nil, partial: nil, redirect_to: nil, display_if: ->(_arg) { true }) @current_action = CmAdmin::Models::Action.find_by(self, name: 'edit') page_title ||= "Edit #{formatted_name.pluralize}" @current_action.set_values(display_name, page_title, page_description, partial, redirect_to) @current_action.display_if = display_if yield end |
#cm_index(display_name: nil, page_title: nil, page_description: nil, partial: nil, view_type: :table) ⇒ Object
Create a table for index page with pagination.

21 22 23 24 25 26 |
# File 'lib/cm_admin/models/dsl_method.rb', line 21 def cm_index(display_name: nil, page_title: nil, page_description: nil, partial: nil, view_type: :table) @current_action = CmAdmin::Models::Action.find_by(self, name: 'index') page_title ||= formatted_name.pluralize @current_action.set_values(display_name, page_title, page_description, partial, view_type) yield end |
#cm_new(display_name: 'Add', page_title: nil, page_description: nil, partial: nil, redirect_to: nil, allow_create_action: -> { true }) ⇒ Object
Create a form for new action
Create a form field for form
@param form_field [String] the name of field
@param input_type [Symbol] the type of field, +:integer+, +:decimal+, +:string+, +:single_select+, +:multi_select+, +:date+, +:date_time+, +:text+, +:switch+, +:custom_single_select+, +:checkbox_group+, +:radio_button+, +:custom_string+, +:custom_date+, +:radio_button_group+
@param is_required [Boolean] the field is required or not, or can be set automatically based on model validation
@param collection [Array] the collection of field, use with single_select or multi_select
For understanding difference between switch and check_box, refer to https://blog.uxtweak.com/checkbox-vs-toggle-switch/
104 105 106 107 108 109 110 |
# File 'lib/cm_admin/models/dsl_method.rb', line 104 def cm_new(display_name: 'Add', page_title: nil, page_description: nil, partial: nil, redirect_to: nil, allow_create_action: -> { true }) @current_action = CmAdmin::Models::Action.find_by(self, name: 'new') page_title ||= "Add #{formatted_name.pluralize}" @current_action.set_values(display_name, page_title, page_description, partial, redirect_to) @current_action.allow_create_action = allow_create_action yield end |
#cm_section(section_name, display_if: nil, col_size: nil, html_attrs: nil, partial: nil, dynamic_fields: nil, &block) ⇒ Object
208 209 210 211 212 |
# File 'lib/cm_admin/models/dsl_method.rb', line 208 def cm_section(section_name, display_if: nil, col_size: nil, html_attrs: nil, partial: nil, dynamic_fields: nil, &block) @available_fields[@current_action.name.to_sym] ||= [] @available_fields[@current_action.name.to_sym] << CmAdmin::Models::Section.new(section_name, @current_action, @model, display_if, html_attrs, col_size, partial, dynamic_fields, &block) end |
#cm_show(display_name: nil, page_title: nil, page_description: nil, partial: nil) ⇒ Object
Create a view for show page
46 47 48 49 50 51 |
# File 'lib/cm_admin/models/dsl_method.rb', line 46 def cm_show(display_name: nil, page_title: nil, page_description: nil, partial: nil) @current_action = CmAdmin::Models::Action.find_by(self, name: 'show') page_title ||= formatted_name.pluralize @current_action.set_values(display_name, page_title, page_description, partial) yield end |
#cm_show_section(section_name, display_if: nil, html_attrs: nil, partial: nil, &block) ⇒ Object
Use #cm_section instead of this method
215 216 217 |
# File 'lib/cm_admin/models/dsl_method.rb', line 215 def cm_show_section(section_name, display_if: nil, html_attrs: nil, partial: nil, &block) cm_section(section_name, display_if:, html_attrs:, partial:, &block) end |
#column(field_name, options = {}) ⇒ Object
Create a new column on index layout.
234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 |
# File 'lib/cm_admin/models/dsl_method.rb', line 234 def column(field_name, = {}) return unless @current_action.instance_of?(CmAdmin::Models::Action) @available_fields[@current_action.name.to_sym] ||= [] if @available_fields[@current_action.name.to_sym].select(&:lockable).size.positive? && [:lockable] raise 'Only one column can be locked in a table.' end if @available_fields[@current_action.name.to_sym].select(&:kanban_image).size.positive? && [:kanban_image] raise 'Only one column can be kanban image in a card view.' end if @available_fields[@current_action.name.to_sym].select(&:kanban_footer).size >= 2 && [:kanban_footer] raise 'Only two columns can be kanban footer in a card view.' end duplicate_columns = @available_fields[@current_action.name.to_sym].filter do |x| !x.field_name.is_a?(Array) && x.field_name.to_sym == field_name end terminate = false if duplicate_columns.size.positive? duplicate_columns.each do |column| if [:field_type].to_s != 'association' terminate = true elsif [:field_type].to_s == 'association' && column.association_name.to_s == [:association_name].to_s terminate = true end end end return if terminate add_to_filter = [:add_to_filter].nil? || [:add_to_filter] generate_filter_for_columns(field_name, add_to_filter: add_to_filter) @available_fields[@current_action.name.to_sym] << CmAdmin::Models::Column.new(field_name, ) end |
#custom_action(name: nil, page_title: nil, page_description: nil, display_name: nil, verb: nil, layout: nil, layout_type: nil, partial: nil, path: nil, display_type: nil, redirect_to: nil, modal_configuration: {}, url_params: {}, display_if: ->(_) { true }, route_type: nil, icon_name: 'fa fa-th-large', icon_style: nil, group_name: nil, success_message: ->(_) { nil }, error_message: ->(_, _) { nil }, alert_type: :flash, &block) ⇒ Object
Create a new custom action for model custom_action name: ‘change_password’, route_type: ‘member’, verb: ‘get’, icon_name: ‘fa-solid fa-key’, page_title: ‘Change Password’, path: ‘:id/change_password’, display_type: :form_modal do
form do
cm_section 'Password Details' do
form_field :username
form_field :age_group_id, input_type: :single_select, helper_method: :age_group_type_collection
form_field :cultural_background_ids, input_type: :multi_select, helper_method: :cultural_background_type_collection
form_field :language, input_type: :single_select, helper_method: :language_collection
end
end
on_submit do
@customer = ::Customer.find(params[:id])
@customer.update!(gender_id: params[:customer][:age_group_id])
@customer
end
end Note: The form block is mandatory for form modal and form page. Params fields will always be under the parent class, for example: params[:age_group_id]
356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 |
# File 'lib/cm_admin/models/dsl_method.rb', line 356 def custom_action(name: nil, page_title: nil, page_description: nil, display_name: nil, verb: nil, layout: nil, layout_type: nil, partial: nil, path: nil, display_type: nil, redirect_to: nil, modal_configuration: {}, url_params: {}, display_if: ->(_) { true }, route_type: nil, icon_name: 'fa fa-th-large', icon_style: nil, group_name: nil, success_message: ->(_) { nil }, error_message: ->(_, _) { nil }, alert_type: :flash, &block) @action = CmAdmin::Models::CustomAction.new( page_title:, page_description:, name:, display_name:, verb:, layout:, layout_type:, partial:, path:, parent: current_action.name, display_type:, display_if:, redirect_to:, action_type: :custom, route_type:, icon_name:, icon_style:, modal_configuration:, model_name: self.name, url_params:, group_name:, alert_type:, success_message:, error_message:, &block ) if @current_group @action.group_name = @current_group[:name] @action.group_icon_name = @current_group[:icon_name] @action.group_icon_style = @current_group[:icon_style] end if %i[form_page form_modal].include?(display_type) @current_action = @action @available_actions << @action define_singleton_method(:on_submit) do |&code_block| if display_type == :form_modal @action.code_block = code_block else @action.verb = :get generate_update_action(name, path, verb, redirect_to, route_type, , , &code_block) end end yield else @available_actions << @action end end |
#eager_load_associations(associations = []) ⇒ Object
Configure Eager load associations for action This will help us avoid N+1 queries
597 598 599 |
# File 'lib/cm_admin/models/dsl_method.rb', line 597 def eager_load_associations(associations = []) @current_action.eager_load_associations = associations if @current_action end |
#filter(db_column_name, filter_type = nil, options = {}) ⇒ Object
Create a new filter for model
472 473 474 475 |
# File 'lib/cm_admin/models/dsl_method.rb', line 472 def filter(db_column_name, filter_type = nil, = {}) filter_type = default_filter_type(db_column_name, filter_type) @filters << CmAdmin::Models::Filter.new(db_column_name:, filter_type:, options:) end |
#kanban_view(column_name, exclude: [], only: []) ⇒ Object
Set kanban view for current action
132 133 134 135 136 137 138 |
# File 'lib/cm_admin/models/dsl_method.rb', line 132 def kanban_view(column_name, exclude: [], only: []) return unless @current_action @current_action.kanban_attr[:column_name] = column_name @current_action.kanban_attr[:exclude] = exclude @current_action.kanban_attr[:only] = only end |
#page_description(description) ⇒ Object
Set page description for current action
122 123 124 125 126 |
# File 'lib/cm_admin/models/dsl_method.rb', line 122 def page_description(description) return unless @current_action @current_action.page_description = description end |
#page_title(title) ⇒ Object
Set page title for current action
114 115 116 117 118 |
# File 'lib/cm_admin/models/dsl_method.rb', line 114 def page_title(title) return unless @current_action @current_action.page_title = title end |
#row(display_if: nil, html_attrs: nil, &block) ⇒ Object
Create a new row on page or form.
193 194 195 196 |
# File 'lib/cm_admin/models/dsl_method.rb', line 193 def row(display_if: nil, html_attrs: nil, &block) @available_fields[@current_action.name.to_sym] ||= [] @available_fields[@current_action.name.to_sym] << CmAdmin::Models::Row.new(@current_action, @model, display_if, html_attrs, &block) end |
#scope_list(scopes = []) ⇒ Object
Set scopes for current action
142 143 144 145 146 |
# File 'lib/cm_admin/models/dsl_method.rb', line 142 def scope_list(scopes = []) return unless @current_action @current_action.scopes = scopes end |
#sort_column(column = :created_at) ⇒ Object
@deprecated: use #sortable_columns instead of this method Set sort column for filters
496 497 498 |
# File 'lib/cm_admin/models/dsl_method.rb', line 496 def sort_column(column = :created_at) @current_action.sort_column = column.to_sym if @current_action end |
#sort_direction(direction = :desc) ⇒ Object
@deprecated: use #sortable_columns instead of this method Set sort direction for filters
482 483 484 485 486 487 488 489 |
# File 'lib/cm_admin/models/dsl_method.rb', line 482 def sort_direction(direction = :desc) unless CmAdmin::Models::Action::VALID_SORT_DIRECTION.include?(direction.to_sym.downcase) raise ArgumentError, "Select a valid sort direction like #{CmAdmin::Models::Action::VALID_SORT_DIRECTION.join(' or ')} instead of #{direction}" end @current_action.sort_direction = direction.to_sym if @current_action end |
#sortable_columns(columns) ⇒ Object
default sort direction will be ascending
Configure sortable columns for model verified_at is a JSONB column, so we need to specify the sort_datatype
sortable_columns([{column: 'id', display_name: 'ID', default: true, default_direction: 'desc'},
{column: 'updated_at', display_name: 'Last Updated At'},
{column: 'verified_at', display_name: 'Verified At', sort_datatype: 'TIMESTAMP'}])
570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 |
# File 'lib/cm_admin/models/dsl_method.rb', line 570 def sortable_columns(columns) @sort_columns = columns.map do |column| column[:display_if] ||= ->(_arg) { true } column end default_column = @sort_columns.filter do |column| column.key?(:default) || column.key?(:default_direction) end raise ArgumentError, 'only one column can be default' if default_column.size > 1 if default_column.blank? @default_sort_column = nil @default_sort_direction = 'asc' return end default_column = default_column.first @default_sort_column = default_column[:column] @default_sort_direction = default_column[:default_direction] if default_column[:default_direction].present? end |
#tab(tab_name, action_name, associated_model: nil, layout_type: nil, layout: nil, partial: nil, display_if: nil, show_count: true, view_type: nil, associated_model_name: nil, allow_create_action: -> { true }, &block) ⇒ Object
Create a new tab on show page.
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
# File 'lib/cm_admin/models/dsl_method.rb', line 165 def tab(tab_name, action_name, associated_model: nil, layout_type: nil, layout: nil, partial: nil, display_if: nil, show_count: true, view_type: nil, associated_model_name: nil, allow_create_action: -> { true }, &block) action_name = action_name.to_s.gsub(' ', '').underscore if action_name.to_s == '' @current_action = CmAdmin::Models::Action.find_by(self, name: 'show') @available_tabs << CmAdmin::Models::Tab.new(tab_name, '', display_if, show_count, &block) else action = CmAdmin::Models::Action.new(name: action_name.to_s, verb: :get, path: ":id/#{action_name}", layout_type:, layout:, partial:, child_records: associated_model, action_type: :tab, display_type: :page, model_name: name, view_type:, associated_model_name:, allow_create_action:) @available_actions << action @current_action = action @available_tabs << CmAdmin::Models::Tab.new(tab_name, action_name, display_if, show_count, &block) end yield if block end |