Active Admin Navigation Links - ruby-on-rails

How do you add your own custom links dynamically to the ActiveAdmin global navigation header other than registering the pages/models? For example, if I want a link that can direct users to my home page for instance.

Seems like ActiveAdmin made it somewhat easier. I upgraded to version 0.6.2 and here is what you can do to add custom links anywhere in your navigation (the example below will add one custom menu item, and one custom dropdown):
In # config/initializers/active_admin.rb
ActiveAdmin.setup do |config|
config.namespace :admin do |admin|
admin.build_menu do |menu|
menu.add :label => "My Custom Link", :url => "/", :priority => 0
menu.add :label => "Pages" do |pages|
pages.add :label => "Homepage", :url => "/admin/homepage"
pages.add :label => "About Us", :url => "/admin/about-us"
pages.add :label => "Facebook", :url => "http://www.facebook.com", :html_options => { :target => "_blank" }
end
end
end
end
In case you already registered models with "Pages" as a parent menu (ie: in your app/admin/ folder, a model with menu :priority => 2, parent: 'Pages') it will keep those as well automatically!

I managed to to this by adding the ActiveAdmin::MenuItem to the current AdminAdmin controller. For example,
ActiveAdmin.register User, :name_space => :example_namespace do
controller do
private
def current_menu
item = ActiveAdmin::MenuItem.new :label => "Link Name", :url => 'http://google.com'
ActiveAdmin.application.namespaces[:example_namespace].menu.add(item)
ActiveAdmin.application.namespaces[:example_namespace].menu
end
end
end
I basically created a new ActiveAdmin::MenuItem and add it to the current ActiveAdmin menu with the namespace example_namespace and return the menu in the end of the current_menu method. Note: current_menu is a method expected by ActiveAdmin so don't change the name of it. You can add as many items you like and each of these items will be converted to a link on your navigation header. Note this works for ActiveAdmin version > 0.4.3 so you might need to do your own digging if you want to do it for version <= 0.4.3.

ActiveAdmin.register AdminPage do
menu :url => proc{ "#{AppConfig.url}/checkins/#{current_admin_user.try(:id)}" }
end
Here, you can use any of your db field values in the URL parameter to construct your own URL.

You can configure the site title in your active admin initializer. For example:
config.site_title_link = "/"
This will give you a link to your rootpage.

Related

How to set a parent menu priority in ActiveAdmin?

I have a couple of models in my Ruby on Rails application like "Plan", "Tester", "Module", etc. Using activeadmin gem, I would like to have a page for each of these entities and place each under a couple of different menus. So my code looks like the following:
ActiveAdmin.register Plan do
menu parent: 'Planning', priority: 1
ActiveAdmin.register Tester do
menu parent: 'Planning', priority: 2
ActiveAdmin.register Module do
menu parent: 'Bundle', priority: 1
ActiveAdmin.register User do
menu parent: 'Administration', priority: 1
I don't have a page for the top menus ('Planning', 'Bundle', 'Administration'), but I want to see them in a custom order and not the alphabetical order. So, my question is how could I set the priority (order) of the parent menus without having a corresponding page for each of them?
The items, which non model-based starts their priority from 10, so u can put 10+ priority for model-based menus.
If you need to set priorities among non model-based menus, you can build fake file under admin folder like admin/administration.rb with code:
ActiveAdmin.register_page "Administration" do
menu :label => "Administration", :priority => 15, :url => '#'
end
and admin/bundle.rb:
ActiveAdmin.register_page "Bundle" do
menu :label => "Bundle", :priority => 16, :url => '#'
end
so on
See 'Customizing Parent Menu Items' in the documentation.
# config/initializers/active_admin.rb
config.namespace :admin do |admin|
admin.build_menu do |menu|
menu.add label: 'Blog', priority: 0
end
end
# app/admin/post.rb
ActiveAdmin.register Post do
menu parent: 'Blog'
end

(Rails + Redmine) Display tab in the top menu depending upon user role

I am working on Redmine 1.4.x. I have two roles: client and employee. To separate the roles I have added is_client boolean attribute to the database. Here is the use case:
if is_client?
puts "it is client"
else
puts "it is employee"
end
Now depending upon this role I have to display Portal tab in the top menu. To achieve this I tried the following:
Redmine::MenuManager.map :top_menu do |menu|
menu.push :portal, "#", :html => {:id => "emp_portal", :onclick => "OpenEmployeePortal()"} , :if => (Proc.new { User.current.is_client? } && Proc.new { User.current.logged? })
end
But I couldn't succeed. It is showing the portal tab for both roles.
So how can I achieve this?
Try this
Redmine::MenuManager.map :top_menu do |menu|
menu.push :portal, "#", :html => {:id => "emp_portal", :onclick => "OpenEmployeePortal()"} , :if => (Proc.new { User.current.is_client? && User.current.logged? })
end

