Module: CmAdmin::Models::DslMethod

Extended by:
ActiveSupport::Concern
Defined in:
lib/cm_admin/models/dsl_method.rb

Instance Method Summary collapse

Instance Method Details

#action_group(name, icon_name: 'fa fa-list', icon_style: nil) ⇒ Object

Create a new group for actions

Examples:

Creating a group

group 'Basic Information', icon_name: 'fa fa-list', icon_style: 'color: #000000' do
  custom_action 'Edit', verb: 'get', display_type: :button, icon_name: 'fa fa-edit', icon_style: 'color: #000000' do
    @posts = Post.all
  end
end

Parameters:

  • name (String)

    the name of group

  • icon_name (String) (defaults to: 'fa fa-list')

    the icon name of group, follow font-awesome icon name

  • icon_style (String) (defaults to: nil)

    the icon style of group, follow font-awesome icon style, example: “–fa-primary-color: #fecb3e; –fa-secondary-color: #e63b7a;”



286
287
288
289
290
# File 'lib/cm_admin/models/dsl_method.rb', line 286

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: nil, html_attrs: {}) ⇒ Object

Note:

Alerts cannot be placed inside nested sections. If added within a nested section, the alert will appear on the wrapped cm_show_section.

Note:

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.

Examples:

Basic info alert

alert_box(header: "Information", body: "This is an informational message.", type: :info)

Basic info alert with custom body

alert_box(header: "Information", body: "This is an informational message. <br>This is a break text", type: :info)

Alert with custom partial

alert_box(partial: "/users/sessions/alert", display_if: ->(arg) { arg.present? })

Alert with conditional display and custom HTML attributes

alert_box(
  header: "Warning",
  body: "Please review your submission.",
  type: :warning,
  display_if: ->(user) { user.submissions.any?(&:incomplete?) },
  html_attrs: { id: "submission-warning", data: { turbo_frame: "warnings" } }
)

Parameters:

  • header (String, nil) (defaults to: nil)

    The title text for the alert.

  • body (String, nil) (defaults to: nil)

    A string to display as the body of the alert.

  • type (Symbol, nil) (defaults to: nil)

    The type of alert. Accepts one of the following symbols: :info, :success, :danger, :warning.

  • partial (String, nil) (defaults to: nil)

    The path to a custom partial or HTML for the alert.

  • display_if (Proc, nil) (defaults to: nil)

    A lambda function that determines whether the alert should be shown. Should return a boolean.

  • html_attrs (Hash) (defaults to: {})

    Additional HTML attributes to apply to the alert. Has no effect on partials.

See Also:



514
515
516
# File 'lib/cm_admin/models/dsl_method.rb', line 514

def alert_box(header: nil, body: nil, type: nil, icon_name: nil, partial: nil, display_if: nil, html_attrs: {})
  @section_fields << 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.

Examples:

Getting all columns

all_db_columns(exclude: ['id'])

Parameters:

  • exclude (Array)

    the array of fields to exclude



265
266
267
268
269
270
271
272
273
274
# File 'lib/cm_admin/models/dsl_method.rb', line 265

def all_db_columns(options = {})
  field_names = instance_variable_get(:@ar_model)&.columns&.map { |x| x.name.to_sym }
  if options.include?(:exclude) && field_names
    excluded_fields = ([] << options[: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 }, &block) ⇒ Object

Create a new bulk action for model

Examples:

Creating a bulk action

bulk_action name: 'approve', display_name: 'Approve', display_if: lambda { |arg| arg.draft? }, redirection_url: '/posts', icon_name: 'fa-regular fa-circle-check', verb: :patch, display_type: :modal, modal_configuration: { title: 'Approve Post', description: 'Are you sure you want approve this post', confirmation_text: 'Approve' }, execution_mode: :individual do
  posts = ::Post.where(id: params[:ids])
  posts.each(&:approved!)
  posts
end

