Revision 611fd588
Added by Amos Benari over 10 years ago
app/assets/javascripts/topbar.js | ||
---|---|---|
'position': 'static'
|
||
});
|
||
|
||
$("[class^='menu_tab_']").removeClass('active');
|
||
$('.menu_tab_settings').addClass($('#current_tab').attr('data-settings'));
|
||
$('.menu_tab_'+$('#current_tab').attr('data-controller')).addClass('active').next('.dropdown').addClass('active');
|
||
mark_active_menu();
|
||
|
||
$('.dropdown-toggle').dropdown();
|
||
if(!is_mobile()){
|
||
... | ... | |
}
|
||
})
|
||
|
||
//open main menu on hover
|
||
$(document).on('mouseenter', '.dropdown.menu_tab_dropdown', function(){
|
||
if(!$(this).hasClass('open')){
|
||
$(this).find('.dropdown-toggle:first').click();
|
||
}
|
||
});
|
||
|
||
function mark_active_menu() {
|
||
$("[class^='menu_tab_']").removeClass('active');
|
||
// if there is no menu for controller_action mark controller_index as active menu
|
||
var active_menu = $('.menu_tab_'+$('#current_tab').data('controller')+'_'+$('#current_tab').data('action'))
|
||
if (!active_menu.exists()){
|
||
active_menu = $('.menu_tab_'+$('#current_tab').data('controller')+'_index')
|
||
}
|
||
active_menu.addClass('active');
|
||
$('.menu_tab_dropdown').each(function(){
|
||
if ($(this).find('.active').length >0) {$(this).addClass('active')}
|
||
})
|
||
}
|
||
|
||
function is_mobile() {
|
||
var check = false;
|
||
(function(a){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4)))check = true})(navigator.userAgent||navigator.vendor||window.opera);
|
app/controllers/about_controller.rb | ||
---|---|---|
def index
|
||
@proxies = SmartProxy.my_proxies.includes(:features)
|
||
@compute_resources = ComputeResource.my_compute_resources
|
||
@plugins = Foreman::Plugin.all
|
||
end
|
||
|
||
end
|
app/controllers/api/v2/plugins_controller.rb | ||
---|---|---|
module Api
|
||
module V2
|
||
class PluginsController < BaseController
|
||
|
||
api :GET, '/plugins', 'List of installed plugins'
|
||
def index
|
||
@plugins = Foreman::Plugin.all
|
||
end
|
||
|
||
end
|
||
end
|
||
end
|
app/helpers/home_helper.rb | ||
---|---|---|
module HomeHelper
|
||
|
||
def class_for_setting_page
|
||
setting_options.flatten.include?(controller_name.to_sym) ? "active" : ""
|
||
end
|
||
|
||
def setting_options
|
||
authorized_menu_actions(settings_menu_items)+[[_('About'), :about]]
|
||
end
|
||
|
||
def settings_menu_items
|
||
configuration_group =
|
||
[[_('Environments'), :environments],
|
||
[_('Global Parameters'), :common_parameters],
|
||
[_('Host Groups'), :hostgroups],
|
||
[_('Puppet Classes'), :puppetclasses],
|
||
[_('Smart Variables'), :lookup_keys],
|
||
[_('Smart Proxies'), :smart_proxies]]
|
||
menu_items = [ [:group, _("Configuration"), configuration_group]]
|
||
|
||
if SETTINGS[:unattended]
|
||
provisioning_group =
|
||
[[_('Architectures'), :architectures],
|
||
[_('Compute Resources'), :compute_resources],
|
||
[_('Domains'), :domains],
|
||
[_('Hardware Models'), :models],
|
||
[_('Installation Media'), :media],
|
||
[_('Operating Systems'), :operatingsystems],
|
||
[_('Partition Tables'), :ptables],
|
||
[_('Provisioning Templates'), :config_templates],
|
||
[_('Subnets'), :subnets]]
|
||
menu_items += [[:divider], [:group, _("Provisioning"), provisioning_group]]
|
||
end
|
||
|
||
if (SETTINGS[:organizations_enabled] or SETTINGS[:locations_enabled])
|
||
menu_items += [[:divider]]
|
||
menu_items += [ [_('Locations'), :locations] ] if SETTINGS[:locations_enabled]
|
||
menu_items += [ [_('Organizations'), :organizations] ] if SETTINGS[:organizations_enabled]
|
||
end
|
||
|
||
users_group =
|
||
[[_('LDAP Authentication'), :auth_source_ldaps],
|
||
[_('Users'), :users],
|
||
[_('User Groups'), :usergroups]]
|
||
users_group += [[_('Roles'), :roles]] if User.current && User.current.admin?
|
||
|
||
menu_items += [[:divider], [:group, _("Users"), users_group] ] if SETTINGS[:login]
|
||
|
||
menu_items += [
|
||
[:divider],
|
||
[_('Bookmarks'), :bookmarks],
|
||
[_('Settings'), :settings]
|
||
]
|
||
menu_items
|
||
def render_menu menu_name
|
||
authorized_menu_actions(Menu::Manager.items(menu_name).children).map do |menu|
|
||
items = authorized_menu_actions(menu.children)
|
||
render "home/submenu", :menu_items => items, :menu_title => _(menu.caption) if items.any?
|
||
end.join(' ').html_safe
|
||
end
|
||
|
||
def authorized_menu_actions(choices)
|
||
last_item = nil
|
||
choices = choices.map do |item|
|
||
#prevent adjacent dividers
|
||
if item == [:divider]
|
||
if last_item
|
||
last_item = nil
|
||
item
|
||
end
|
||
elsif item.size == 2 && authorized_for(item[1], :index)
|
||
last_item = item
|
||
item
|
||
elsif item.size == 3
|
||
item[2] = item[2].map do |sub_item|
|
||
sub_item if authorized_for(sub_item[1], :index)
|
||
end.compact
|
||
if item[2].size > 0
|
||
last_item = item
|
||
item
|
||
end
|
||
end
|
||
last_item = Menu::Divider.new(:first_div)
|
||
choices = choices.map do |item|
|
||
last_item = case item
|
||
when Menu::Divider
|
||
item unless last_item.is_a?(Menu::Divider) #prevent adjacent dividers
|
||
when Menu::Item
|
||
item if item.authorized?
|
||
when Menu::Toggle
|
||
item if item.authorized_children.size > 0
|
||
end
|
||
end.compact
|
||
choices.pop if (choices.last == [:divider])
|
||
choices.shift if choices.first.is_a?(Menu::Divider)
|
||
choices.pop if choices.last.is_a?(Menu::Divider)
|
||
choices
|
||
end
|
||
|
||
def menu(tab, label, path = nil)
|
||
path ||= send("hash_for_#{tab}_path")
|
||
return '' unless authorized_for(path[:controller], path[:action] )
|
||
content_tag(:li, :class => "menu_tab_#{tab} ") do
|
||
link_to_if_authorized(label, path)
|
||
end
|
||
def menu_item_tag item
|
||
content_tag(:li,
|
||
link_to(_(item.caption), item.url_hash, item.html_options.merge(:id => "menu_item_#{item.name}")),
|
||
:class => "menu_tab_#{item.url_hash[:controller]}_#{item.url_hash[:action]}")
|
||
end
|
||
|
||
def org_switcher_title
|
||
... | ... | |
title
|
||
end
|
||
|
||
# filters out any non allowed actions from the setting menu.
|
||
def allowed_choices choices, action = "index"
|
||
choices.map do |opt|
|
||
name, kontroller = opt
|
||
url = send("#{kontroller}_url")
|
||
authorized_for(kontroller, action) ? [name, url] : nil
|
||
end.compact.sort
|
||
end
|
||
|
||
def user_header
|
||
summary = gravatar_image_tag(User.current.mail, :class=>'gravatar small', :alt=>_('Change your avatar at gravatar.com')) +
|
||
"#{User.current.to_label} " + content_tag(:span, "", :class=>'caret')
|
app/services/foreman/access_control.rb | ||
---|---|---|
|
||
def permission(name, hash, options={})
|
||
@permissions ||= []
|
||
options.merge!(:security_block => @security_block)
|
||
options.merge!(:security_block => @security_block) if @security_block
|
||
@permissions << Permission.new(name, hash, options)
|
||
end
|
||
|
app/services/foreman/access_permissions.rb | ||
---|---|---|
map.security_block :tasks do |map|
|
||
map.permission :view_tasks, {:trends => [:show]}
|
||
end
|
||
|
||
map.security_block :plugins do |map|
|
||
map.permission :view_plugins, {:plugins => [:index],
|
||
:"api/v2/plugins" => [:index]
|
||
}
|
||
end
|
||
end
|
app/services/foreman/plugin.rb | ||
---|---|---|
# Redmine - project management software
|
||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||
#
|
||
# This program is free software; you can redistribute it and/or
|
||
# modify it under the terms of the GNU General Public License
|
||
# as published by the Free Software Foundation; either version 2
|
||
# of the License, or (at your option) any later version.
|
||
#
|
||
# This program is distributed in the hope that it will be useful,
|
||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
# GNU General Public License for more details.
|
||
#
|
||
# You should have received a copy of the GNU General Public License
|
||
# along with this program; if not, write to the Free Software
|
||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||
|
||
module Foreman #:nodoc:
|
||
|
||
class PluginNotFound < Foreman::Exception; end
|
||
class PluginRequirementError < Foreman::Exception; end
|
||
|
||
# Base class for Foreman plugins.
|
||
# Plugins are registered using the <tt>register</tt> class method that acts as the public constructor.
|
||
#
|
||
# Foreman::Plugin.register :example do
|
||
# name 'Example plugin'
|
||
# author 'John Smith'
|
||
# description 'This is an example plugin for Foreman'
|
||
# version '0.0.1'
|
||
# end
|
||
#
|
||
class Plugin
|
||
|
||
@registered_plugins = {}
|
||
class << self
|
||
attr_reader :registered_plugins
|
||
private :new
|
||
|
||
def def_field(*names)
|
||
class_eval do
|
||
names.each do |name|
|
||
define_method(name) do |*args|
|
||
args.empty? ? instance_variable_get("@#{name}") : instance_variable_set("@#{name}", *args)
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
# Plugin constructor
|
||
def register(id, &block)
|
||
plugin = new(id)
|
||
if (gem = Gem.loaded_specs[id.to_s])
|
||
plugin.name gem.name
|
||
plugin.author gem.authors.join(',')
|
||
plugin.description gem.description
|
||
plugin.url gem.homepage
|
||
plugin.version gem.version.to_s
|
||
end
|
||
|
||
plugin.instance_eval(&block)
|
||
|
||
registered_plugins[id] = plugin
|
||
end
|
||
|
||
# Clears the registered plugins hash
|
||
# It doesn't unload installed plugins
|
||
def clear
|
||
@registered_plugins = {}
|
||
end
|
||
|
||
# Returns an array of all registered plugins
|
||
def all
|
||
registered_plugins.values.sort
|
||
end
|
||
|
||
# Finds a plugin by its id
|
||
def find(id)
|
||
registered_plugins[id.to_sym]
|
||
end
|
||
|
||
# Checks if a plugin is installed
|
||
#
|
||
# @param [String] id name of the plugin
|
||
def installed?(id)
|
||
registered_plugins[id.to_sym].present?
|
||
end
|
||
end
|
||
|
||
def_field :name, :description, :url, :author, :author_url, :version
|
||
attr_reader :id
|
||
|
||
def initialize(id)
|
||
@id = id.to_sym
|
||
end
|
||
|
||
|
||
def <=>(plugin)
|
||
self.id.to_s <=> plugin.id.to_s
|
||
end
|
||
|
||
def to_s
|
||
"Foreman plugin: #{id}, #{version}, #{author}, #{description}"
|
||
end
|
||
|
||
# Sets a requirement on Foreman version
|
||
# Raises a PluginRequirementError exception if the requirement is not met
|
||
# matcher format is gem dependency format
|
||
def requires_foreman(matcher)
|
||
current = SETTINGS[:version].notag
|
||
unless Gem::Dependency.new('', matcher).match?('', current)
|
||
raise PluginRequirementError.new(N_("%{id} plugin requires Foreman %{matcher} but current is %{current}" % {:id=>id, :matcher => matcher, :current=>current}))
|
||
end
|
||
true
|
||
end
|
||
|
||
# Sets a requirement on a Foreman plugin version
|
||
# Raises a PluginRequirementError exception if the requirement is not met
|
||
# matcher format is gem dependency format
|
||
def requires_foreman_plugin(plugin_name, matcher)
|
||
plugin = Plugin.find(plugin_name)
|
||
raise PluginNotFound.new(N_("%{id} plugin requires the %{plugin_name} plugin, not found") % {:id =>id, :plugin_name=>plugin_name}) unless plugin
|
||
unless Gem::Dependency.new('', matcher).match?('', plugin.version)
|
||
raise PluginRequirementError.new(N_("%{id} plugin requires the %{plugin_name} plugin %{matcher} but current is %{plugin_version}" % {:id=>id, :plugin_name=>plugin_name,:matcher=> matcher,:plugin_version=>plugin.version}))
|
||
end
|
||
true
|
||
end
|
||
|
||
# Adds an item to the given menu
|
||
# The id parameter is automatically added to the url.
|
||
# menu :menu_name, :plugin_example, 'menu text', { :controller => :example, :action => :index }
|
||
#
|
||
# name parameter can be: :top_menu or :admin_menu
|
||
#
|
||
def menu(menu, name, options={})
|
||
options.merge!(:parent => @parent) if @parent
|
||
Menu::Manager.map(menu).item(name, options)
|
||
end
|
||
|
||
alias :add_menu_item :menu
|
||
|
||
def sub_menu(menu, name, options={}, &block)
|
||
options.merge!(:parent => @parent) if @parent
|
||
Menu::Manager.map(menu).sub_menu(name, options)
|
||
current = @parent
|
||
@parent = name
|
||
self.instance_eval(&block)
|
||
@parent = current
|
||
end
|
||
|
||
# Removes item from the given menu
|
||
def delete_menu_item(menu, item)
|
||
Menu::Manager.map(menu).delete(item)
|
||
end
|
||
|
||
def security_block(name, &block)
|
||
@security_block = name
|
||
self.instance_eval(&block)
|
||
@security_block = nil
|
||
end
|
||
|
||
# Defines a permission called name for the given controller=>actions
|
||
def permission(name, hash, options={})
|
||
options.merge!(:security_block => @security_block)
|
||
Foreman::AccessControl.map do |map|
|
||
map.permission name, hash, options
|
||
end
|
||
end
|
||
|
||
# Add a new role if it doesn't exist
|
||
def role(name, permissions)
|
||
Role.transaction do
|
||
role = Role.find_or_create_by_name(name)
|
||
role.update_attribute :permissions, permissions if role.permissions.empty?
|
||
end
|
||
end
|
||
|
||
end
|
||
end
|
app/services/foreman/version.rb | ||
---|---|---|
|
||
# Simple struct for manipulation and comparing versions
|
||
class Version
|
||
attr_reader :version, :major, :minor, :build, :tag, :short
|
||
attr_reader :version, :major, :minor, :build, :tag, :short, :notag
|
||
alias :full :version
|
||
|
||
def initialize givenversion=nil
|
||
... | ... | |
@version = File.read(root + "/VERSION").chomp # or fail if not found
|
||
end
|
||
@major, @minor, @build = @version.scan(/\d+/)
|
||
@tag = @version.include?('-') ? @version.split('-').last : "" rescue ""
|
||
@short = "#{@major}.#{@minor}"
|
||
|
||
if @version =~ /\A(.*)-([^-]+)\z/
|
||
@notag = $1
|
||
@tag = $2
|
||
else
|
||
@notag = @version
|
||
@tag = ""
|
||
end
|
||
end
|
||
|
||
def to_s
|
app/services/menu/divider.rb | ||
---|---|---|
module Menu
|
||
class Divider < Node
|
||
def initialize(name, options={})
|
||
@caption = options[:caption]
|
||
super name
|
||
end
|
||
|
||
def authorized?
|
||
true
|
||
end
|
||
end
|
||
end
|
app/services/menu/item.rb | ||
---|---|---|
module Menu
|
||
class Item < Node
|
||
include Rails.application.routes.url_helpers
|
||
attr_reader :name, :condition, :parent, :child_menus, :last, :html_options
|
||
|
||
def initialize(name, options)
|
||
raise ArgumentError, "Invalid option :if for menu item '#{name}'" if options[:if] && !options[:if].respond_to?(:call)
|
||
raise ArgumentError, "Invalid option :html for menu item '#{name}'" if options[:html] && !options[:html].is_a?(Hash)
|
||
raise ArgumentError, "Cannot set the :parent to be the same as this item" if options[:parent] == name.to_sym
|
||
raise ArgumentError, "Invalid option :children for menu item '#{name}'" if options[:children] && !options[:children].respond_to?(:call)
|
||
@name = name
|
||
@url_hash = options[:url_hash]
|
||
@condition = options[:if]
|
||
@caption = options[:caption]
|
||
@html_options = options[:html] || {}
|
||
@parent = options[:parent]
|
||
@child_menus = options[:children]
|
||
@last = options[:last] || false
|
||
super @name.to_sym
|
||
end
|
||
|
||
def url_hash
|
||
@url_hash ||= send("hash_for_#{name}_path")
|
||
@url_hash.inject({}) do |h,(key,value)|
|
||
h[key] = (value.respond_to?(:call) ? value.call : value)
|
||
h
|
||
end
|
||
end
|
||
|
||
def authorized?
|
||
User.current.allowed_to?({
|
||
:controller => url_hash[:controller].to_s.gsub(/::/, "_").underscore,
|
||
:action => url_hash[:action]
|
||
})
|
||
rescue false
|
||
end
|
||
|
||
end
|
||
end
|
app/services/menu/loader.rb | ||
---|---|---|
module Menu
|
||
class Loader
|
||
def self.load
|
||
Manager.map :user_menu do |menu|
|
||
menu.item :logout, :caption => N_('Sign out'),
|
||
:url_hash => {:controller => 'users', :action => 'logout'}
|
||
menu.item :my_account, :caption => N_('My account'),
|
||
:url_hash => {:controller => 'users', :action => 'edit', :id => Proc.new { User.current }}
|
||
end
|
||
|
||
Manager.map :admin_menu do |menu|
|
||
menu.sub_menu :administer_menu, :caption => N_('Administer') do
|
||
menu.item :locations, :caption => N_('Locations') if SETTINGS[:locations_enabled]
|
||
menu.item :organizations, :caption => N_('Organizations') if SETTINGS[:organizations_enabled]
|
||
menu.divider
|
||
if SETTINGS[:login]
|
||
menu.item :auth_source_ldaps,:caption => N_('LDAP authentication')
|
||
menu.item :users, :caption => N_('Users')
|
||
menu.item :usergroups, :caption => N_('User groups')
|
||
menu.item :roles, :caption => N_('Roles')
|
||
end
|
||
menu.divider
|
||
menu.item :bookmarks, :caption => N_('Bookmarks')
|
||
menu.item :settings, :caption => N_('Settings')
|
||
menu.item :about_index, :caption => N_('About')
|
||
end
|
||
end
|
||
|
||
Manager.map :top_menu do |menu|
|
||
menu.sub_menu :monitor_menu, :caption => N_('Monitor') do
|
||
menu.item :dashboard, :caption => N_('Dashboard')
|
||
menu.item :reports, :caption => N_('Reports'),
|
||
:url_hash => {:controller => 'reports', :action => 'index', :search => 'eventful = true'}
|
||
menu.item :fact_values, :caption => N_('Facts')
|
||
menu.item :statistics, :caption => N_('Statistics')
|
||
menu.item :trends, :caption => N_('Trends')
|
||
menu.item :audits, :caption => N_('Audits')
|
||
end
|
||
|
||
menu.sub_menu :hosts_menu, :caption => N_('Hosts') do
|
||
menu.item :hosts, :caption => N_('All hosts')
|
||
if SETTINGS[:unattended]
|
||
menu.divider :caption => N_('Provisioning Setup')
|
||
menu.item :operatingsystems,:caption => N_('Operating systems')
|
||
menu.item :config_templates,:caption => N_('Provisioning templates')
|
||
menu.item :ptables, :caption => N_('Partition tables')
|
||
menu.item :media, :caption => N_('Installation media')
|
||
menu.item :models, :caption => N_('Hardware models')
|
||
menu.item :architectures, :caption => N_('Architectures')
|
||
end
|
||
end
|
||
|
||
menu.sub_menu :configure_menu, :caption => N_('Configure') do
|
||
menu.item :hostgroups, :caption => N_('Host groups')
|
||
menu.item :common_parameters, :caption => N_('Global parameters')
|
||
menu.divider :caption => N_('Puppet')
|
||
menu.item :environments, :caption => N_('Environments')
|
||
menu.item :puppetclasses, :caption => N_('Puppet classes')
|
||
menu.item :lookup_keys, :caption => N_('Smart variables')
|
||
|
||
end
|
||
|
||
menu.sub_menu :infrastructure_menu, :caption => N_('Infrastructure') do
|
||
menu.item :smart_proxies, :caption => N_('Smart proxies')
|
||
if SETTINGS[:unattended]
|
||
menu.item :compute_resources, :caption => N_('Compute resources')
|
||
menu.item :subnets, :caption => N_('Subnets')
|
||
menu.item :domains, :caption => N_('Domains')
|
||
end
|
||
end
|
||
|
||
end
|
||
end
|
||
end
|
||
end
|
app/services/menu/manager.rb | ||
---|---|---|
# Redmine - project management software
|
||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||
#
|
||
# This program is free software; you can redistribute it and/or
|
||
# modify it under the terms of the GNU General Public License
|
||
# as published by the Free Software Foundation; either version 2
|
||
# of the License, or (at your option) any later version.
|
||
#
|
||
# This program is distributed in the hope that it will be useful,
|
||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
# GNU General Public License for more details.
|
||
#
|
||
# You should have received a copy of the GNU General Public License
|
||
# along with this program; if not, write to the Free Software
|
||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||
module Menu
|
||
module Manager
|
||
|
||
class << self
|
||
def map(menu_name)
|
||
@items ||= {}
|
||
mapper = Mapper.new(menu_name.to_sym, @items)
|
||
if block_given?
|
||
yield mapper
|
||
else
|
||
mapper
|
||
end
|
||
end
|
||
|
||
def items(menu_name)
|
||
# force menu reload in development when auto loading modified files
|
||
@items || Menu::Loader.load
|
||
@items[menu_name.to_sym] || Node.new(:root)
|
||
end
|
||
end
|
||
|
||
class Mapper
|
||
attr_reader :menu, :menu_items
|
||
|
||
def initialize(menu, items)
|
||
items[menu] ||= Node.new(:root)
|
||
@menu = menu
|
||
@menu_items = items[menu]
|
||
end
|
||
|
||
# Adds an item at the end of the menu. Available options:
|
||
# * param: the parameter name that is used for the project id (default is :id)
|
||
# * if: a Proc that is called before rendering the item, the item is displayed only if it returns true
|
||
# * caption that can be:
|
||
# * a localized string Symbol
|
||
# * a String
|
||
# * a Proc that can take the project as argument
|
||
# * before, after: specify where the menu item should be inserted (eg. :after => :activity)
|
||
# * parent: menu item will be added as a child of another named menu (eg. :parent => :issues)
|
||
# * children: a Proc that is called before rendering the item. The Proc should return an array of MenuItems, which will be added as children to this item.
|
||
# eg. :children => Proc.new {|project| [Foreman::Manager::MenuItem.new(...)] }
|
||
# * last: menu item will stay at the end (eg. :last => true)
|
||
# * html_options: a hash of html options that are passed to link_to
|
||
def push(obj, options={})
|
||
parent = options[:parent] || @parent
|
||
|
||
target_root = (parent && subtree = self.find(parent)) ? subtree : @menu_items.root
|
||
|
||
# menu item position
|
||
if options[:first]
|
||
target_root.prepend(obj)
|
||
elsif (before = options[:before]) && exists?(before)
|
||
target_root.add_at(obj, position_of(before))
|
||
elsif (after = options[:after]) && exists?(after)
|
||
target_root.add_at(obj, position_of(after) + 1)
|
||
elsif options[:last]
|
||
target_root.add_last(obj)
|
||
else
|
||
target_root.add(obj)
|
||
end
|
||
end
|
||
|
||
def item(name, options={})
|
||
push(Item.new(name, options), options)
|
||
end
|
||
|
||
def sub_menu name, options={}, &block
|
||
push(Toggle.new(name, options[:caption]), options)
|
||
current = @parent
|
||
@parent = name
|
||
self.instance_eval(&block) if block_given?
|
||
@parent = current
|
||
end
|
||
|
||
def divider options={}
|
||
push(Divider.new(:divider, options), options)
|
||
end
|
||
|
||
# Removes a menu item
|
||
def delete(name)
|
||
if found = self.find(name)
|
||
@menu_items.remove!(found)
|
||
end
|
||
end
|
||
|
||
# Checks if a menu item exists
|
||
def exists?(name)
|
||
@menu_items.any? {|node| node.name == name}
|
||
end
|
||
|
||
def find(name)
|
||
@menu_items.find {|node| node.name == name}
|
||
end
|
||
|
||
def position_of(name)
|
||
@menu_items.each do |node|
|
||
if node.name == name
|
||
return node.position
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end
|
app/services/menu/node.rb | ||
---|---|---|
module Menu
|
||
|
||
class Node
|
||
include Enumerable
|
||
attr_accessor :parent
|
||
attr_reader :name
|
||
|
||
def initialize(name, children = [])
|
||
@name = name
|
||
@children = children
|
||
@last_items_count = children.size
|
||
end
|
||
|
||
def caption
|
||
case @caption
|
||
when String
|
||
@caption
|
||
when Proc
|
||
@caption.call().to_s
|
||
when Symbol
|
||
@caption.to_s.humanize
|
||
else
|
||
@name.to_s.humanize unless @name == :divider
|
||
end
|
||
end
|
||
|
||
def authorized_children
|
||
children.map{|sub_item| sub_item if sub_item.authorized?}.compact
|
||
end
|
||
|
||
def children
|
||
if block_given?
|
||
@children.each {|child| yield child}
|
||
else
|
||
@children
|
||
end
|
||
end
|
||
|
||
# Returns the number of descendants + 1
|
||
def size
|
||
@children.inject(1) {|sum, node| sum + node.size}
|
||
end
|
||
|
||
def each &block
|
||
yield self
|
||
children { |child| child.each(&block) }
|
||
end
|
||
|
||
# Adds a child at first position
|
||
def prepend(child)
|
||
add_at(child, 0)
|
||
end
|
||
|
||
# Adds a child at given position
|
||
def add_at(child, position)
|
||
if child.is_a?(Menu::Item) && find {|node| node.name == child.name}
|
||
Rails.logger.error "Child already exists #{child.name}"
|
||
return
|
||
end
|
||
|
||
@children = @children.insert(position, child)
|
||
child.parent = self
|
||
child
|
||
end
|
||
|
||
# Adds a child as last child
|
||
def add_last(child)
|
||
add_at(child, -1)
|
||
@last_items_count += 1
|
||
child
|
||
end
|
||
|
||
# Adds a child
|
||
def add(child)
|
||
position = @children.size - @last_items_count
|
||
add_at(child, position)
|
||
end
|
||
alias :<< :add
|
||
|
||
# Removes a child
|
||
def remove!(child)
|
||
@children.delete(child)
|
||
@last_items_count -= +1 if child && child.last
|
||
child.parent = nil
|
||
child
|
||
end
|
||
|
||
# Returns the position for this node in it's parent
|
||
def position
|
||
self.parent.children.index(self)
|
||
end
|
||
|
||
# Returns the root for this node
|
||
def root
|
||
root = self
|
||
root = root.parent while root.parent
|
||
root
|
||
end
|
||
end
|
||
end
|
app/services/menu/toggle.rb | ||
---|---|---|
module Menu
|
||
class Toggle < Node
|
||
def initialize(name, caption)
|
||
@caption = caption
|
||
super name.to_sym
|
||
end
|
||
|
||
def authorized?
|
||
true
|
||
end
|
||
end
|
||
end
|
app/views/about/index.html.erb | ||
---|---|---|
<div class="stats-well">
|
||
<h4><%=_("System Status")%></h4>
|
||
<ul class="nav nav-tabs" data-tabs="tabs">
|
||
<li class="active"><a href="#available_providers" data-toggle="tab"><%= _('Available Providers') %></a></li>
|
||
<% if @proxies.any? %>
|
||
<li><a href="#smart_proxies" data-toggle="tab"><%= _('Smart Proxies') %></a></li>
|
||
<% end %>
|
||
<% if @compute_resources.any? %>
|
||
<li class="active"><a href="#smart_proxies" data-toggle="tab"><%= _('Smart Proxies') %></a></li>
|
||
<% if SETTINGS[:unattended] %>
|
||
<li><a href="#available_providers" data-toggle="tab"><%= _('Available Providers') %></a></li>
|
||
<li><a href="#compute_resources" data-toggle="tab"><%= _('Compute Resources') %></a></li>
|
||
<% end %>
|
||
<% end %>
|
||
<li><a href="#plugins" data-toggle="tab"><%= _('Plugins') %></a></li>
|
||
</ul>
|
||
<div class="tab-content">
|
||
<div class="tab-pane active" id="available_providers">
|
||
<table class="table table-striped">
|
||
<tr>
|
||
<th><%= _("Provider") %></th>
|
||
<th><%= _("Status") %></th>
|
||
</tr>
|
||
<% ComputeResource::SUPPORTED_PROVIDERS.each do |provider| %>
|
||
<tr>
|
||
<td><%= provider %></td>
|
||
<% if ComputeResource::PROVIDERS.include?(provider) %>
|
||
<td><div class="badge badge-success"><%= _('Installed') %></div></td>
|
||
<% else %>
|
||
<td><div class="badge badge-inverse"><%= _('Not Installed') %></div></td>
|
||
<% end %>
|
||
</tr>
|
||
<% end %>
|
||
</table>
|
||
<%= _('To enable a provider, either install the OS package (e.g. foreman-libvirt) or enable the bundler group for development setup (e.g. ovirt).') %>
|
||
</div>
|
||
<% if @proxies.any? %>
|
||
<div class="tab-pane" id="smart_proxies">
|
||
<div class="tab-pane active" id="smart_proxies">
|
||
<% if @proxies.empty? %>
|
||
<p class="ca"><%= _("No smart proxies to show") %></p>
|
||
<% else %>
|
||
<% else %>
|
||
<table class="table table-striped">
|
||
<tr>
|
||
<th><%= _("Name") %></th>
|
||
<th><%= _("Features") %></th>
|
||
<th><%= _("Status") %></th>
|
||
</tr>
|
||
<% @proxies.each do |proxy| %>
|
||
<tr>
|
||
<td><%= link_to_if_authorized proxy.name, hash_for_edit_smart_proxy_path(:id => proxy.id) %></td>
|
||
<td><%=h proxy.features.to_sentence %></td>
|
||
<td><div class="proxy-status" data-url=<%= ping_smart_proxy_path(proxy) %>><%= _("Connecting..") %></div></td>
|
||
</tr>
|
||
<th><%= _("Name") %></th>
|
||
<th><%= _("Features") %></th>
|
||
<th><%= _("Status") %></th>
|
||
</tr>
|
||
<% @proxies.each do |proxy| %>
|
||
<tr>
|
||
<td><%= link_to_if_authorized proxy.name, hash_for_edit_smart_proxy_path(:id => proxy.id) %></td>
|
||
<td><%=h proxy.features.to_sentence %></td>
|
||
<td><div class="proxy-status" data-url=<%= ping_smart_proxy_path(proxy) %>><%= _("Connecting..") %></div></td>
|
||
</tr>
|
||
<% end %>
|
||
</table>
|
||
<% end %>
|
||
</table>
|
||
<% end %>
|
||
</div>
|
||
<% end %>
|
||
<% if @compute_resources.any? %>
|
||
<% if SETTINGS[:unattended] %>
|
||
<div class="tab-pane" id="available_providers">
|
||
<table class="table table-striped">
|
||
<tr>
|
||
<th><%= _("Provider") %></th>
|
||
<th><%= _("Status") %></th>
|
||
</tr>
|
||
<% ComputeResource::SUPPORTED_PROVIDERS.each do |provider| %>
|
||
<tr>
|
||
<td><%= provider %></td>
|
||
<% if ComputeResource::PROVIDERS.include?(provider) %>
|
||
<td><div class="badge badge-success"><%= _('Installed') %></div></td>
|
||
<% else %>
|
||
<td><div class="badge badge-inverse"><%= _('Not Installed') %></div></td>
|
||
<% end %>
|
||
</tr>
|
||
<% end %>
|
||
</table>
|
||
<%= _('To enable a provider, either install the OS package (e.g. foreman-libvirt) or enable the bundler group for development setup (e.g. ovirt).') %>
|
||
</div>
|
||
<div class="tab-pane" id="compute_resources">
|
||
<% if @compute_resources.empty? %>
|
||
<p class="ca"><%= _("No compute resource to show") %></p>
|
||
<% else %>
|
||
<% if @compute_resources.empty? %>
|
||
<p class="ca"><%= _("No compute resource to show") %></p>
|
||
<% else %>
|
||
<table class="table table-striped">
|
||
<tr>
|
||
<th><%= _("Name") %></th>
|
||
<th><%= _("Type") %></th>
|
||
<th><%= _("Status") %></th>
|
||
</tr>
|
||
<% @compute_resources.each do |compute| %>
|
||
<tr>
|
||
<td><%= link_to compute.name, compute %></td>
|
||
<td><%= compute.provider_friendly_name %></td>
|
||
<td><div class="compute-status" data-url=<%= ping_compute_resource_path(compute) %>><%= _("Connecting..") %></div></td>
|
||
</tr>
|
||
<% end %>
|
||
</table>
|
||
<% end %>
|
||
</div>
|
||
<% end %>
|
||
<div class="tab-pane" id="plugins">
|
||
<% if @plugins.empty? %>
|
||
<p class="ca"><%= _("No plugins found") %></p>
|
||
<% else %>
|
||
<table class="table table-striped">
|
||
<tr>
|
||
<th><%= _("Name") %></th>
|
||
<th><%= _("Type") %></th>
|
||
<th><%= _("Status") %></th>
|
||
</tr>
|
||
<% @compute_resources.each do |compute| %>
|
||
<tr>
|
||
<td><%= link_to compute.name, compute %></td>
|
||
<td><%= compute.provider_friendly_name %></td>
|
||
<td><div class="compute-status" data-url=<%= ping_compute_resource_path(compute) %>><%= _("Connecting..") %></div></td>
|
||
</tr>
|
||
<th><%= _("Name") %></th>
|
||
<th><%= _("Description") %></th>
|
||
<th><%= _("Author") %></th>
|
||
<th><%= _("Version") %></th>
|
||
</tr>
|
||
<% @plugins.each do |plugin| %>
|
||
<tr>
|
||
<td><%= plugin.url.blank? ? plugin.name : link_to(plugin.name, plugin.url, :rel=>'external')%></td>
|
||
<td><%= _(plugin.description) %></td>
|
||
<td><%= plugin.author_url.blank? ? plugin.author : link_to(plugin.author, plugin.author_url)%></td>
|
||
<td><%= plugin.version %></td>
|
||
</tr>
|
||
<% end %>
|
||
</table>
|
||
<% end %>
|
||
</table>
|
||
<% end %>
|
||
</div>
|
||
<% end %>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="span5">
|
||
<div class="stats-well">
|
||
<h4><%= _("Support") %></h4>
|
app/views/api/v2/plugins/index.json.rabl | ||
---|---|---|
collection @plugins
|
||
|
||
attributes :id, :name, :author, :description, :url, :version
|
app/views/home/_org_switcher.html.erb | ||
---|---|---|
<% if SETTINGS[:locations_enabled] || SETTINGS[:organizations_enabled] %>
|
||
<li class="dropdown org-switcher" >
|
||
<li class="dropdown org-switcher menu_tab_dropdown" >
|
||
<a href="#" class ="dropdown-toggle" data-toggle="dropdown" ><%= org_switcher_title %><span class="caret"></span></a>
|
||
|
||
<ul class="dropdown-menu">
|
app/views/home/_settings.html.erb | ||
---|---|---|
<li class="dropdown menu_tab_settings">
|
||
<% choices = setting_options %>
|
||
<%= link_to (_("More") + content_tag(:span,'', :class=>"caret")).html_safe, "#", :class => "dropdown-toggle", :'data-toggle'=>"dropdown" unless choices.empty?%>
|
||
<ul class="dropdown-menu">
|
||
<% choices.each do |item|%>
|
||
<% if item[0] == :divider %>
|
||
<%= content_tag(:li, "", :class=>"divider") %>
|
||
<% elsif item[0] == :group %>
|
||
<%= content_tag :li, :class=>"dropdown-submenu" do %>
|
||
<%= link_to(item[1],"#",:class=>"dropdown-toggle", :"data-toggle"=>"dropdown") %>
|
||
<%= content_tag :ul, :class=>"dropdown-menu" do%>
|
||
<% item[2].each do |sub_item|%>
|
||
<%= content_tag(:li, link_to(sub_item[0], {:controller => "/#{sub_item[1]}", :action => :index})) %>
|
||
<% end %>
|
||
<% end %>
|
||
<% end %>
|
||
<% else %>
|
||
<%= content_tag(:li, link_to(item[0], {:controller => "/#{item[1]}", :action => :index})) %>
|
||
<% end %>
|
||
<% end %>
|
||
</ul>
|
||
</li>
|
app/views/home/_submenu.html.erb | ||
---|---|---|
<li class="dropdown menu_tab_dropdown">
|
||
<%= link_to (menu_title + content_tag(:span, '', :class => "caret")).html_safe, "#", :class => "dropdown-toggle", :'data-toggle' => "dropdown" %>
|
||
<ul class="dropdown-menu">
|
||
<% authorized_menu_actions(menu_items).each do |item| %>
|
||
<% case item %>
|
||
<% when Menu::Item %>
|
||
<%= menu_item_tag item %>
|
||
<% when Menu::Divider %>
|
||
<%= content_tag(:li, "", :class => "divider") %>
|
||
<%= content_tag(:li, _(item.caption), :class => "nav-header") if item.caption %>
|
||
<% when Menu::Toggle %>
|
||
<%= content_tag :li, :class => "dropdown-submenu" do %>
|
||
<%= link_to(_(item.caption), "#", :class => "dropdown-toggle", :"data-toggle" => "dropdown") %>
|
||
<%= content_tag :ul, :class => "dropdown-menu" do %>
|
||
<% authorized_menu_actions(item.children).each do |sub_item| %>
|
||
<%= menu_item_tag sub_item %>
|
||
<% end %>
|
||
<% end %>
|
||
<% end %>
|
||
<% end %>
|
||
<% end %>
|
||
</ul>
|
||
</li>
|
app/views/home/_topbar.html.erb | ||
---|---|---|
<span class="icon-cog icon-white"></span>
|
||
</a>
|
||
<!-- menu -->
|
||
<div id='current_tab' data-controller='<%=controller_name.gsub(/_.*/,"s")%>' data-settings='<%= class_for_setting_page %>'> </div>
|
||
<%= content_tag :div,nil, :id=>'current_tab', :data=>{:controller=>controller_name, :action=>action_name} %>
|
||
|
||
<% if User.current %>
|
||
<% cache(TopbarSweeper.fragment_name) do %>
|
||
<div class="nav-collapse collapse nav1">
|
||
<ul class="nav" id="menu">
|
||
<%= render "home/org_switcher" %>
|
||
<%= menu 'dashboard', _('Dashboard') %>
|
||
<%= menu 'hosts', _('Hosts') %>
|
||
<%= menu 'reports', _('Reports'), hash_for_reports_path.merge(:search => 'eventful = true') %>
|
||
<%= menu 'facts' , _('Facts'), hash_for_fact_values_path %>
|
||
<%= menu 'audits', _('Audits'), hash_for_audits_path %>
|
||
<%= menu 'statistics', _('Statistics') %>
|
||
<%= menu 'trends', _('Trends'), hash_for_trends_path %>
|
||
</ul>
|
||
</div>
|
||
<div class="nav-collapse collapse nav2">
|
||
<ul class="nav pull-right" id="menu2">
|
||
<%= render "home/settings" %>
|
||
</ul>
|
||
</div>
|
||
<%= render "home/org_switcher" %>
|
||
<%= render_menu :top_menu %>
|
||
</ul>
|
||
</div>
|
||
<div class="nav-collapse collapse nav2">
|
||
<ul class="nav pull-right" id="menu2">
|
||
<%= render_menu :admin_menu %>
|
||
</ul>
|
||
</div>
|
||
<% end %>
|
||
<% end %>
|
app/views/home/_user_dropdown.html.erb | ||
---|---|---|
<ul class="nav pull-right ">
|
||
<li class="dropdown">
|
||
<li class="dropdown menu_tab_dropdown">
|
||
<%= user_header %>
|
||
<ul class="dropdown-menu pull-right">
|
||
<li><%= link_to(_("Sign Out"), logout_users_path) %></li>
|
||
<li><%= link_to(_("My account"), edit_user_path(User.current) )%></li>
|
||
<% authorized_menu_actions(Menu::Manager.items(:user_menu).children).map do |item| %>
|
||
<%= menu_item_tag item %>
|
||
<% end %>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
config/initializers/foreman.rb | ||
---|---|---|
require 'foreman/access_permissions'
|
||
require 'foreman/default_data/loader'
|
||
require 'menu/loader'
|
||
require 'foreman/renderer'
|
||
require 'foreman/controller'
|
||
require 'net'
|
||
... | ... | |
# We load the default settings for the roles if they are not already present
|
||
Foreman::DefaultData::Loader.load(false)
|
||
|
||
#load topbar
|
||
Menu::Loader.load
|
||
|
||
# clear our users topbar cache
|
||
begin
|
||
User.unscoped.pluck(:id).each do |id|
|
config/routes/api/v2.rb | ||
---|---|---|
end
|
||
end
|
||
get 'orchestration/(:id)/tasks', :to => 'tasks#index'
|
||
|
||
resources :plugins, :only => [:index]
|
||
end
|
||
match '*other', :to => 'v2/home#route_error', :constraints => ApiConstraints.new(:version => 2)
|
||
end
|
lib/tasks/plugins.rake | ||
---|---|---|
desc "List Installed plugins"
|
||
task :plugins => :environment do
|
||
puts 'Collecting plugin information'
|
||
Foreman::Plugin.all.map{ |p| puts p.to_s }
|
||
end
|
script/foreman-debug | ||
---|---|---|
add_files /etc/sysconfig/named /etc/default/bind
|
||
add_files /etc/{sysconfig,default}/libvirt*
|
||
add_files /etc/sysconfig/pgsql
|
||
add_cmd "foreman-rake plugins" "plugin_list"
|
||
|
||
qprintf "\n\n"
|
||
qprintf "%10s %s\n" "HOSTNAME:" "$(hostname -f 2>/dev/null)"
|
test/functional/api/v2/plugins_controller_test.rb | ||
---|---|---|
require 'test_helper'
|
||
|
||
class Api::V2::PluginsControllerTest < ActionController::TestCase
|
||
|
||
test "should get plugins " do
|
||
get :index
|
||
plugins = assigns(:plugins)
|
||
assert_response :success
|
||
end
|
||
|
||
end
|
test/integration/top_bar_test.rb | ||
---|---|---|
end
|
||
within("div.navbar-inner") do
|
||
assert page.has_link?("Dashboard", :href => "/dashboard")
|
||
assert page.has_link?("Hosts", :href => "/hosts")
|
||
assert page.has_link?("All hosts", :href => "/hosts")
|
||
assert page.has_link?("Reports", :href => "/reports?search=eventful+%3D+true")
|
||
assert page.has_link?("Facts", :href => "/fact_values")
|
||
assert page.has_link?("Audits", :href => "/audits")
|
||
... | ... | |
test "Hosts link" do
|
||
visit root_path
|
||
within("div.navbar-inner") do
|
||
click_link("Hosts")
|
||
click_link("All hosts")
|
||
end
|
||
assert page.has_selector?('h1', :text => "Hosts")
|
||
end
|
test/unit/menu_item_test.rb | ||
---|---|---|
# Redmine - project management software
|
||
# Copyright (C) 2006-2009 Jean-Philippe Lang
|
||
#
|
||
# This program is free software; you can redistribute it and/or
|
||
# modify it under the terms of the GNU General Public License
|
||
# as published by the Free Software Foundation; either version 2
|
||
# of the License, or (at your option) any later version.
|
||
#
|
||
# This program is distributed in the hope that it will be useful,
|
||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
# GNU General Public License for more details.
|
||
#
|
||
# You should have received a copy of the GNU General Public License
|
||
# along with this program; if not, write to the Free Software
|
||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||
|
||
require 'test_helper'
|
||
|
||
module MenuItemTestHelper
|
||
# Helpers
|
||
def get_menu_item(menu_name, item_name)
|
||
Menu::Manager.items(menu_name).find {|item| item.name == item_name.to_sym}
|
||
end
|
||
end
|
||
|
||
class MenuItemTest < ActiveSupport::TestCase
|
||
include MenuItemTestHelper
|
||
|
||
Menu::Manager.map :test_menu do |menu|
|
||
menu.item(:parent)
|
||
menu.item(:child_menu, :parent => :parent)
|
||
menu.item(:child2_menu, :parent => :parent)
|
||
end
|
||
|
||
context "MenuItem#caption" do
|
||
should "be tested"
|
||
end
|
||
|
||
context "MenuItem#html_options" do
|
||
should "be tested"
|
||
end
|
||
|
||
def test_new_menu_item_with_all_required_parameters
|
||
assert Menu::Item.new(:test_good_menu, :url_hash => {:controller=>'test', :action=>'index'}, :after => :me)
|
||
end
|
||
|
||
def test_new_menu_item_should_require_a_proc_to_use_for_the_if_condition
|
||
assert_raises ArgumentError do
|
||
Menu::Item.new(:test_error, :if => ['not_a_proc'] )
|
||
end
|
||
|
||
assert Menu::Item.new(:test_good_if, :if => Proc.new{})
|
||
end
|
||
|
||
def test_new_menu_item_should_allow_a_hash_for_extra_html_options
|
||
assert_raises ArgumentError do
|
||
Menu::Item.new(:test_error, :html => ['not_a_hash'])
|
||
end
|
||
|
||
assert Menu::Item.new(:test_good_html, :html => { :onclick => 'doSomething' })
|
||
end
|
||
|
||
def test_new_menu_item_should_require_a_proc_to_use_the_children_option
|
||
assert_raises ArgumentError do
|
||
Menu::Item.new(:test_error, :children => ['not_a_proc'])
|
||
end
|
||
|
||
assert Menu::Item.new(:test_good_children, :children => Proc.new{} )
|
||
end
|
||
|
||
def test_new_should_not_allow_setting_the_parent_item_to_the_current_item
|
||
assert_raises ArgumentError do
|
||
Menu::Item.new(:test_error, :parent => :test_error )
|
||
end
|
||
end
|
||
|
||
def test_has_children
|
||
parent_item = get_menu_item(:test_menu, :parent)
|
||
assert parent_item.children.present?
|
||
assert_equal 2, parent_item.children.size
|
||
assert_equal get_menu_item(:test_menu, :child_menu), parent_item.children[0]
|
||
assert_equal get_menu_item(:test_menu, :child2_menu), parent_item.children[1]
|
||
end
|
||
end
|
test/unit/menu_manager_test.rb | ||
---|---|---|
# Redmine - project management software
|
||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||
#
|
||
# This program is free software; you can redistribute it and/or
|
||
# modify it under the terms of the GNU General Public License
|
||
# as published by the Free Software Foundation; either version 2
|
||
# of the License, or (at your option) any later version.
|
||
#
|
||
# This program is distributed in the hope that it will be useful,
|
||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
# GNU General Public License for more details.
|
||
#
|
||
# You should have received a copy of the GNU General Public License
|
||
# along with this program; if not, write to the Free Software
|
||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||
|
||
require 'test_helper'
|
||
|
||
class MenuManagerTest < ActiveSupport::TestCase
|
||
def test_map_should_yield_a_mapper
|
||
assert_difference 'Menu::Manager.items(:test_menu).size' do
|
||
Menu::Manager.map :test_menu do |mapper|
|
||
assert_kind_of Menu::Manager::Mapper, mapper
|
||
mapper.item :new_item
|
||
end
|
||
end
|
||
end
|
||
|
||
def test_items_should_return_menu_items
|
||
items = Menu::Manager.items(:test_menu)
|
||
assert_kind_of Menu::Node, items.first
|
||
end
|
||
end
|
test/unit/menu_mapper_test.rb | ||
---|---|---|
# Redmine - project management software
|
||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||
#
|
||
# This program is free software; you can redistribute it and/or
|
||
# modify it under the terms of the GNU General Public License
|
||
# as published by the Free Software Foundation; either version 2
|
||
# of the License, or (at your option) any later version.
|
||
#
|
||
# This program is distributed in the hope that it will be useful,
|
||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
# GNU General Public License for more details.
|
||
#
|
||
# You should have received a copy of the GNU General Public License
|
||
# along with this program; if not, write to the Free Software
|
||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||
|
||
require 'test_helper'
|
||
|
||
class MenuMapperTest < ActiveSupport::TestCase
|
||
test "Mapper#initialize should define a root MenuNode if menu is not present in items" do
|
||
menu_mapper = Menu::Manager::Mapper.new(:test_menu, {})
|
||
node = menu_mapper.menu_items
|
||
assert_not_nil node
|
||
assert_equal :root, node.name
|
||
end
|
||
|
||
test "Mapper#initialize should use existing MenuNode if present" do
|
||
node = "foo" # just an arbitrary reference
|
||
menu_mapper = Menu::Manager::Mapper.new(:test_menu, {:test_menu => node})
|
||
assert_equal node, menu_mapper.menu_items
|
||
end
|
||
|
||
def test_push_onto_root
|
||
menu_mapper = Menu::Manager::Mapper.new(:test_menu, {})
|
||
menu_mapper.item :test_overview, :url_hash => { :controller => 'hosts', :action => 'show'}
|
||
|
||
menu_mapper.exists?(:test_overview)
|
||
end
|
||
|
||
def test_push_onto_parent
|
||
menu_mapper = Menu::Manager::Mapper.new(:test_menu, {})
|
||
menu_mapper.item :test_overview, :url_hash => { :controller => 'hosts', :action => 'show'}
|
||
menu_mapper.item :test_child, :url_hash => { :controller => 'hosts', :action => 'show'}, :parent => :test_overview
|
||
|
||
assert menu_mapper.exists?(:test_child)
|
||
assert_equal :test_child, menu_mapper.find(:test_child).name
|
||
end
|
||
|
||
def test_push_onto_grandparent
|
||
menu_mapper = Menu::Manager::Mapper.new(:test_menu, {})
|
||
menu_mapper.item :test_overview, :url_hash => { :controller => 'hosts', :action => 'show'}
|
||
menu_mapper.item :test_child, :url_hash => { :controller => 'hosts', :action => 'show'}, :parent => :test_overview
|
||
menu_mapper.item :test_grandchild, :url_hash => { :controller => 'hosts', :action => 'show'}, :parent => :test_child
|
||
|
||
assert menu_mapper.exists?(:test_grandchild)
|
||
grandchild = menu_mapper.find(:test_grandchild)
|
||
assert_equal :test_grandchild, grandchild.name
|
||
assert_equal :test_child, grandchild.parent.name
|
||
end
|
||
|
||
def test_push_first
|
||
menu_mapper = Menu::Manager::Mapper.new(:test_menu, {})
|
||
menu_mapper.item :test_second, :url_hash => { :controller => 'hosts', :action => 'show'}
|
||
menu_mapper.item :test_third, :url_hash => { :controller => 'hosts', :action => 'show'}
|
||
menu_mapper.item :test_fourth, :url_hash => { :controller => 'hosts', :action => 'show'}
|
||
menu_mapper.item :test_fifth, :url_hash => { :controller => 'hosts', :action => 'show'}
|
||
menu_mapper.item :test_first, :url_hash => { :controller => 'hosts', :action => 'show'}, :first => true
|
||
|
||
root = menu_mapper.find(:root)
|
||
assert_equal 5, root.children.size
|
||
{0 => :test_first, 1 => :test_second, 2 => :test_third, 3 => :test_fourth, 4 => :test_fifth}.each do |position, name|
|
||
assert_not_nil root.children[position]
|
||
assert_equal name, root.children[position].name
|
||
end
|
||
|
||
end
|
||
|
||
def test_push_before
|
||
menu_mapper = Menu::Manager::Mapper.new(:test_menu, {})
|
||
menu_mapper.item :test_first, :url_hash => { :controller => 'hosts', :action => 'show'}
|
||
menu_mapper.item :test_second, :url_hash => { :controller => 'hosts', :action => 'show'}
|
||
menu_mapper.item :test_fourth, :url_hash => { :controller => 'hosts', :action => 'show'}
|
||
menu_mapper.item :test_fifth, :url_hash => { :controller => 'hosts', :action => 'show'}
|
||
menu_mapper.item :test_third, :url_hash => { :controller => 'hosts', :action => 'show'}, :before => :test_fourth
|
||
|
||
root = menu_mapper.find(:root)
|
||
assert_equal 5, root.children.size
|
||
{0 => :test_first, 1 => :test_second, 2 => :test_third, 3 => :test_fourth, 4 => :test_fifth}.each do |position, name|
|
||
assert_not_nil root.children[position]
|
||
assert_equal name, root.children[position].name
|
||
end
|
||
|
||
end
|
||
|
||
def test_push_after
|
||
menu_mapper = Menu::Manager::Mapper.new(:test_menu, {})
|
||
menu_mapper.item :test_first, :url_hash => { :controller => 'hosts', :action => 'show'}
|
||
menu_mapper.item :test_second, :url_hash => { :controller => 'hosts', :action => 'show'}
|
||
menu_mapper.item :test_third, :url_hash => { :controller => 'hosts', :action => 'show'}
|
||
menu_mapper.item :test_fifth, :url_hash => { :controller => 'hosts', :action => 'show'}
|
||
menu_mapper.item :test_fourth, :url_hash => { :controller => 'hosts', :action => 'show'}, :after => :test_third
|
||
|
||
root = menu_mapper.find(:root)
|
||
assert_equal 5, root.children.size
|
||
{0 => :test_first, 1 => :test_second, 2 => :test_third, 3 => :test_fourth, 4 => :test_fifth}.each do |position, name|
|
||
assert_not_nil root.children[position]
|
||
assert_equal name, root.children[position].name
|
||
end
|
||
|
||
end
|
||
|
||
def test_push_last
|
||
menu_mapper = Menu::Manager::Mapper.new(:test_menu, {})
|
Also available in: Unified diff
fixes #3510 - plugin interface for registering a plugin, updated menu system