Showing posts with label Active admin Addon. Show all posts
Showing posts with label Active admin Addon. Show all posts
ActiveAdmin Addons - Extends ActiveAdmin to enable a set of great optional UX improving add-ons

ActiveAdmin Addons - Extends ActiveAdmin to enable a set of great optional UX improving add-ons

June 07, 2017
ActiveAdmin Addons will extend your ActiveAdmin and enable a set of addons you can optionally use to improve the ActiveAdmin UI and make it awesome.

What you get:


  • Range Filter : Filter your results using a numeric range (i.e. age between 18-30).
  • Select2 : Cool select boxes for everyone.
  • Paperclip Integration : Show thumbnails or icons on your lists.
  • AASM Integration : Nice looking tags for states.
  • Enum Integration : Nice looking tags for enums.
  • Boolean Values : Beautiful boolean values.
  • Number Formatting : Format you currencies with ease.
  • List : Show Arrays or Hashes like a list.
  • Color Picker : Select colors from a pretty popup.
  • Date Time Picker : Pick date and time comfortably.

Installation


Add this line to your application's Gemfile:
 gem 'activeadmin_addons'  
And then execute:
 $ bundle  
After that, run the generator:
 $ rails g activeadmin_addons:install  
check here to see more information about this generator.

Default changes to behaviour


Installing this gem will enable the following changes by default:
  • The default date input will be :datepicker instead of :date_select
  • Filters and selects will offer integration with enumerize
  • All select boxes will use select2

Addons


Range Filter

To filter based on a range of values you can use range_select like this:
 filter :number, as: :range_select  

Select2


Default

With select2 the select control looks nicer, it works great with large collections and multiple selection. If you don't want to use it in a specific control, just add the "default-select" class:
 f.input :created_at, input_html: { class: "default-select" }  
If you don't want all the select controls wrapped by select2, you can change the default behavior setting as "default" the default_select option in the initializer.
 ActiveadminAddons.setup do |config|  
  config.default_select = "default"  
 end  
Now, if you want to enable select2 for a single control, you can add the "select2" class:
 f.input :created_at, input_html: { class: "select2" }  

Tagging

Using tags input, you can add tags using select2. To enable select2 with tags functionality you need to do the following:
 f.input :names, as: :tags  
You can load previous created tags using collection option passing an array of strings like this:
 f.input :names, as: :tags, collection: ['Julio', 'Emilio', 'Leandro']  

Tagging with Active Record collections


To use tagging functionality with Active Record collections you need to do something like this:
 class Event < ActiveRecord::Base  
  has_and_belongs_to_many :performers  
 end  
 class Performer < ActiveRecord::Base  
  has_and_belongs_to_many :events  
 end  
So, in the ActiveAdmin's Event form, you can add:
 f.input :performer_ids, as: :tags, collection: Performer.all, display_name: :full_name  
Remember: the input name must be: performer_ids not performers and you need to add to permit_params the performer_ids: [] key.

Options

  • display_name : (optional) You can pass an optional display_name to set the attribute (or method) to show results on the select. It defaults to: name
  • value : (optional) You can pass an optional value to set the attribute (or method) to use when an item is selected. It defaults to: id
  • width : (optional) You can set the select input width (px or %).

Selected List

This form control allows you to handle your many to many associations.
If, for example, you have something like this:
 class Event < ActiveRecord::Base  
  has_and_belongs_to_many :performers  
 end  
 class Performer < ActiveRecord::Base  
  has_and_belongs_to_many :events  
 end  
In the ActiveAdmin's Event form, you can add:
 f.input :performer_ids, as: :selected_list  
Remember: the input name must be: performer_ids not performers and you need to add to permit_params the performer_ids: [] key.