Creating a bulk action with form modal

bulk_action name: 'approve', display_name: 'Approve', display_if: lambda { |arg| arg.draft? }, redirection_url: '/posts', icon_name: 'fa-regular fa-circle-check', verb: :patch, display_type: :form_modal, modal_configuration: { title: 'Approve Post', confirmation_text: 'Approve' }, execution_mode: :individual do
 form do
   cm_section 'Comment' do
     form_field :comment
   end
 end
 on_submit do |id|
   post = ::Post.find(id)
   post.approved!
   post
 end
end

Parameters:

  • name (String) (defaults to: nil)

    the name of action

  • display_name (String) (defaults to: nil)

    the display name of action

  • display_if (Proc) (defaults to: ->(_) { true })

    A lambda that takes the current object and return true or false

  • redirection_url (String) (defaults to: nil)

    the redirection url of action

  • icon_name (String) (defaults to: nil)

    the icon name of action, follow font-awesome icon name

  • verb (String) (defaults to: nil)

    the verb of action, get, post, put, patch or delete

  • display_type (Symbol) (defaults to: nil)

    the display type of action, :page, :modal, :form_modal, :button, :icon_only[deprecated]

  • modal_configuration (Hash) (defaults to: {})

    the configuration of modal

  • route_type (String) (defaults to: nil)

    the route type of action, member, collection

  • partial (String) (defaults to: nil)

    the partial path of action

  • execution_mode (Symbol) (defaults to: :individual)

    the types of execution mode are :bulk, :individual [default :individual]



415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
# File 'lib/cm_admin/models/dsl_method.rb', line 415

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 }, &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:, &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(page_title: nil, page_description: nil, partial: nil, redirect_to: nil) ⇒ 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/

Examples:

Editing page with a redirect

cm_edit(page_title: "Edit Post", page_description: 'Enter all details to edit Post', redirect_to: ->(current_object) { "/pages/#{current_object.id}" }) do
  cm_section 'Details' do
    form_field :title, input_type: :string
    form_field :body, input_type: :rich_text
  end
end

Parameters:

  • page_title (String) (defaults to: nil)

    or [Symbol] the title of page, if symbol passed, it will be a method name on model

  • page_description (String) (defaults to: nil)

    the description of page

  • partial (String) (defaults to: nil)

    the partial path of page

  • redirect_to (Proc, nil) (defaults to: nil)

    A lambda that takes the current object and redirect to path after update



71
72
73
74
75
76
# File 'lib/cm_admin/models/dsl_method.rb', line 71

def cm_edit(page_title: nil, page_description: nil, partial: nil, redirect_to: nil)
  @current_action = CmAdmin::Models::Action.find_by(self, name: 'edit')
  page_title ||= "Edit #{ar_model.model_name.plural.titleize}"
  @current_action.set_values(page_title, page_description, partial, redirect_to)
  yield
end

#cm_index(page_title: nil, page_description: nil, partial: nil, view_type: :table) ⇒ Object

Create a table for index page with pagination.

Examples:

Index page

cm_index do
  page_title 'Post'
  column :title
  column :created_at, field_type: :date, format: '%d %b, %Y'
  column :updated_at, field_type: :date, format: '%d %b, %Y', header: 'Last Updated At'
end

Parameters:

  • page_title (String) (defaults to: nil)

    the title of page

  • page_description (String) (defaults to: nil)

    the description of page

  • partial (String) (defaults to: nil)

    the partial path of page

  • view_type (Symbol) (defaults to: :table)

    view type of page :table, :card or :kanban



20
21
22
23
24
25
# File 'lib/cm_admin/models/dsl_method.rb', line 20

def cm_index(page_title: nil, page_description: nil, partial: nil, view_type: :table)
  @current_action = CmAdmin::Models::Action.find_by(self, name: 'index')
  page_title ||= ar_model.model_name.plural.titleize
  @current_action.set_values(page_title, page_description, partial, view_type)
  yield
