How do I edit or override the footer of ActiveAdmin? - ruby-on-rails

How do I edit or override the footer of Active_Admin?

Answer:
In your rails app, create this file: app/admin/footer.rb
The content would be something like:
module ActiveAdmin
module Views
class Footer < Component
def build
super :id => "footer"
super :style => "text-align: right;"
div do
small "Cool footer #{Date.today.year}"
end
end
end
end
end
Don't forget! restart the app/server.
Any ActiveAdmin layout component can be customized like this.
More about it:
Why does it work?
This is Ruby's magic sauce. We are reopening the definition of the Footer class and changing it for our custom content.
Is it totally customizable? I don't know. This is the inheritance path:
ActiveAdmin
class Component < Arbre::Component
class Footer < Component
Arbre
class Component < Arbre::HTML::Div
This means that we can use Arbre's DSL directly.

If all you want to do is change or delete the 'powered by' message, what you can do is change its value in a locale file. Example, edit config/locales/en.yml
And use something like this:
en:
active_admin:
powered_by: "Powered by hamsters"
Why this works:
The default locale for a rails app is english, the en locale file.

Between v1.0.4pre and v.1.0.5pre, the previous method of overriding Footer#build no longer works well, and the new API is
ActiveAdmin.application.footer = proc {
...
}

For v.1.0.0.pre5 I found that the Accepted Answer requires a small additiion, namely adding a variable to build as below:
module ActiveAdmin
module Views
class Footer < Component
def build (namespace)
super :id => "footer"
super :style => "text-align: right;"
div do
small "Cool footer #{Date.today.year}"
end
end
end
end
end

From gist
create file in lib/footer.rb
class Footer < ActiveAdmin::Component
def build
super :id => "footer"
span "My Awesome footer"
end
end
add to initializers/active_admin.rb
ActiveAdmin.setup do |config|
......some config here....
config.view_factory.footer = Footer
......some config here....
end

Newer version of ActiveAdmin provides configurable option to set footer.
ActiveAdmin Footer Customization
config.footer = "MyApp Revision v1.3"
Footer can be configured using proc, where you can even render partial.
ActiveAdmin Footer Customization using proc
config.footer = proc { "Enjoy MyApp Revision 123, #{controller.current_admin_user.try(:email)}!" }
PR which added the ability to customize the footer

Related

HTML in pure Ruby