Options

  • url: (optional) This is the URL where to get the results. This URL expects an activeadmin collection Url (like the index action) or anything that uses ransack search gem. By default, the url will be inferred from the attribute. In the example: GET /admin/performers.
  • response_root: (optional) If a request to url responds with root, you can indicate the name of that root with this attribute. By default, the gem will try to infer the root from url. For example: if url is GET /admin/performers, the root will be performers. If you have a rootless api, you don't need to worry about this attribute.
  • minimum_input_length : (optional) Minimum number of characters required to initiate the search. It defaults to: 1
  • fields : (optional) An array of field names where to search for matches in the related model. If we give many fields, they will be searched with an OR condition.
  • display_name : (optional) You can pass an optional display_name to set the attribute to show results on the select. It defaults to: name.
  • width : (optional) You can set the select input width (px or %).
  • order_by : (optional) Order (sort) results by a specific attribute, suffixed with _desc or _asc. Eg: description_desc. By default is used the first field in descending direction.

Ajax Search

To enable select2 ajax search functionality you need to do the following:
 f.input :category_id, as: :search_select, url: admin_categories_path,  
      fields: [:name, :description], display_name: 'name', minimum_input_length: 2,  
      order_by: 'description_asc'  

Filter Usage


To use on filters you need to add as: :ajax_filter with same options. If you want to use url helpers, use a proc like on the example
 filter :category_id, as: :ajax_filter, url: proc { admin_categories_path },  
      fields: [:name, :description], display_name: 'name', minimum_input_length: 2,  
      order_by: 'description_asc'  

Options

  • category_id : Notice we're using the relation field name, not the realtion itself, so you can't use f.input :category.
  • url : This is the URL where to get the results. This URL expects an activeadmin collection Url (like the index action) or anything that uses ransack search gem.
  • response_root : (optional) If a request to url responds with root, you can indicate the name of that root with this attribute. By default, the gem will try to infer the root from url. For example: if url is GET /admin/categories, the root will be categories. If you have a rootless api, you don't need to worry about this attribute.
  • fields : an array of field names where to search for matches in the related model (Category in this example). If we give many fields, they will be searched with an OR condition.
  • display_name : (optional) You can pass an optional display_name to set the field to show results on the select. This will be the field read from the object on loading the form and also when reading data from the ajax response(on the JSON). It defaults to: name
  • minimum_input_length : (optional) Minimum number of characters required to initiate the search. It defaults to: 1
  • class : (optional) You can pass extra classes for your field.
  • width : (optional) You can set the select input width (px or %).
  • order_by : (optional) Order (sort) results by a specific attribute, suffixed with _desc or _asc. Eg: description_desc. By default is used the first field in descending direction.

Nested Select

Lets say you have the following Active Record models
 class Country < ActiveRecord::Base  
 end  
 class Region < ActiveRecord::Base  
  belongs_to :country  
 end  
 class City < ActiveRecord::Base  
  belongs_to :region  
 end  
And the following Active Admin pages:
 ActiveAdmin.register Country do  
  permit_params :name  
 end  
 ActiveAdmin.register Region do  
  permit_params :name, :country_id  
 end  
 ActiveAdmin.register City do  
  permit_params :name, :region_id  
 end  
to enable nested select functionality, you we'll need to do the following:
 f.input :city_id, as: :nested_select,  
          level_1: { attribute: :country_id },  
          level_2: { attribute: :region_id },  
          level_3: { attribute: :city_id }  
By default, the nested select input uses the index action of the different levels to get the data. For example, the level 2 (region) will perform an ajax request to /admin/regions&country_id_eq=[selected_country_id] to get the regions for a given country. It's not mandatory to register the ActiveAdmin pages. But, if you don't, you'll need to pass the url attribute, on each level, to make it work.
 f.input :city_id, as: :nested_select,  
          level_1: {  
           attribute: :country_id,  
           url: '/api/countries'  
          },  
          level_2: {  
           attribute: :region_id,  
           url: '/api/regions'  
          },  
          level_3: {  
           attribute: :city_id,  
           url: '/api/cities'  
          }  
Remember: those custom endpoints need to work with Ransack filters. Another option is to pass the collection attribute. If you set this, the url attribute will be ignored (no ajax request will be executed) and you will work with preloaded collections.
 f.input :city_id, as: :nested_select,  
          level_1: {  
           attribute: :country_id,  
           collection: Country.all  
          },  
          level_2: {  
           attribute: :region_id,  
           collection: Region.active  
          },  
          level_3: {  
           attribute: :city_id,  
           collection: City.all  
          }  

Options