end

#cm_new(page_title: nil, page_description: nil, partial: nil, redirect_to: nil) ⇒ 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/

Examples:

Creating a new page with a redirect

cm_new(page_title: "Add Post", page_description: 'Enter all details to add Post', redirect_to: ->(current_object) { "/pages/#{current_object.id}" }) do
  cm_section 'Details' do
    form_field :title, input_type: :string
    form_field :body, input_type: :rich_text
  end
end

Parameters:

  • page_title (String) (defaults to: nil)

    the title of page

  • page_description (String) (defaults to: nil)

    the description of page

  • partial (String) (defaults to: nil)

    the partial path of page

  • redirect_to (Proc, nil) (defaults to: nil)

    A lambda that takes the current object and redirect to path after create



98
99
100
101
102
103
# File 'lib/cm_admin/models/dsl_method.rb', line 98

def cm_new(page_title: nil, page_description: nil, partial: nil, redirect_to: nil)
  @current_action = CmAdmin::Models::Action.find_by(self, name: 'new')
  page_title ||= "Add #{ar_model.model_name.plural.titleize}"
  @current_action.set_values(page_title, page_description, partial, redirect_to)
  yield
end

#cm_section(section_name, display_if: nil, col_size: nil, html_attrs: nil, partial: nil, &block) ⇒ Object

Examples:

Creating a section

cm_section('Basic Information', display_if: ->(current_object) { current_object.name == 'John' }, col_size: 6, html_attrs: { class: 'section-class' }) do
  field :title, input_type: :string
end


200
201
202
203
204
# File 'lib/cm_admin/models/dsl_method.rb', line 200

def cm_section(section_name, display_if: nil, col_size: nil, html_attrs: nil, partial: 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, &block)
end

#cm_show(page_title: nil, page_description: nil, partial: nil) ⇒ Object

Create a view for show page

Examples:

Showing page

cm_show page_title: :title do
  tab :profile, '' do
    cm_section 'Post Details' do
      field :title
      field :body, field_type: :rich_text
      field :is_featured
      field :status, field_type: :tag, tag_class: STATUS_TAG_COLOR
    end
  end
end

Parameters:

  • page_title (String | Symbol) (defaults to: nil)

    the title of page, if symbol passed, it will be a method name on model

  • page_description (String) (defaults to: nil)

    the description of page

  • partial (String) (defaults to: nil)

    the partial path of page



44
45
46
47
48
49
# File 'lib/cm_admin/models/dsl_method.rb', line 44

def cm_show(page_title: nil, page_description: nil, partial: nil)
  @current_action = CmAdmin::Models::Action.find_by(self, name: 'show')
  page_title ||= ar_model.model_name.plural.titleize
  @current_action.set_values(page_title, page_description, partial)
  yield
end

#cm_show_section(section_name, display_if: nil, html_attrs: nil, partial: nil, &block) ⇒ Object

Deprecated.

Use #cm_section instead of this method



207
208
209
# File 'lib/cm_admin/models/dsl_method.rb', line 207

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.

Examples:

Creating a column

column('name', field_type: :string)

Parameters:

  • field_name (String)

    the name of field

  • field_type (Symbol)

    the type of field, :string, :text, :image, :date, :rich_text, :time, :integer, :decimal, :custom, :datetime, :money, :money_with_symbol, :link, :association, :enum, :tag, :attachment, :drawer

  • header (String)

    the header of field

  • format (String)

    the format of field for date field

  • helper_method (Symbol)

    the helper method for field, should be defined in custom_helper.rb file, will take two arguments, record and field_name

  • export_method (Symbol)

    the export method for field, should be defined in model, will take no arguments

  • height (Integer)

    the height of field for image field

  • width (Integer)

    the width of field for image field



225
226
227
228
229
230
231
232
233
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
# File 'lib/cm_admin/models/dsl_method.rb', line 225