Add form in sidebar

In my ActiveAdmin app, I need to have a form in the sidebar (only for the show method) that will show a single (for the moment) datepicker. Once user click on the datepicker, the whole page should reload taking into account the date selected (within the show controller).
Any idea on how to add this simple form in a sidebar ?
EDIT
I tried the following but I'm not sure how the form can target a dedicated controller other than the current model.
sidebar :history, :only => :show do
form do |f|
f.input :start_date, :as => :datepicker
end
end
How can a form in a sidebar can target another controller than the one of the current model ?
I presume you have a show controller and don't mean the show action.
make the view into a partial called "whatever" (I call it this)
So, your whatever.erb.html looks like this
<%= render "whatever" %>
If you use Jquery Ui datepicker, you can add a onSelect function
$(".date").datepicker({
dateFormat: "yy-mm-dd",
onSelect: function() {
$('#range_form').submit();
}
}).attr( 'readOnly' , 'true' )
If you want a range add a form tag in your view with two date fields, else you just add one
<%= form_tag('/range', :id => "range_form", :remote => true) do -%>
<%= text_field_tag 'from', Date.now.strftime("%Y-%m-%d"),:class => "date"%>
<%= text_field_tag 'to', Date.now.strftime("%Y-%m-%d"), :class => "date"%>
<% end %>
For this you'll have to add a route in your routes.rb
match "/range/" => "show#todo_range", :as => :range
In your show controller
def range
time_range = ((Date.parse(params[:from]).midnight..Date.parse(params[:to]).midnight)
#whatever = Whatever.where(:date => time_range)
end
Then add a js view to handle the callback
$(".maindiv").empty().append(<%=j(render #whatever)%>)
I have not tested this exact code, so watch out for typos.
Good luck and comment if I need to edit

Active Admin - refresh second drop down based on first drop down, Ruby on Rails

I am using Active Admin Gem on Ruby on Rails. I have a form in which i have selected category and sub category and then accordingly i have to fill the data. So i created two tables in sqlite added in active admin resouce.
Every thing is working fine but the drop down of sub category is not getting filtered based on the category choosen.
I am new to Ruby and RoR too. I don't know how to refresh dropdown of the subcategory after selecting category.
I know i can do it from AJAX and javascript but i dont know where to code for that?
Also, is there any specific filter avaliable in Active Admin which will make it happen without ajax or javascript.
Any ideas or help will be highly appreciated.
i don't know if there is any specific filter avaliable in Active Admin, but i solved it in this 3-steps way (assuming category - is a house, subcategory - is a flat):
1-st step: define helper containing ajax request
(of course, you have to predefine path in routes.rb)
#application_helper.rb
def remote_request(type, path, params={}, target_tag_id)
"$.#{type}('#{path}',
{#{params.collect { |p| "#{p[0]}: #{p[1]}" }.join(", ")}},
function(data) {$('##{target_tag_id}').html(data);}
);"
end
2-nd step: add this method for :onchange action
#admin/inhabitants.rb (DSL with formtastic)
form do |f|
f.inputs do
#...
f.input :house, :input_html => {
:onchange => remote_request(:post, :change_flats, {:house_id=>"$('#house_id').val()"}, :flat_id)
}
f.input :flat
#...
end
end
3-rd step: render result of filtering
(you can render partial instead of :text, I decided leave it in one activeadmin resource file )
controller do
def change_flats
#flats = House.find_by_id(params[:house_id]).try(:flats)
render :text=>view_context.options_from_collection_for_select(#flats, :id, :flat_number)
end
end
I accomplished this as any non-rails developer working on a rails project would - quick and dirty. Here's how:
#...
f.input :user, :input_html => {
:onchange => "
var user = $(this).val();
$('#order_location_id').val(0).find('option').each(function(){
var $option = $(this),
isCorrectUser = ($option.attr('data-user') === user);
$option.prop('disabled',!isCorrectUser);
});
"
}
f.input :location, collection: Location.all.map{ |loc|
[loc.name,loc.id, {"data-user" => loc.user_id}]
}
#...
No AJAX required. Note that this does not remove the unwanted options, it just disables them (sufficient for my scenario). This could easily be made modular with a helper, but I really only needed the functionality once.
For anyone else wrestling with the same problem, look at this railscast
I faced the same problem here
here's how I implemented multiple dynamic select menus in activeadmin:
config/initializers/active_admin.rb
config.register_javascript 'exam_registrations.js.coffee'
app/admin/exam_registrations.rb
form do |f|
f.inputs "Exam Registration Details" do
f.input :user_id, :label => 'Teacher', :as => :select, :collection => User.where(:admin => 'false', :active => true).order(:name), :include_blank => true
f.input :student_id, :hint => 'Students grouped by teacher names', :as => :select, :collection => option_groups_from_collection_for_select(User.where(:admin => false, :active => true).order(:name), :students, :name, :id, :name)
f.input :lesson_id, :hint => 'Lessons grouped by student names', :as => :select, :collection => option_groups_from_collection_for_select(Student.where(:active => true).order(:name), :lessons, :name, :id, :name)
end
f.buttons
end
app/assets/javascripts/exam_registrations.js.coffee
#first menu
jQuery ->
$('#exam_registration_student_id').parent().hide()
students = $('#exam_registration_student_id').html()
$('#exam_registration_user_id').change ->
user = $('#exam_registration_user_id :selected').text()
escaped_user = user.replace(/([ #;&,.+*~\':"!^$[\]()=>|\/#])/g, '\\$1')
options = $(students).filter("optgroup[label='#{escaped_user}']").html()
if options
$('#exam_registration_student_id').html(options)
$('#exam_registration_student_id').parent().show()
else
$('#exam_registration_student_id').empty()
$('#exam_registration_lesson_id').empty()
# second menu
$('#exam_registration_lesson_id').parent().hide()
lessons = $('#exam_registration_lesson_id').html()
$('#exam_registration_student_id').click ->
student = $('#exam_registration_student_id :selected').text()
escaped_student = student.replace(/([ #;&,.+*~\':"!^$[\]()=>|\/#])/g, '\\$1')
options = $(lessons).filter("optgroup[label='#{escaped_student}']").html()
if options
$('#exam_registration_lesson_id').html(options)
$('#exam_registration_lesson_id').parent().show()
else
$('#exam_registration_lesson_id').empty()
restart the server and the menus work!
Now it's possible with this gem https://github.com/holyketzer/activeadmin-ajax_filter, use in you form code like this:
f.input :category_id, as: :select # ...
f.input :subcategory_id, as: :ajax_select, data: {
ajax_search_fields: [:category_id],
search_fields: [:subcategory_atrribute],
url: '/admin/subcategories/filter'
}
And in you subcategory resource page:
ActiveAdmin.register Subcategory do
include ActiveAdmin::AjaxFilter
# ...
end
don't forget to include assets
You can also use activeadmin_addons gem Nested Select
dependent-select could be also a good option

Rails Beginner - How to define 3 buttons enabling a user to make a choice?

I am aware this is a very basic question, we are very new to rails and have been unable to find a specific answer to this question.
Background: We have just 1 database containing product information (called Product), one column (type) contains information regarding the product type and is either a value of 1 or 2.
Aim: create 3 buttons on a page which correspond to different user choices
e.g. Button 1 - show items of type 1; Button 2 - show items of type 2; Button 3 - show all items.
Ideally the information regarding the button pressed should be visible to a number of pages within a class (we have an index page, as well as 3 others in the controller)
Would somebody be able to provide an outline of the code required to do this please?
I am guessing it is some combination involving the ..._controller.rb and..._helper.rb?
Thanks a lot for your patience
What I would do is the following.
First, create a scope or named_scope in your Project model for finding projects by type. You'll then be able to use this scope to query your projects depending on type.
# Rails 3
class Project
scope :by_type, lambda{ |type| where(type: type.to_i) unless type.nil? }
end
#Rails 2
class Project
named_scope :by_type, lambda do |type|
{ :conditions => { :type => type.to_i } } unless type.nil?
end
end
Next, create a before filter in your controller to load the projects of that type. The before filter should be applied to all pages where you want the buttons to be present:
class ProjectsController
before_filter :load_projects, :only => [:index, :action1, :action2]
protected
def load_projects
#projects = Project.by_type(params[:type])
end
end
Finally, create a partial for the buttons that you can include in the views that have the option of displaying different project types:
# _project_options.html.erb
<%= link_to "Button 1", :controller => params[:controller], :action => params[:action], :type => '1' %>
<%= link_to "Button 2", :controller => params[:controller], :action => params[:action], :type => '2' %>
<%= link_to "Button 3", :controller => params[:controller], :action => params[:action], :type => '' %>
You can then include this partial in each of your related views. And you'll be able to display the projects by doing something like this (if you have an _projects.html.erb partial defined):
render #projects
You can load all the Products and then hide them selectively with some javascript. Just add a class to your markup for each type of product, like this:
<%= link_to #product.name, product_path(#product), :class => #product.type %>

Resources