Nested select, allows you to customize the general behavior of the input:
  • fields : (optional) An array of field names where to search for matches in the related model. If we give many fields, they will be searched with an OR condition.
  • display_name : (optional) You can pass an optional display_name to set the attribute (or method) to show results on the select. It defaults to: name
  • minimum_input_length : (optional) Minimum number of characters required to initiate the search. It defaults to: 1
  • response_root : (optional) If you have defined the url attribute and a request to that url responds with a root, you can indicate the name of that root with this attribute. By default, the gem will try to infer the root from url. For example: if url is GET /admin/countries, the root will be countries. If you have a rootless api, you don't need to worry about this attribute.
 f.input :city_id, as: :nested_select,  
          fields: [:name, :id],  
          display_name: :id,  
          minimum_input_length: 3,  
          level_1: { attribute: :country_id },  
          level_2: { attribute: :region_id },  
          level_3: { attribute: :city_id }  
Also, you can redefine general options on each level.
 f.input :city_id, as: :nested_select,  
          fields: [:name],  
          display_name: :name,  
          minimum_input_length: 0,  
          level_1: {  
           attribute: :country_id,  
           minimum_input_length: 3,  
           url: '/api/countries',  
           response_root: 'paises'  
          },  
          level_2: {  
           attribute: :region_id,  
           display_name: :id,  
          },  
          level_3: {  
           attribute: :city_id,  
           fields: [:name, :information]  
          }  
response_root is not valid as general configuration. You need to define this attribute by level. If you are using ajax search, you can define custom filters. For example, if you have:
 f.input :city_id, as: :nested_select,  
          level_1: { attribute: :country_id },  
          level_2: {  
           attribute: :region_id,  
           filters: { name_contains: "Cuy", id_gt: 22 }  
          },  
          level_3: { attribute: :city_id }  
After select a country, the regions will be filtered by:
  • The selected country id.
  • The text entered in the region's input.
  • All filters passed on :filters attribute. Each filter needs to be a key (Ransak gem style) with a value.

Paperclip Integration

For Images

Image Row
 show do  
  attributes_table do  
   image_row :photo  
  end  
 end  
Image Column
 index do  
  image_column :photo, style: :thumb  
 end  
You can pass style attribute matching paperclip's style definition

For Any Attachment

Displays a paperclip link with attachment related icon into index and show views.
Attachment Row
 show do  
  attributes_table do  
   attachment_row("My doc", :attachment, label: 'Download pdf file', truncate: false)  
  end  
 end  
Attachment Column
 index do  
  attachment_column :document  
 end  

Options

  • truncate : you can pass truncate attribute to toggle truncating the filename. attachment_column truncates by default.
  • label : if you want to show another text instead of the filename. It can be a string, or a proc if you need another attribute from the model attachment_column "Who wrote it", :pdf_file, label: proc { |book| book.author.name }

AASM Integration

You can show aasm values as active admin tags.
State Row
 show do  
  attributes_table do  
   state_row :state  
  end  
 end  
State Column
 index do  
  state_column :state  
 end  
The name of the state will be the class name (rejected, approved, etc.), but you can pass a hash of options to map different states with tag colors.
 state_column(:state, states: { destroyed: "rejected" })  
You will need to define inside your_app/app/assets/stylesheets/active_admin.css.scss the following:
 .status_tag {  
  &.rejected { background: $rejected-color; }  
  &.approved { background: $approved-color; }  
 }  

Enum Integration

You can show Rails' built in enums or enumerize values as active admin tags.

Boolean values

Bool Row
Modifies how boolean values are displayed in attributes_table control (the one used in show view) You just need to use bool_row method
 show do  
  attributes_table do  
   bool_row :paid  
  end  
 end  
Bool Column
Modifies how boolean values are displayed in index view You just need to use bool_column method
 index do  
  bool_column :paid  
 end  

Style

You can set your own style for boolean values, adding the following code to active_admin.scss file.
 .bool-value {  
  font-size: 12px;  
  &.true-value {  
   color: #08A510;  
  }  
  &.false-value {  
   color: #FF0000;  
  }  
 }  

i18n Support


The default values are:
  • true: ✔
  • false: ✗
Modifing the default
 es:  
  activeadmin:  
   addons:  
    boolean:  
     default:  
      true_value: pagada  
      false_value: no pagada  
