diff --git a/app/controllers/rate_caches_controller.rb b/app/controllers/rate_caches_controller.rb
new file mode 100644
index 0000000..316c991
--- /dev/null
+++ b/app/controllers/rate_caches_controller.rb
@@ -0,0 +1,10 @@
+class RateCachesController < ApplicationController
+ unloadable
+
+ layout 'admin'
+
+ before_filter :require_admin
+
+ def index
+ end
+end
diff --git a/app/views/rate_caches/index.html.erb b/app/views/rate_caches/index.html.erb
new file mode 100644
index 0000000..564eb6c
--- /dev/null
+++ b/app/views/rate_caches/index.html.erb
@@ -0,0 +1 @@
+
<%= l(:text_rate_caches_panel) %>
diff --git a/assets/images/database_refresh.png b/assets/images/database_refresh.png
new file mode 100644
index 0000000..ff803be
Binary files /dev/null and b/assets/images/database_refresh.png differ
diff --git a/config/locales/en.yml b/config/locales/en.yml
index f8c9ed7..a529972 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -8,3 +8,5 @@ en:
rate_label_set_rate: Set Rate
rate_label_default: Default Rate
rate_cost: Cost
+ text_rate_caches_panel: "Rate Caches"
+
diff --git a/init.rb b/init.rb
index c18393b..6d9358b 100644
--- a/init.rb
+++ b/init.rb
@@ -36,6 +36,8 @@ Redmine::Plugin.register :redmine_rate do
})
permission :view_rate, { }
+
+ menu :admin_menu, :rate_caches, { :controller => 'rate_caches', :action => 'index'}, :caption => :text_rate_caches_panel
end
require 'redmine_rate/hooks/timesheet_hook_helper'
@@ -44,3 +46,4 @@ require 'redmine_rate/hooks/plugin_timesheet_views_timesheet_group_header_hook'
require 'redmine_rate/hooks/plugin_timesheet_views_timesheet_time_entry_hook'
require 'redmine_rate/hooks/plugin_timesheet_views_timesheet_time_entry_sum_hook'
require 'redmine_rate/hooks/plugin_timesheet_view_timesheets_report_header_tags_hook'
+require 'redmine_rate/hooks/view_layouts_base_html_head_hook'
diff --git a/lib/redmine_rate/hooks/view_layouts_base_html_head_hook.rb b/lib/redmine_rate/hooks/view_layouts_base_html_head_hook.rb
new file mode 100644
index 0000000..8361aec
--- /dev/null
+++ b/lib/redmine_rate/hooks/view_layouts_base_html_head_hook.rb
@@ -0,0 +1,9 @@
+module RedmineRate
+ module Hooks
+ class ViewLayoutsBaseHtmlHeadHook < Redmine::Hook::ViewListener
+ def view_layouts_base_html_head(context={})
+ return content_tag(:style, "#admin-menu a.rate-caches { background-image: url('#{image_path('database_refresh.png', :plugin => 'redmine_rate')}'); }", :type => 'text/css')
+ end
+ end
+ end
+end
diff --git a/test/integration/admin_panel_test.rb b/test/integration/admin_panel_test.rb
new file mode 100644
index 0000000..ea1c94f
--- /dev/null
+++ b/test/integration/admin_panel_test.rb
@@ -0,0 +1,26 @@
+require 'test_helper'
+
+class AdminPanelTest < ActionController::IntegrationTest
+ def setup
+ @user = User.generate!(:admin => true, :password => 'rates', :password_confirmation => 'rates')
+
+ login_as(@user.login, 'rates')
+ end
+
+ context "Rate Caches admin panel" do
+ should "be listed in the main Admin section" do
+ click_link "Administration"
+ assert_response :success
+
+ assert_select "#admin-menu" do
+ assert_select "a.rate-caches"
+ end
+
+ end
+
+ should "show the last run timestamp for the last caching run"
+ should "show the last run timestamp for the last cache clearing run"
+ should "have a button to force a caching run"
+ should "have a button to force a cache clearing run"
+ end
+end
diff --git a/test/test_helper.rb b/test/test_helper.rb
index bd1ed0c..9aa74bb 100644
--- a/test/test_helper.rb
+++ b/test/test_helper.rb
@@ -3,3 +3,41 @@ require File.expand_path(File.dirname(__FILE__) + '/../../../../test/test_helper
# Ensure that we are using the temporary fixture path
Engines::Testing.set_fixture_path
+
+require "webrat"
+
+Webrat.configure do |config|
+ config.mode = :rails
+end
+
+module IntegrationTestHelper
+ def login_as(user="existing", password="existing")
+ visit "/login"
+ fill_in 'Login', :with => user
+ fill_in 'Password', :with => password
+ click_button 'login'
+ assert_response :success
+ assert User.current.logged?
+ end
+
+ def logout
+ visit '/logout'
+ assert_response :success
+ assert !User.current.logged?
+ end
+
+ def assert_forbidden
+ assert_response :forbidden
+ assert_template 'common/403'
+ end
+
+ def assert_requires_login
+ assert_response :success
+ assert_template 'account/login'
+ end
+
+end
+
+class ActionController::IntegrationTest
+ include IntegrationTestHelper
+end