def column(field_name, options = {})
  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? && options[: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? && options[: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 && options[: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 { |x| x.field_name.to_sym == field_name }
  terminate = false

  if duplicate_columns.size.positive?
    duplicate_columns.each do |column|
      if options[:field_type].to_s != 'association'
        terminate = true
      elsif options[:field_type].to_s == 'association' && column.association_name.to_s == options[:association_name].to_s
        terminate = true
      end
    end
  end

  return if terminate

  generate_filter_for_columns(field_name, add_to_filter: options[:add_to_filter])

  @available_fields[@current_action.name.to_sym] << CmAdmin::Models::Column.new(field_name, options)
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 }, &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]

Examples:

Creating a custom action with modal

custom_action name: 'approve', route_type: 'member', verb: 'patch', icon_name: 'fa-regular fa-circle-check', path: ':id/approve', display_type: :modal, display_if: lambda(&:draft?), modal_configuration: { title: 'Approve Post', description: 'Are you sure you want approve this post', confirmation_text: 'Approve' } do
  post = ::Post.find(params[:id])
  post.approved!
  post
end

Creating a custom action with button

custom_action name: 'approve', route_type: 'member', verb: 'patch', icon_name: 'fa-regular fa-circle-check', path: ':id/approve', display_type: :button, display_if: lambda(&:draft?), group_name: 'my action' do
  post = ::Post.find(params[:id])
  post.approved!
  post
end

Creating a custom action with form modal and form page

Parameters:

  • name (String) (defaults to: nil)

    the name of action

  • page_title (String) (defaults to: nil)

    the title of page

  • page_description (String) (defaults to: nil)

    the description of page

  • display_name (String) (defaults to: nil)

    the display name of action

  • verb (String) (defaults to: nil)

    the verb of action, get, post, put, patch or delete

  • layout (String) (defaults to: nil)

    the layout of action

  • layout_type (String) (defaults to: nil)

    the layout type of action, cm_association_index, cm_association_show

  • partial (String) (defaults to: nil)

    the partial path of action

  • path (String) (defaults to: nil)

    the path of action

  • display_type (Symbol) (defaults to: nil)

    the display type of action, :button, :modal , :form_modal, :form_page, :page, :icon_only

  • modal_configuration (Hash) (defaults to: {})

    the configuration of modal

  • url_params (Hash) (defaults to: {})

    the url params of action

  • display_if (Proc) (defaults to: ->(_) { true })

    A lambda that takes the current object and return true or false

  • route_type (String) (defaults to: nil)

    the route type of action, member, collection

  • icon_name (String) (defaults to: 'fa fa-th-large')

    the icon name of action, follow font-awesome icon name

  • icon_style (String) (defaults to: nil)

    the icon style of action, follow font-awesome icon style, example: “–fa-primary-color: #fecb3e; –fa-secondary-color: #e63b7a;”

  • group_name (String) (defaults to: nil)

    the group name of action, all the action with same group name will be grouped together in dropdown.



343
344
345
346
347
348
349
350
351
352
353
354
355
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
# File 'lib/cm_admin/models/dsl_method.rb', line 343

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 }, &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:,
    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, success_message, error_message, &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

Examples:

Eager load associations

eager_load_assocations [:association_name]
eager_load_assocations [:constant]


556
557
558
# File 'lib/cm_admin/models/dsl_method.rb', line 556

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

Examples:

Creating a filter

filter('name', :search)
filter('created_at', :date)
filter('status', :single_select, collection: ['draft', 'published'])
filter('status', :multi_select,  helper_method: 'status_collection')
filter('age', :range)

Parameters:

  • db_column_name (String)

    the name of column

  • filter_type (String) (defaults to: nil)

    the type of filter, :date, :multi_select, :range, :search, :single_select

  • placeholder (String)

    the placeholder of filter

  • helper_method (String)

    the helper method for filter, should be defined in custom_helper.rb file

  • filter_with (Symbol)

    filter with scope name on model

  • active_by_default (Boolean)

    make filter active by default

  • collection (Array)

    the collection of filter, use with single_select or multi_select



