Module: CmAdmin::Models::DslMethod

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

Instance Method Summary collapse

Instance Method Details

#alert_box(header: nil, body: nil, type: 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:



378
379
380
# File 'lib/cm_admin/models/dsl_method.rb', line 378

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



227
228
229
230
231
232
233
234
235
236
# File 'lib/cm_admin/models/dsl_method.rb', line 227

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: ->(_arg) { true }, redirection_url: nil, icon_name: nil, verb: nil, display_type: nil, modal_configuration: {}, route_type: nil, partial: nil, execution_mode: :individual, &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

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: ->(_arg) { 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, :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]



296
297
298
299
300
301
302
303
304
# File 'lib/cm_admin/models/dsl_method.rb', line 296

def bulk_action(name: nil, display_name: nil, display_if: ->(_arg) { true }, redirection_url: nil, icon_name: nil, verb: nil, display_type: nil, modal_configuration: {}, route_type: nil, partial: nil, execution_mode: :individual, &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:, &block
  )
  @available_actions << bulk_action
end

#cm_edit(page_title: nil, page_description: nil, partial: nil, redirect_to: nil) ⇒ Object

Create a form for edit action

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



63
64
65
66
67
# File 'lib/cm_admin/models/dsl_method.rb', line 63

def cm_edit(page_title: nil, page_description: nil, partial: nil, redirect_to: nil)
  @current_action = CmAdmin::Models::Action.find_by(self, name: 'edit')
  @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
# 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')
  @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

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



83
84
85
86
87
# File 'lib/cm_admin/models/dsl_method.rb', line 83

def cm_new(page_title: nil, page_description: nil, partial: nil, redirect_to: nil)
  @current_action = CmAdmin::Models::Action.find_by(self, name: 'new')
  @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


178
179
180
181
# File 'lib/cm_admin/models/dsl_method.rb', line 178

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



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

def cm_show(page_title: nil, page_description: nil, partial: nil)
  @current_action = CmAdmin::Models::Action.find_by(self, name: 'show')
  @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



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

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

  • height (Integer)

    the height of field for image field

  • width (Integer)

    the width of field for image field



201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
# File 'lib/cm_admin/models/dsl_method.rb', line 201

def column(field_name, options = {})
  @available_fields[@current_action.name.to_sym] ||= []
  raise 'Only one column can be locked in a table.' if @available_fields[@current_action.name.to_sym].select { |x| x.lockable }.size > 0 && options[:lockable]

  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

  @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, modal_configuration: {}, url_params: {}, display_if: ->(_arg) { true }, route_type: nil, icon_name: 'fa fa-th-large', &block) ⇒ Object

Create a new custom action for model

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?) do
  post = ::Post.find(params[:id])
  post.approved!
  post
end

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

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

    the configuration of modal

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

    the url params of action

  • display_if (Proc) (defaults to: ->(_arg) { 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



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

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, modal_configuration: {}, url_params: {}, display_if: ->(_arg) { true }, route_type: nil, icon_name: 'fa fa-th-large', &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:,
    action_type: :custom, route_type:, icon_name:, modal_configuration:,
    model_name: self.name, url_params:, &block
  )
  @available_actions << action
end

#filter(db_column_name, filter_type, 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)

    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



320
321
322
# File 'lib/cm_admin/models/dsl_method.rb', line 320

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



109
110
111
112
113
114
115
# File 'lib/cm_admin/models/dsl_method.rb', line 109

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



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

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



91
92
93
94
95
# File 'lib/cm_admin/models/dsl_method.rb', line 91

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



163
164
165
166
# File 'lib/cm_admin/models/dsl_method.rb', line 163

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



119
120
121
122
123
# File 'lib/cm_admin/models/dsl_method.rb', line 119

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



340
341
342
# File 'lib/cm_admin/models/dsl_method.rb', line 340

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

Raises:

  • (ArgumentError)


329
330
331
332
333
# File 'lib/cm_admin/models/dsl_method.rb', line 329

def sort_direction(direction = :desc)
  raise ArgumentError, "Select a valid sort direction like #{CmAdmin::Models::Action::VALID_SORT_DIRECTION.join(' or ')} instead of #{direction}" unless CmAdmin::Models::Action::VALID_SORT_DIRECTION.include?(direction.to_sym.downcase)

  @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

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

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

Parameters:

  • columns (Array)

    the array of hash for column and display name

Raises:

  • (ArgumentError)


392
393
394
395
396
397
398
399
400
401
402
403
404
# File 'lib/cm_admin/models/dsl_method.rb', line 392

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
  return if default_column.blank?

  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, custom_action, associated_model: nil, layout_type: nil, layout: nil, partial: nil, display_if: 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' do
  column :message
end

Parameters:

  • tab_name (String)

    or [Symbol] the name of tab

  • custom_action (String)

    the name of custom 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



139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/cm_admin/models/dsl_method.rb', line 139

def tab(tab_name, custom_action, associated_model: nil, layout_type: nil, layout: nil, partial: nil, display_if: nil, &block)
  if custom_action.to_s == ''
    @current_action = CmAdmin::Models::Action.find_by(self, name: 'show')
    @available_tabs << CmAdmin::Models::Tab.new(tab_name, '', display_if, &block)
  else
    action = CmAdmin::Models::Action.new(name: custom_action.to_s, verb: :get, path: ':id/' + custom_action,
                                         layout_type:, layout:, partial:, child_records: associated_model,
                                         action_type: :custom, display_type: :page, model_name: name)
    @available_actions << action
    @current_action = action
    @available_tabs << CmAdmin::Models::Tab.new(tab_name, custom_action, display_if, &block)
  end
  yield if block
end