5 Commits
13 changed files with 107 additions and 156 deletions
+1 -1
View File
@@ -1 +1 @@
0.3.0 0.2.1
+4 -4
View File
@@ -52,11 +52,11 @@ module RateHelper
url_options[:user_id] ||= options[:user_id] url_options[:user_id] ||= options[:user_id]
##### #####
link_to(caption,
link_to_remote(caption, {:remote => true, :update => options[:update] || "content", :url => url_options, :method => options[:method] || :post},
{:update => options[:update] || "content", :url => url_options, :method => options[:method] || :post},
{:href => url_for(url_options), {:href => url_for(url_options),
:class => css}) :class => css})
# link_to caption, :remote => true
end end
private private
@@ -88,7 +88,7 @@ module RateHelper
##### #####
link_to_remote(caption, link_to_remote(caption,
{:update => options[:update] || "content", :url => url_options, :method => options[:method] || :post}, {:remote => true, :update => options[:update] || "content", :url => url_options, :method => options[:method] || :post},
{:href => url_for(url_options)}) + {:href => url_for(url_options)}) +
(icon ? nbsp(2) + image_tag(icon) : '') (icon ? nbsp(2) + image_tag(icon) : '')
end end
+1 -1
View File
@@ -18,7 +18,7 @@ class Rate < ActiveRecord::Base
before_destroy :unlocked? before_destroy :unlocked?
after_destroy :update_time_entry_cost_cache after_destroy :update_time_entry_cost_cache
named_scope :history_for_user, lambda { |user, order| scope :history_for_user, lambda { |user, order|
{ {
:conditions => { :user_id => user.id }, :conditions => { :user_id => user.id },
:order => order, :order => order,
@@ -0,0 +1,18 @@
%td{:align => "left", :id => "rate_#{project.id}_#{member.user.id}"}
- if rate.nil? || rate.default?
- if rate && rate.default?
%em #{number_to_currency(rate.amount)}
- if User.current.admin?
= form_tag form_url, :method => :post, :remote => true do
= text_field :rate, :amount, :size => 8
= hidden_field(:rate,:date_in_effect, :value => Date.today.to_s)
= hidden_field(:rate, :project_id, :value => project.id)
= hidden_field(:rate, :user_id, :value => member.user.id)
= hidden_field_tag("back_url", url_for(:controller => 'projects', :action => 'settings', :id => project, :tab => 'members'))
= submit_tag(l(:rate_label_set_rate), :class => "small")
- else
%strong
- if User.current.admin?
= link_to number_to_currency(rate.amount), :controller => 'users', :action => 'edit', :id => member.user, :tab => 'rates'
- else
= number_to_currency(rate.amount)
+1 -1
View File
@@ -1,4 +1,4 @@
<% form_for(@rate) do |f| %> <%= form_for(@rate) do |f| %>
<table class="list"> <table class="list">
<thead> <thead>
<th style="width:15%"><%= l(:label_date) %></th> <th style="width:15%"><%= l(:label_date) %></th>
+9 -13
View File
@@ -3,21 +3,17 @@
<% if rate.nil? || rate.default? %> <% if rate.nil? || rate.default? %>
<% if rate && rate.default? %> <% if rate && rate.default? %>
<em><%= number_to_currency(rate.amount) %></em> <em><%= number_to_currency(rate.amount) %></em>
<% end %> <% end %>
<%= form_for(:rate, :url => rates_path(:format => 'js'), :remote => true) do |f| %>
<% remote_form_for(:rate, :url => rates_path(:format => 'js')) do |f| %> <%= f.text_field :amount %>
<%= f.hidden_field :date_in_effect, :value => Date.today.to_s, :id => "" %>
<%= f.text_field :amount %> <%= f.hidden_field :project_id, :value => membership.project.id %>
<%= f.hidden_field :date_in_effect, :value => Date.today.to_s, :id => "" %> <%= f.hidden_field :user_id, :value => user.id %>
<%= f.hidden_field :project_id, :value => membership.project.id %> <%= hidden_field_tag "back_url", url_for(:controller => 'users', :action => 'edit', :id => user, :tab => 'memberships') %>
<%= f.hidden_field :user_id, :value => user.id %> <%= submit_tag(l(:rate_label_set_rate), :class => "small") %>
<%= hidden_field_tag "back_url", url_for(:controller => 'users', :action => 'edit', :id => user, :tab => 'memberships') %>
<%= submit_tag(l(:rate_label_set_rate), :class => "small") %>
<% end %> <% end %>
<% else %> <% else %>
<strong><%= link_to number_to_currency(rate.amount), { :action => 'edit', :id => user, :tab => 'rates'} %></strong> <strong><%= link_to number_to_currency(rate.amount), { :action => 'edit', :id => user, :tab => 'rates'} %></strong>
<% end %> <% end %>
</td> </td>
-3
View File
@@ -1,3 +0,0 @@
#admin-menu a.rate-caches {
background-image: url('../images/database_refresh.png');
}
+4 -11
View File
@@ -1,11 +1,4 @@
if Gem::Version.new("3.0") > Gem::Version.new(Rails.version) then resources :rates
ActionController::Routing::Routes.draw do |map|
map.resources :rates match 'rate_caches', :to => 'rate_caches#index', :via => "get"
map.connect "rate_caches", :conditions => { :method => :put }, :controller => "rate_caches", :action => "update" match 'rate_caches', :to => 'rate_caches#update', :via => "put"
end
else
RedmineApp::Application.routes.draw do
resources :rates
match :rate_caches, :to => "rate_caches#update", :method => :put
end
end
+15 -25
View File
@@ -1,33 +1,23 @@
require 'redmine' require 'redmine'
Rails.logger.info 'Starting Rate plugin for Redmine' # Patches to the Redmine core
ActionDispatch::Callbacks.to_prepare do
gem 'lockfile'
require_dependency 'application_controller' require_dependency 'application_controller'
require_dependency 'time_entry' ApplicationController.send(:include, RateHelper)
require_dependency 'users_helper' ApplicationController.send(:helper, :rate)
if Gem::Version.new("3.0") > Gem::Version.new(Rails.version) then require_dependency 'time_entry'
require 'dispatcher' TimeEntry.send(:include, RateTimeEntryPatch)
Distpatcher.to_prepare :redmine_rate do
gem 'lockfile' require_dependency 'users_helper'
ApplicationController.send(:include, RateHelper) UsersHelper.send(:include, RateUsersHelperPatch) unless UsersHelper.included_modules.include?(RateUsersHelperPatch)
ApplicationController.send(:helper, :rate)
TimeEntry.send(:include, RateTimeEntryPatch)
UsersHelper.send(:include, RateUsersHelperPatch) unless UsersHelper.included_modules.include?(RateUsersHelperPatch)
end
else
ActionDispatch::Callbacks.to_prepare do
gem 'lockfile'
ApplicationController.send(:include, RateHelper)
ApplicationController.send(:helper, :rate)
TimeEntry.send(:include, RateTimeEntryPatch)
UsersHelper.send(:include, RateUsersHelperPatch) unless UsersHelper.included_modules.include?(RateUsersHelperPatch)
end
end end
# Hooks # Hooks
require 'rate_project_hook' require_dependency 'rate_project_hook'
require 'rate_memberships_hook' require_dependency 'rate_memberships_hook'
Redmine::Plugin.register :redmine_rate do Redmine::Plugin.register :redmine_rate do
name 'Rate' name 'Rate'
@@ -35,9 +25,9 @@ Redmine::Plugin.register :redmine_rate do
url 'https://projects.littlestreamsoftware.com/projects/redmine-rate' url 'https://projects.littlestreamsoftware.com/projects/redmine-rate'
author_url 'http://www.littlestreamsoftware.com' author_url 'http://www.littlestreamsoftware.com'
description "The Rate plugin provides an API that can be used to find the rate for a Member of a Project at a specific date. It also stores historical rate data so calculations will remain correct in the future." description "The Rate plugin provides an API that can be used to find the rate for a Member of a Project at a specific date. It also stores historical rate data so calculations will remain correct in the future."
version '0.3.0' version '0.2.1'
requires_redmine :version_or_higher => '1.0.0' requires_redmine :version_or_higher => '2.0.0'
# These settings are set automatically when caching # These settings are set automatically when caching
settings(:default => { settings(:default => {
+6 -6
View File
@@ -5,11 +5,11 @@ class RateMembershipsHook < Redmine::Hook::ViewListener
def view_users_memberships_table_row(context={}) def view_users_memberships_table_row(context={})
return context[:controller].send(:render_to_string, { return context[:controller].send(:render_to_string, {
:partial => 'users/membership_rate', :partial => 'users/membership_rate',
:locals => { :locals => {
:membership => context[:membership], :membership => context[:membership],
:user => context[:user] :user => context[:user]
}}) }
})
end end
end end
+18 -61
View File
@@ -10,9 +10,9 @@ class RateProjectHook < Redmine::Hook::ViewListener
# Context: # Context:
# * :project => Current project # * :project => Current project
# #
def view_projects_settings_members_table_header(context ={ }) def view_projects_settings_members_table_header(context={})
return '' unless (User.current.allowed_to?(:view_rate, context[:project]) || User.current.admin?) return '' unless (User.current.allowed_to?(:view_rate, context[:project]) || User.current.admin?)
return "<th>#{l(:rate_label_rate)} #{l(:rate_label_currency)}</td>" return content_tag(:th, "#{l(:rate_label_rate)} #{l(:rate_label_currency)}")
end end
# Renders an AJAX from to update the member's billing rate # Renders an AJAX from to update the member's billing rate
@@ -22,72 +22,29 @@ class RateProjectHook < Redmine::Hook::ViewListener
# * :member => Current Member record # * :member => Current Member record
# #
# TODO: Move to a view # TODO: Move to a view
def view_projects_settings_members_table_row(context = { }) def view_projects_settings_members_table_row(context={})
member = context[:member] return '' unless (User.current.allowed_to?(:view_rate, context[:project]) || User.current.admin?)
project = context[:project]
return '' unless (User.current.allowed_to?(:view_rate, project) || User.current.admin?)
if Object.const_defined? 'Group' # 0.8.x compatibility if Object.const_defined? 'Group' # 0.8.x compatibility
# Groups cannot have a rate # Groups cannot have a rate
return content_tag(:td,'') if member.principal.is_a? Group return content_tag(:td,'') if context[:member].principal.is_a? Group
rate = Rate.for(member.principal, project) rate = Rate.for(context[:member].principal, context[:project])
else else
rate = Rate.for(member.user, project) rate = Rate.for(context[:member].user, context[:project])
end end
content = '' return context[:controller].send(:render_to_string, {
partial: "projects/settings_members",
if rate.nil? || rate.default? locals: {
if rate && rate.default? form_url: {
content << "<em>#{number_to_currency(rate.amount)}</em> " :controller => 'rates',
end :action => 'create'
},
if (User.current.admin?) rate: rate,
member: context[:member],
url = { project: context[:project]
:controller => 'rates',
:action => 'create',
:method => :post,
:protocol => Setting.protocol,
:host => Setting.host_name
} }
# Build a form_remote_tag by hand since this isn't in the scope of a controller })
# and url_rewriter doesn't like that fact.
form = form_tag(url, :onsubmit => remote_function(:url => url,
:host => Setting.host_name,
:protocol => Setting.protocol,
:form => true,
:method => 'post',
:return => 'false' )+ '; return false;')
form << text_field(:rate, :amount)
form << hidden_field(:rate,:date_in_effect, :value => Date.today.to_s)
form << hidden_field(:rate, :project_id, :value => project.id)
form << hidden_field(:rate, :user_id, :value => member.user.id)
form << hidden_field_tag("back_url", url_for(:controller => 'projects', :action => 'settings', :id => project, :tab => 'members', :protocol => Setting.protocol, :host => Setting.host_name))
form << submit_tag(l(:rate_label_set_rate), :class => "small")
form << "</form>"
content << form
end
else
if (User.current.admin?)
content << content_tag(:strong, link_to(number_to_currency(rate.amount), {
:controller => 'users',
:action => 'edit',
:id => member.user,
:tab => 'rates',
:protocol => Setting.protocol,
:host => Setting.host_name
}))
else
content << content_tag(:strong, number_to_currency(rate.amount))
end
end
return content_tag(:td, content, :align => 'left', :id => "rate_#{project.id}_#{member.user.id}" )
end end
def model_project_copy_before_save(context = {}) def model_project_copy_before_save(context = {})
+4 -4
View File
@@ -18,11 +18,11 @@ module RateTimeEntryPatch
module ClassMethods module ClassMethods
# Updated the cached cost of all TimeEntries for user and project # Updated the cached cost of all TimeEntries for user and project
def update_cost_cache(user, project=nil) def update_cost_cache(user, project=nil)
c = ARCondition.new #c = ARCondition.new
c << ["#{TimeEntry.table_name}.user_id = ?", user] c = "#{TimeEntry.table_name}.user_id = %d" % [user.id]
c << ["#{TimeEntry.table_name}.project_id = ?", project] if project c << " AND #{TimeEntry.table_name}.project_id = %d" % [project.id] if project
TimeEntry.all(:conditions => c.conditions).each do |time_entry| TimeEntry.all(:conditions => c ).each do |time_entry|
time_entry.save_cached_cost time_entry.save_cached_cost
end end
end end
@@ -2,7 +2,7 @@ module RedmineRate
module Hooks module Hooks
class ViewLayoutsBaseHtmlHeadHook < Redmine::Hook::ViewListener class ViewLayoutsBaseHtmlHeadHook < Redmine::Hook::ViewListener
def view_layouts_base_html_head(context={}) def view_layouts_base_html_head(context={})
stylesheet_link_tag "rate.css", :plugin => "redmine_rate" content_tag(:style, "#admin-menu a.rate-caches { background-image: url('#{image_path('database_refresh.png')}'); }", :type => 'text/css')
end end
end end
end end