Is there such a gem exists for writing rails view helpers or even views? If not, what would be the starting point for such a gem?
div class: 'header' do
h1 { 'Hello World' }
a href: 'http://google.com', class: 'button' do
'Google'
end
end
Inspired by how recent javascript front-end libraries implement component based views using pure javascript functions, such as: React, Vue.js etc.
Maybe Markaby will help you, which lets you generate HTML through Ruby.
An example from the official docs:
require 'markaby'
mab = Markaby::Builder.new
mab.html do
head { title "Boats.com" }
body do
h1 "Boats.com has great deals"
ul do
li "$49 for a canoe"
li "$39 for a raft"
li "$29 for a huge boot that floats and can fit 5 people"
end
end
end
puts mab.to_s
Arbre will do the job.
It was extracted from widely used ActiveAdmin gem as independent solution for such needs.
A simple example from project's README:
html = Arbre::Context.new do
h2 "Why is Arbre awesome?"
ul do
li "The DOM is implemented in ruby"
li "You can create object oriented views"
li "Templates suck"
end
end
puts html.to_s # =>
will render the following:
<h2>Why is Arbre awesome?</h2>
<ul>
<li>The DOM is implemented in ruby</li>
<li>You can create object oriented views</li>
<li>Templates suck</li>
</ul>
Firstly, your code looks very similar to HAML:
#app/views/model/your_view.haml
.header
%h1 Hello World
= link_to "Google", "http://google.com", class: "button"
If you're looking for a way to clear up your views, that may be a good place to begin.
#Meeh looks like he has a good answer; if you wanted another opinion, I would start looking into pseudocode.
To my understanding, pseudocode is basically a way to create a "application-level" functionality of a deeper level. For example...
#app/helpers/view_helper.rb
class ViewHelper
def a approved_site, *options
return "Site not valid" unless Site.exists? name: approved_site.to_s
site = Site.find_by name: approved_site.to_s
options.extract_args!
link_to site.name, site.url, options #-> ruby automatically returns the last line
end
end
... this would allow you to call:
#app/views/controller/view.haml
= a :google, class: "button"
--
If you wanted to make that into a full-scale front-end framework, you'd need a collection of "base" functions. On top of those functions, you'd have more specific implementations, such as:
#app/helpers/base_helper.rb
class BaseHelper
def meta type, *args
types = %i(js css title link keywords author description robots favicon)
options = args.join(', ')
# Return Values
case type
when :title
Haml::Engine.new("%title #{options}").render
end
end
end
end
#app/helpers/meta_helper.rb
class MetaHelper
def title value
meta :title, value
end
end
I think you want react.rb (http://reactrb.org) Does everything Abre does, plus can deal with client side interactions as well (if you need it to.)
The dom gem that I have developed does exactly what you wanted to. Using it, you can do things like:
require "dom"
["foo".dom(:span, class: "bold"), "bar"].dom(:div).dom(:body).dom(:html)
# => "<html><body><div><span class=\"bold\">foo</span>bar</div></body></html>"

Using I18n markdown strings in HAML

I have localised markdown strings in my language file, and I am looking for a cleaner way to do the following in HAML:
#text_for_something
:markdown
#{ t(:text_in_markown) }
Or, equivalently:
#text_for_something!= Maruku.new( t(:text_in_markown) ).to_html
I know this is not what you were thinking of but you could just add the following helper to helpers/application_helper.rb
def render_md(key)
Maruku.new( t(key) ).to_html
end
and then just use it in your HAML like this:
#text_for_something!= render_md :text_in_markown
Hope it helps.
I ended up doing something similar for the i18n of my Rails Tutorial sample app. Not sure if it matters, but I used RDiscount to render Markdown.
In summary, I file each i18n-ized markdown file under a controller/action directory under config/locales, and determine which page needs to be rendered in the controller. For example, in the case of a simple About page, here is where the :en markdown file is located here:
config/locales/static_pages/about/about.en.md
About Us
========
Some more markdown text...
The path to the file to be rendered gets determined in the controller and assigned to #page, then the file itself gets rendered out in the relevant HAML partial:
app/controllers/static_pages_controller.rb
class StaticPagesController < ApplicationController
before_filter :localized_page
def about
# ...
end
# ...
protected
def localized_page
locale = params[:locale]
#page = "#{Rails.root}/config/locales/#{controller_name}/"\
"#{action_name}/#{action_name}.#{locale}.md"
end
end
app/views/static_pages/about.html.haml
= render 'static_page', title: t('.about_us'), page: #page
app/views/static_pages/_static_page.html.haml
- provide(:title, title) if title
:markdown
#{render file: page}

ActiveAdmin display default view content

I am working with ActiveAdmin and need to make customizations to some views and have come across a couple of scenarios I feel I am doing wrong.
I am adding an additional table to a show view (comments on Posts). This requires me to rewrite the whole attributes table and then add my panel. Is there a way to customize views without losing the default content?
I would also like to add a table of associated items on the show view which doesn't need to be customized is there any way to include the default tale that would normally be on the index view with default actions and paging?
After digging in the source code of Active Admin, I've found a way to patch this
show do
default_main_content
panel "Your Added Stuff" do
# Add stuff here
end
end
Of course this is undocumented and maybe considered a hack, but unless any other solution exists, it works.
Note: To do this in the form action (new and edit):
form do |f|
f.inputs
# Other inputs here
f.actions
end
Instead of using default_main_content, you could also just loop through the columns on the model like so:
ActiveAdmin.register Ad do
show do
attributes_table do
default_attribute_table_rows.each do |field|
row field
end
# Custom bits here
end
end
end
A couple areas of the documentation might help you:
See Customize the Show Page, Customizing the Index Page, Customizing the Form, and Custom Pages. An example of customizing a show screen:
ActiveAdmin.register Ad do
show do |ad|
default_main_content
h3 ad.title
end
end
See Custom Action Items in the Custom Controller Actions section of the documentation. An example:
action_item :only => :show, :if => proc{ current_admin_user.super_admin? } do
"Only display this to super admins on the show screen"
end
NB default_main_content does not exist in the documentation anymore, yet it works fine.
Just figured that out myself:
For the default table index page you can do something like this
index do
h1 "Hello World"
p "get more content"
instance_eval(&default_table)
end

How can I customize the active admin layout?

I need to customize the active admin layout, but how can I do it?
The active admin layout is not actually defined as a layout file, but is generated programatically. Placing a custom layout in the layout directory will therefore not actually override the default layout.
You can, however, monkey-patch or duck-punch the active admin layout methods inside your application.
The following will add an ie-specific stylesheet to the header:
module ActiveAdmin
module Views
module Pages
class Base < Arbre::HTML::Document
alias_method :original_build_active_admin_head, :build_active_admin_head unless method_defined?(:original_build_active_admin_head)
def build_active_admin_head
within #head do
meta :"http-equiv" => "Content-type", :content => "text/html; charset=utf-8"
insert_tag Arbre::HTML::Title, [title, active_admin_application.site_title].join(" | ")
active_admin_application.stylesheets.each do |path|
link :href => stylesheet_path(path), :media => "screen", :rel => "stylesheet", :type => "text/css"
end
active_admin_application.javascripts.each do |path|
script :src => javascript_path(path), :type => "text/javascript"
end
text_node csrf_meta_tag
text_node "<!--[if lt IE 7]>
<link rel=\"stylesheet\" type=\"text/css\" media=\"all\" href=\"admin_ie7.css\ />
<![endif] -->".html_safe
end
end
end
end
end
end
Clearly an ugly solution.
When a view is defined in a gem AND in the rails app, the one defined in the Rails app is served. It's a logic priority.
So if you need to override all or some active admin views, you'll have to copy these in your app and change them as you desire.
Maybe ActiveAdmin does provide a nicer way to do this by now? I don't know.
However here would be an example for a bit cleaner patch for that situation, in my example to add the webpacker gems javascript_pack_tag to my admin area.
module MyApp
module ActiveAdmin
module Views
module Pages
module BaseExtension
def build_active_admin_head
super
within #head do
text_node(javascript_pack_tag('application'))
end
end
end
end
end
end
end
class ActiveAdmin::Views::Pages::Base < Arbre::HTML::Document
prepend MyApp::ActiveAdmin::Views::Pages::BaseExtension
end
(Using rails 5.1.4) I tried two solutions here that involved messing with the active_admin library, and they did not work for me at all. I found my solution in config/initializers/active_admin.rb. I am adding a small amount of bootstrap styling to the default layout. As far as linking to stylesheets, javascripts, etc., it was as simple as adding this to my active_admin.rb, as per the comments therein:
# == Register Stylesheets & Javascripts
#
# We recommend using the built in Active Admin layout and loading
# up your own stylesheets / javascripts to customize the look
# and feel.
#
# To load a stylesheet:
# config.register_stylesheet 'my_stylesheet.css'
config.register_stylesheet 'https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css', { integrity: 'sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk', crossorigin: 'anonymous' }
As far as editing that generated layout, I have yet to figure it out, but it could at least be done indirectly via JavaScript and the inclusion of that javascipt in this file via
config.register_javascript 'active_admin_view_tweaks.js', { defer: true }
I am going to be editing class attributes to make my pages responsive with bootstrap, so I might follow something like this geeksforgeeks article to edit the pages with JavaScript after they've loaded.
I don't know if there is a way to edit the generated layout more directly, but this should work for some cases.
You can override the active admin page layout by putting the following code in your config/intializers/active_admin.rb file:
module AdminPageLayoutOverride
def build_page(*args)
within super do
render "shared/your_custom_view_partial"
end
end
end
ActiveAdmin::Views::Pages::Base.send :prepend, AdminPageLayoutOverride
In the above example, I have a custom view file at app/views/shared/_your_custom_view_partial.html.erb location and I am injecting that in all of my active admin pages by the above code.

How to add a link back to the application in ActiveAdmin?

I need to add a few links to certain pages of the application in the ActiveAdmin pages. I can do this using sidebars, but I'll have to repeat the code for each of my resources. Is there anyway of adding custom links to the header ? Or define a sidebar that will appear for all resources ?
I also wouldn't want to overlook setting config.site_title_link in initializers/active_admin.rb.
I'm pretty sure it takes a symbol representing the name of a route from your application, for example:
config.site_title_link = :root
would link the site title to your application's root_path.
Thanks #phoet ! Implemented it by overriding the HeaderRenderer instead:
module ActiveAdmin
module Views
class HeaderRenderer
def to_html
title + global_navigation + application_link + utility_navigation
end
def application_link
link_to('Back to Application', root_url)
end
end
end
end
i think there is no build-in way to do it, but you can override the render-logic in the TabsRenderer (2.2) / TabbedNavigation (3.0):
def render_menu(menu)
content_tag :ul, :id => #options[:id] do
menu.items.collect do |item|
render_item(item)
end.join.<<('your_custom_stuff').html_safe
end
end

Resources