452
453
454
455
# File 'lib/cm_admin/models/dsl_method.rb', line 452

def filter(db_column_name, filter_type = nil, options = {})
  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

Parameters:

  • column_name (String)

    the name of column

  • exclude (Array) (defaults to: [])

    the array of fields to exclude

  • only (Array) (defaults to: [])

    the array of fields to include



125
126
127
128
129
130
131
# File 'lib/cm_admin/models/dsl_method.rb', line 125

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

Parameters:

  • description (String)

    the description of page



115
116
117
118
119
# File 'lib/cm_admin/models/dsl_method.rb', line 115

def page_description(description)
  return unless @current_action

  @current_action.page_description = description
end

#page_title(title) ⇒ Object

Set page title for current action

Parameters:

  • title (String)

    the title of page



107
108
109
110
111
# File 'lib/cm_admin/models/dsl_method.rb', line 107

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.

Examples:

Creating a row

row(display_if: ->(current_object) { current_object.name == 'John' }, html_attrs: { class: 'row-class' }) do
  cm_section 'Details' do
    form_field :title, input_type: :string
  end
end

Parameters:

  • display_if (Proc) (defaults to: nil)

    A lambda that takes the current object and return true or false

  • html_attrs (Hash) (defaults to: nil)

    A hash that contains html attributes



185
186
187
188
# File 'lib/cm_admin/models/dsl_method.rb', line 185

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

Parameters:

  • scopes (Array) (defaults to: [])

    the array of scopes



135
136
137
138
139
# File 'lib/cm_admin/models/dsl_method.rb', line 135

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

Examples:

Setting sort column

sort_column(:created_at)

Parameters:

  • column (Symbol) (defaults to: :created_at)

    the column name



476
477
478
# File 'lib/cm_admin/models/dsl_method.rb', line 476

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

Examples:

Setting sort direction

sort_direction(:asc)

Parameters:

  • direction (Symbol) (defaults to: :desc)

    the direction of sort, :asc, :desc



462
463
464
465
466
467
468
469
# File 'lib/cm_admin/models/dsl_method.rb', line 462

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

Note:

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'}])

Examples:

Sortable Columns

sortable_columns([{column: 'id', display_name: 'ID'},
                  {column: 'updated_at', display_name: 'Last Updated At'}])

Sortable Columns with default column and direction

Parameters:

  • columns (Array)

    the array of hash for column and display name

Raises:

  • (ArgumentError)


530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
# File 'lib/cm_admin/models/dsl_method.rb', line 530

def sortable_columns(columns)
  @sort_columns = columns
  default_column = 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, &block) ⇒ Object

Create a new tab on show page.

Examples:

Creating a tab

tab :comments, 'comment', associated_model: 'comments', layout_type: 'cm_association_index', show_count: true do
  column :message
end

Parameters:

  • tab_name (String)

    or [Symbol] the name of tab

  • action_name (String)

    the name of action

  • associated_model (String) (defaults to: nil)

    the name of associated model

  • layout_type (String) (defaults to: nil)

    the layout type of tab, cm_association_index, cm_association_show

  • layout (String) (defaults to: nil)

    the layout of tab

  • partial (String) (defaults to: nil)

    the partial path of tab

  • display_if (Proc) (defaults to: nil)

    A lambda that takes the current object and return true or false

  • view_type (Symbol) (defaults to: nil)

    view type of page :table or :card

  • show_count (Boolean) (defaults to: true)

    show count of records in tab, default is true

  • associated_model_name (String) (defaults to: nil)

    the name of associated model, if not provided, it will be the child_records class name



158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/cm_admin/models/dsl_method.rb', line 158

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, &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:)
    @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