Modifing a specific model
 es:  
  activeadmin:  
   addons:  
    boolean:  
     models:  
      invoice:  
       true_value: pagada  
       false_value: no pagada  
Modifing an specific model attribute
 es:  
  activeadmin:  
   addons:  
    boolean:  
     models:  
      invoice:  
       paid:  
        true_value: pagada  
        false_value: no pagada  

Number Formatting

Number Row
 show do  
  attributes_table do  
   number_row :number, as: :human  
  end  
 end  
Number Column
 index do  
  number_column :number, as: :currency, unit: "$", separator: ","  
 end  

Options

If you want to customize the default number format, you can pass the same options passed to Rails NumberHelper methods.

List

list_[row|column] takes as first param an attribute (or method) that must return an Array or Hash. For example:
 resource.skills  
 #=> ["Animation", "Branding", "Creative Director"]  
 resource.contact  
 #=> { "twitter" => "goku84", "facebook" => "kamehouse" }  
List Row
 show do  
  attributes_table do  
   list_row :skills, list_type: :ol  
   list_row :contact, localize: true  
  end  
 end  
List Column
 index do  
  list_column :skills  
  list_column :contact  
 end  

Options


  • localize : allows you to translate array values or hash keys using the following structure:
  •  [languaje]:  
      addons_list:  
       [model_name]:  
        [method]:  
         key1: value1  
         key2: value2  
    
     es:  
      addons_list:  
       resource:  
        contact:  
         twitter: TwiTTer  
         facebook: Face  
    
  • list_type : allows you to pick between :ul (unordered list) and :ol (ordered list) types.

Nested Lists

You can use list_row and list_column with nested data:
 {  
  title: "Detalle",  
  categories: ["home", "investment"],  
  picture: {  
   path: "invoice.png",  
   size: "5MB",  
   geo: {  
    lat: 12.34343,  
    lng: 34.4343  
   }  
  }  
 }  
When working with nested lists, the locales must be defined in the following way:
 es:  
  addons_list:  
   invoice:  
    details:  
     title: Título  
     categories: Categorías  
     categories_home: Hogar  
     categories_investment: Inversión  
     picture: Foto  
     picture_path: Path  
     picture_size: Tamaño  
     picture_geo: Geo  
     picture_geo_lat: Latitud  
     picture_geo_lng: Longitud  

Color Picker

Form
You can pick colors using JQuery Palette Color Picker
 form do |f|  
  f.inputs "Details" do  
   f.input :color, as: :color_picker  
  end  
  f.actions  
Options
palette : If you don't want default, you can pass your own colors:
 form do |f|  
  f.inputs "Details" do  
   f.input :color, as: :color_picker, palette: ["#DD2900","#D94000","#D55500","#D26A00","#CE7D00","#CA9000","#C6A300","#C2B400","#B9BF00"]  
  end  
  f.actions  

Date Time Picker

Form
You can pick dates with time using the xdan's jQuery Plugin Date and Time Picker
 form do |f|  
  f.inputs "Details" do  
   f.input :updated_at, as: :date_time_picker  
  end  
  f.actions  

Options

You can pass to picker_options, all the options available on xdan's library. Notice timepicker: false to only show a date picker
 form do |f|  
  f.inputs "Details" do  
   f.input :updated_at, as: :date_time_picker,  
              picker_options: {  
               min_date: Date.current - 2.days,  
               allow_times: [  
                '12:10', '13:10', '15:10',  
                '17:10', '18:10', '19:10'  
               ],  
               timepicker: false  
              }  
  end  
  f.actions  

Overriding defaults

You can add, in a Rails initializer, default options like this:
 datetime_picker_input = Formtastic::Inputs::StringInput::DateTimePickerInput  
 # This if for front-end javascript side  
 datetime_picker_input.default_datetime_picker_options = {  
  format: "d-m-Y H:i",  
  step: 10 # minutes  
 }  
 # This if for backend (Ruby)  
 datetime_picker_input.format = "%d-%m-%Y %H:%M"  


Note: Special thanks to Platanus

Contact - contact@platan.us

Disclaimer: The blog is created to share angular directives information to geek, curious Angular Developers.