Commit 0cb752ee by Nguyen Vo Huy Hoang

Add a plugin: Redmine Work Time

parent 1fe8a08d
Pipeline #1527 failed with stages
in 0 seconds
WorkTime is a plugin of Redmine to view and update Spent time by each user.
### Installation notes ###
0. Setup Redmine
1. Download redmine_work_time-*.zip from https://bitbucket.org/tkusukawa/redmine_work_time/downloads
2. Expand the plugin into the plugins directory
3. Migrate plugin: rake redmine:plugins:migrate RAILS_ENV=production
4. Restart Redmine
5. Enable the module on the project setting page.
6. Check the permissions on the Roles and permissions(Administration)
### Links ###
* http://www.redmine.org/plugins/redmine_work_time
* https://bitbucket.org/tkusukawa/redmine_work_time
* http://www.r-labs.org/projects/worktime/
\ No newline at end of file
= work_time
Description goes here
module WorkTimeHelper
def print_issue_cost(issue)
return "" unless issue
if issue.tracker_id == 12 # Userstory
issue_cost_est = issue.total_estimated_hours
issue_cost = issue.total_spent_hours
else
issue_cost_est = issue.estimated_hours || 'NG'
issue_cost = TimeEntry.where(:issue_id => issue.id).sum(:hours).to_f
end
due_date = issue.due_date || 'NG'
return sprintf("(%1.1f/%s/%s)",issue_cost, issue_cost_est, due_date)
end
def print_issue_cost_rate(issue)
return "" unless issue
issue_cost_est = issue.estimated_hours
return "" unless issue_cost_est
issue_cost = TimeEntry.where(:issue_id => issue.id).sum(:hours).to_f
return sprintf("%1.0f",issue_cost/issue_cost_est*100)
end
def wk_pretty_issue_name(issue, issue_id = issue.id)
if issue.nil? || !issue.visible?
content_tag :del, issue_id
elsif issue.closed?
content_tag :del, issue.to_s
else
issue.to_s
end
end
end
class UserIssueMonth < ActiveRecord::Base
attr_accessible :uid, :issue, :odr
end
class WtDailyMemo < ActiveRecord::Base
attr_accessible :user_id, :day, :created_on, :updated_on, :description
end
class WtHolidays < ActiveRecord::Base
attr_accessible :holiday, :created_on, :created_by
end
class WtMemberOrder < ActiveRecord::Base
attr_accessible :user_id, :position, :prj_id
end
class WtProjectOrders < ActiveRecord::Base
attr_accessible :uid, :dsp_prj, :dsp_pos
end
class WtTicketRelay < ActiveRecord::Base
attr_accessible :issue_id, :position, :parent
end
<%
settings = Setting.plugin_redmine_work_time
if settings.is_a?(Hash) &&
settings['account_start_days'].is_a?(Hash) &&
settings['account_start_days'].has_key?(@project.id.to_s)
day = settings['account_start_days'][@project.id.to_s]
else
day = 1
end
%>
<%= form_tag(:controller=>"work_time", :id=>@project, :action => "register_project_settings") do %>
<p>
<%=content_tag(:label, l(:wt_account_start_day))%>
<%=number_field_tag 'account_start_day', day , in: 1..31 %>
</p>
<%= submit_tag l(:wt_update) %>
<%end%>
<%
@settings = Hash.new unless @settings.is_a?(Hash)
%>
<p>
<%= label_tag :settings_show_account_menu, 'show account menu' %>
<%= check_box_tag 'settings[show_account_menu]', true, @settings['show_account_menu'] %>
</p>
<% (@settings['account_start_days'] || {}).each do |k,v| %>
<%= hidden_field_tag "settings[account_start_days][#{k}]", v %>
<% end %>
<%#*************************************************** プロジェクトセレクタ %>
<%= @restrict_project ? Project.find(@restrict_project).name : ""%>
<select onchange="if (this.value != '') {window.location = this.value;}">
<option selected="selectes"><%=l(:wt_select_project)%></option>
<option value="<%= url_for(@link_params.merge(:prj=>false));%>">---</option>
<%
prjs = Project.
joins("LEFT JOIN wt_project_orders ON wt_project_orders.dsp_prj=projects.id AND wt_project_orders.uid=#{User.current.id}").
select("projects.*, coalesce(wt_project_orders.dsp_pos,100000) as pos").
order("pos,name").
all
Project.project_tree(prjs) do |prj, level|
next unless prj.active?
next if !prj.visible?
name_prefix = (level > 0 ? '&nbsp;' * 2 * level + '&#187; ': '').html_safe
%>
<option value="<%= url_for(@link_params.merge(:prj=>prj.id));%>"> <%=name_prefix + prj.name%> </option>
<%end%>
</select>
<%#**************************************************** ユーザセレクタ %>
<%if @project then%>
<%=l(:wt_select_user)%>
<select onchange="if (this.value != '') {window.location = this.value;}">
<option value="">---</option>
<%
members_name_id = Array.new
@members.each {|mem| members_name_id << [mem[1].to_s, mem[1].id]}
members_name_id.sort!
members_name_id.each do |member_name_id|
sel = (member_name_id[1] == @this_uid) ? 'selected' : ''
%>
<option value="<%= url_for(link_params.merge(:user=>member_name_id[1]));%>" <%=sel%>>
<%=member_name_id[0]%>
</option>
<%
end
%>
</select>
<%end%>
<table border="0" id="time_input_table">
<tr style="background:#fff;font-size:14px">
<td>&nbsp;</td>
<td><%=l(:work_time)%></td>
<% if @is_registerd_backlog then %>
<td><%=l(:field_remaining_hours)%></td>
<% end %>
<td><%=l(:field_activity)%></td>
<td><%=l(:field_status)%></td>
<td><%=l(:field_comments)%></td>
<% @custom_fields.each do |cf| %>
<td><%= cf.name %></td>
<% end %>
</tr>
<%
@day_pack[:odr_prjs].each do |prj_pack|
next if prj_pack[:ref_issues].length==0
prj = prj_pack[:prj]
next if !prj.visible?
dsp_prj = prj.id
dsp_pos = prj_pack[:odr]
activities = []
activity_default = nil
prj.activities.each do |act|
activities.push([act.name, act.id])
activity_default = act.id if act.is_default
end
%>
<tr style="background:#000;color:#fff;">
<td>
<%if @this_uid==@crnt_uid then%>
<a href="#"
style="color:#8ff;"
onclick="prj_pos('<%=url_for(@link_params) %>',
<%=dsp_prj%>,
<%=dsp_pos%>,
<%=@prj_odr_max+((dsp_pos.to_i<0)?1:0)%>);
return false;">
<%= (dsp_pos.to_i<0) ? "*" : dsp_pos %>:
</a>
<%end%>
<%=prj.name%>
</td>
<td><%=sprintf("%1.2f", prj_pack[:total])%></td>
<% if @is_registerd_backlog then %>
<td>&nbsp;</td>
<% end %>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<% @custom_fields.each do |cf| %>
<td>&nbsp;</td>
<% end %>
</tr>
<%
prj_pack[:odr_issues].each do |issue_pack|
issue = issue_pack[:issue]
issue_id = issue.nil? ? -1 : issue.id
issue_odr = issue_pack[:odr].to_i
# issue_class = issue_pack[:worked] ? "#cfc" : "#fff"
issue_css_classes = issue_pack[:css_classes]
issue = Issue.find_by_id(issue_id)
issue_html = wk_pretty_issue_name issue, issue_id
if issue_pack[:each_entries].length==0 then
%>
<!-- 工数エントリなし -->
<tr id="time_entry_pos<%=issue_id%>_0">
<td class="<%=issue_css_classes%>">
<div style="position:relative;width:300px;">
<%if @this_uid==@crnt_uid then%>
<a href="#"
onclick="ticket_pos('<%=url_for(@link_params) %>',
<%=issue_id%>,
<%=issue_odr%>,
<%=@issue_odr_max+((issue_odr.to_i<0)?1:0)%>);
return false;">
<%= (issue_odr.to_i<0) ? "*" : issue_odr %>
</a>
<%end%>
<%= link_to(issue_html,
{:controller=>"issues", :action=>"show", :id=>issue_id},
:popup=>true, :class=>'wt_iss_link', :'data-issue'=>issue_id) %>
<span class="tooltip">
<strong><%= print_issue_cost(issue) %></strong>
<span class="tip">Logtime/Estimation/Due_Date</span>
</span>
<%if User.current.allowed_to?(:edit_issues, issue.project)%>
<a name="<%='done_ratio'+issue.id.to_s%>"
class="wt_done_ratio"
data-issue="<%= issue_id %>"
href="#"
onclick="input_done_ratio(
'<%=url_for(@link_params.merge(:action=>"ajax_done_ratio_input"))%>',
<%=issue_id%>);
return false;">
[<%=issue.done_ratio%>&#37;]
</a>
<%else%>
[<%=issue.done_ratio%>&#37;]
<%end%>
<%if @this_uid==@crnt_uid then%>
&nbsp;&nbsp;&nbsp;
<a style="position:absolute;bottom:1px;right:10px;"
href="#"
onclick="dup_ticket(
'<%=url_for(@link_params.merge(:action=>"ajax_add_tickets_insert"))%>',
'time_entry_pos<%=issue_id%>_0',
<%=issue_id%>);
return false;">
+
</a>
<%if issue_odr>0 then%>
<a style="position:absolute;bottom:1px;right:3px;" href="<%=url_for(@link_params.merge(:ticket_del=>issue_id))%>">x</a>
<%end%>
<%end%>
</div>
</td>
<td>
<%= text_field_tag("new_time_entry["+issue_id.to_s+"][0][hours]", "", :size=>5, :oninput => "sumDayTimes()") %>
</td>
<% if @is_registerd_backlog then %>
<td>
<% if issue_pack[:cnt_childrens] != 0 || issue.closed? then %>
<%= issue[:remaining_hours] %>
<% else %>
<%= text_field_tag("new_time_entry["+issue_id.to_s+"][0][remaining_hours]", issue[:remaining_hours], :size=>5, :oninput => "sumDayTimes()") %>
<% end %>
</td>
<% end %>
<td>
<%= select_tag "new_time_entry["+issue_id.to_s+"][0][activity_id]", options_for_select(activities,activity_default) %>
</td>
<td>
<% if issue.new_statuses_allowed_to(User.current).length == 0 then %>
<%= issue.status %>
<% else %>
<% select_name="new_time_entry["+issue_id.to_s+"][0][status_id]" %>
<%= select_tag select_name,
options_for_select(issue.new_statuses_allowed_to(User.current).collect {|p| [p.name, p.id]},
issue.status_id),
:onchange => "statusUpdateOnDailyTable('#{select_name}')",
:required => true %>
<% end %>
</td>
<td>
<%= text_field_tag("new_time_entry["+issue_id.to_s+"][0][comments]", "", :size=>80)%>
</td>
<%if @custom_fields.length != 0
dummy_hour = TimeEntry.new(:project => issue.project, :issue => issue, :user => @this_user, :spent_on => @this_date)
dummy_hour.custom_field_values.each do |cfv|
%>
<td><%= custom_field_tag "new_time_entry_"+issue_id.to_s+"_0", cfv %></td>
<%end
end%>
</tr>
<%
else
issue_pack[:each_entries].each do |hour_id, hour|
%>
<!-- 工数エントリあり -->
<tr id="time_entry_pos<%=hour_id%>">
<td class="<%=issue_css_classes%>">
<div style="position:relative;width:300px;">
<%if !issue.nil? then%>
<%if @this_uid==@crnt_uid then%>
<a href="#"
onclick="ticket_pos('<%=url_for(@link_params) %>',
<%=issue_id%>,
<%=issue_odr%>,
<%=@issue_odr_max+((issue_odr.to_i<0)?1:0)%>);
return false;">
<%= (issue_odr.to_i<0) ? "*" : issue_odr %>
</a>
<%end%>
<%= link_to(issue_html,
{:controller=>"issues", :action=>"show", :id=>issue_id},
:popup=>true, :class=>'wt_iss_link', :'data-issue'=>issue_id) %>
<%= print_issue_cost(issue) %>
<%if User.current.allowed_to?(:edit_issues, issue.project)%>
<a name="<%='done_ratio'+issue_id.to_s%>"
class="wt_done_ratio"
data-issue="<%= issue_id %>"
href="#"
onclick="input_done_ratio(
'<%=url_for(@link_params.merge(:action=>"ajax_done_ratio_input"))%>',
<%=issue_id%>);
return false;">
[<%=issue.done_ratio%>&#37;]
</a>
<%else%>
[<%=issue.done_ratio%>&#37;]
<%end%>
<%if @this_uid==@crnt_uid then%>
&nbsp;&nbsp;&nbsp;
<a style="position:absolute;bottom:1px;right:10px;"
href="#"
onclick="dup_ticket(
'<%=url_for(@link_params.merge(:action=>"ajax_add_tickets_insert"))%>',
'time_entry_pos<%=hour_id%>',
<%=issue_id%>);
return false;">
+
</a>
<%if issue_odr>0 then%>
<a style="position:absolute;bottom:1px;right:3px;" href="<%=url_for(@link_params.merge(:ticket_del=>issue_id))%>">x</a>
<%end%>
<%end%>
<%end%>
</div>
</td>
<td>
<%= text_field_tag("time_entry["+hour_id.to_s+"][hours]", sprintf("%1.2f", hour.hours), :size=>5, :oninput => "sumDayTimes()") %>
</td>
<% if @is_registerd_backlog then %>
<td>
<% if issue_pack[:cnt_childrens] != 0 || hour.issue.closed? then %>
<%= hour.issue[:remaining_hours] %>
<% else %>
<%= text_field_tag("time_entry["+hour_id.to_s+"][remaining_hours]", hour.issue[:remaining_hours], :size=>5, :oninput => "sumDayTimes()") %>
<% end %>
</td>
<% end %>
<td>
<%= select_tag "time_entry["+hour_id.to_s+"][activity_id]", options_for_select(activities, hour.activity_id), :required => true %>
</td>
<td>
<% if issue.new_statuses_allowed_to(User.current).length == 0 then %>
<%= issue.status %>
<% else %>
<% select_name="time_entry["+hour_id.to_s+"][status_id]" %>
<%= select_tag select_name,
options_for_select(issue.new_statuses_allowed_to(User.current).collect {|p| [p.name, p.id]},
issue.status_id),
:onchange => "statusUpdateOnDailyTable('#{select_name}')",
:required => true %>
<% end %>
</td>
<td>
<%= text_field_tag("time_entry["+hour_id.to_s+"][comments]", hour.comments, :size=>80)%>
</td>
<% hour.custom_field_values.each do |cfv| %>
<td><%= custom_field_tag "time_entry_"+hour_id.to_s, cfv %></td>
<% end %>
</tr>
<%
end
end
end
end
%>
<% if @day_pack[:other]!=0 then %>
<tr style="background:#000;color:#fff;">
<td>private</td>
<td><%=sprintf("%1.2f", @day_pack[:other])%></td>
<% if @is_registerd_backlog then %>
<td><%=sprintf("%1.2f", @day_pack[:other_remain]) if @day_pack[:other_remain]%></td>
<% end %>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<% @custom_fields.each do |cf| %>
<td>&nbsp;</td>
<% end %>
</tr>
<% end %>
<tr align="center" id="time_input_table_bottom" style="background:#ddd;">
<td>&nbsp;</td>
<td><span id='currentTotal' title='<%=l(:wt_saved_value)%> <%=sprintf("%1.2f", @day_pack[:total])%>'><%=sprintf("%1.2f", @day_pack[:total])%></span></td>
<% if @is_registerd_backlog then %>
<td>&nbsp;</td>
<% end %>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<% @custom_fields.each do |cf| %>
<td>&nbsp;</td>
<% end %>
</tr>
</table>
<%
win_w = 35 # 小窓の幅
win_h = 31 # 小窓の高さ
win_hs = 20 # 小さい小窓の高さ
box_w = 300
box_h = win_hs*3+win_h*@month_pack[:count_issues]+win_hs*@month_pack[:count_prjs]+20
if @month_pack[:other]!=0 then
box_h += win_hs
end
%>
<h2><%=l(:wt_monthly_report)%> (<%=@this_user%>)</h2>
<table width="100%" style="border:0;border-collapse:collapse;">
<tr>
<!-- ************************************************ 左側を表示 -->
<td style="width:<%=box_w%>px;padding:0px;">
<div style="background: #ccc;">
<div style="position:relative;height:<%=box_h%>px;overflow:auto;">
<div style="position:absolute;top:1px;left:1px;">
<div style="background: #fff;font-size:1.5em;">
<div style="text-align:center;position:relative;top:1px;left:1px;width:<%=box_w-2%>px;height:<%=win_hs*2-1%>px;">
<%= @first_date.strftime("%Y/%m/%d") %> - <%= @last_date.strftime("%Y/%m/%d") %>
</div>
</div>
<div style="text-align:right;position:absolute;top:1px;left:1px;width:<%=box_w-2%>px;height:<%=win_hs*2-1%>px;">
<%= link_to(">>", @link_params.merge(:day=>@next_month.day, :month=>@next_month.month, :year=>@next_month.year))%>
</div>
<div style="text-align:left;position:absolute;top:1px;left:1px;">
<%= link_to("<<", @link_params.merge(:day=>@last_month.day, :month=>@last_month.month, :year=>@last_month.year))%>
</div>
</div>
<%
ofst_t = win_hs*3-5
@month_pack[:odr_prjs].each do |prj_pack|
next if prj_pack[:count_issues] == 0
prj = prj_pack[:prj]
dsp_pos = prj_pack[:odr]
prj_ofst_t = ofst_t
ofst_t += win_hs
prj_pack[:odr_issues].each do |issue_pack|
next if issue_pack[:count_hours] == 0
issue = issue_pack[:issue]
issue_id = issue.nil? ? -1 : issue.id
issue_odr = issue_pack[:odr]
%>
<div style="position:absolute;top:<%=ofst_t%>px;left:1px;">
<div style="background: #fff;font-size:0.8em;">
<div style="position:relative;top:1px;left:1px;width:<%=box_w-2%>px;height:<%=win_h-1%>px;">
<%if !issue.nil? then%>
<%if @this_uid==@crnt_uid then%>
<a href="#"
onclick="JavaScript:
ticket_pos(
'<%=url_for(@link_params) %>',
<%=issue_id%>,
<%=issue_odr%>,
<%=@issue_odr_max+((issue_odr.to_i<0)?1:0)%>);
return false;">
<%= (issue_odr.to_i<0) ? "*" : issue_odr %>
</a>
<%end%>
<%= link_to(wk_pretty_issue_name(issue, issue_id), {:controller=>"issues", :action=>"show", :id=>issue_id}, :popup=>true, :class=>'wt_iss_link', :'data-issue'=>issue_id) %>
<%= print_issue_cost(issue) %>
<%end%>
<div style="position:absolute;top:15px;right:15px;">
<%=sprintf("%1.2f", issue_pack[:total])%>
</div>
</div>
</div>
</div>
<%
ofst_t += win_h
end
%>
<div style="position:absolute;top:<%=prj_ofst_t%>px;left:2px;">
<div style="background:#000;color:#fff;font-size:1.0em;">
<div style="position:relative;top:1px;left:1px;width:<%=box_w-3%>px;height:<%=win_hs-1%>px;">
<%if @this_uid==@crnt_uid then%>
<a href="#"
style="color:#8ff;"
onclick="JavaScript:
prj_pos(
'<%=url_for(@link_params) %>',
<%=prj.id%>,
<%=dsp_pos%>,
<%=@prj_odr_max+((dsp_pos.to_i<0)?1:0)%>);
return false;">
<%= (dsp_pos.to_i<0) ? "*" : dsp_pos %>:
</a>
<%end%>
<%= prj.name%>
<div style="position:absolute;top:1px;right:10px;">
<%=sprintf("%1.2f",prj_pack[:total])%>
</div>
</div>
</div>
</div>
<%
end
%>
<%if @month_pack[:other]!=0 then%>
<div style="position:absolute;top:<%=ofst_t%>px;left:2px;">
<div style="background:#000;color:#fff;font-size:1.0em;">
<div style="position:relative;top:1px;left:1px;width:<%=box_w-4%>px;height:<%=win_hs-2%>px;">
private
<div style="position:absolute;top:1px;right:10px;">
<%=sprintf("%1.2f", @month_pack[:other])%>
</div>
</div>
</div>
</div>
<%end%>
<div style="position:absolute;bottom:10px;right:10px;">
<%=sprintf("%1.2f", @month_pack[:total])%>
</div>
<div style="position:absolute;top:<%=win_hs*2%>px;right:10px;">
<%=sprintf("%1.2f", @month_pack[:total])%>
</div>
</div>
</div>
</td>
<!-- ************************************************ 右側を表示 -->
<td>
<div style="background: #ccc;">
<div style="position:relative;height:<%=box_h%>px;overflow:auto;" id="day_scroll">
<% # チケット毎の合計時間を計算&表示
day_pos = 0
(@first_date..@last_date).each do |date|
day_pos += 1
month = date.month
day = date.day
wday = date.wday
ofst_l = win_w*(day_pos-1)
holidayEntry = WtHolidays.
where(["holiday=:h and deleted_on is null",{:h=>date}]).
all
if holidayEntry.size == 0 then
bcolor = @wday_color[wday]
else
bcolor = "#fbc"
end
if day==@this_date.day then
bcolor_day = "#cfc"
today_id = 'id=day_scroll_today'
else
bcolor_day = bcolor
today_id = ''
end
%>
<div style="position:absolute;top:1px;left:<%=ofst_l%>px;" <%=today_id%> >
<div style="background:<%=bcolor_day%>;">
<div style="text-align:center;position:relative;top:1px;left:1px;width:<%=win_w-1%>px;height:<%=win_hs-1%>px;">
<%= link_to(day, @link_params.merge(:day=>day, :month=>month)) %>
</div>
</div>
</div>
<div style="position:absolute;top:<%=win_hs+1%>px;left:<%=ofst_l%>px;">
<div style="background:<%=bcolor%>;">
<div style="text-align:center;position:relative;top:1px;left:1px;width:<%=win_w-1%>px;height:<%=win_hs-1%>px;">
<%= @wday_name[wday]%>
</div>
</div>
</div>
<%
ofst_t = win_hs*3-5
day_cost = 0
@month_pack[:odr_prjs].each do |prj_pack|
next if prj_pack[:count_issues] == 0
dsp_prj = prj_pack[:prj].id
dsp_pos = prj_pack[:odr]
prj_ofst_t = ofst_t
ofst_t += win_hs
prj_pack[:odr_issues].each do |issue_pack|
next if issue_pack[:count_hours] == 0
issue = issue_pack[:issue]
issue_id = issue.nil? ? -1 : issue.id
issue_odr = issue_pack[:odr]
%>
<div style="position:absolute;top:<%=ofst_t%>px;left:<%=ofst_l%>px;">
<div style="background:<%=bcolor%>;font-size:0.8em;">
<div style="text-align:center;position:relative;top:5px;left:1px;width:<%=win_w-1%>px;height:<%=win_h-1%>px;">
<%
if issue_pack[:total_by_day].has_key?(date) then
%>
<%=sprintf("%1.2f", issue_pack[:total_by_day][date])%>
<%
end
%>
</div>
</div>
</div>
<%
ofst_t += win_h
end
%>
<div style="position:absolute;top:<%=prj_ofst_t%>px;left:<%=ofst_l%>px;">
<div style="background:#000;color:#fff;font-size:0.8em;">
<div style="text-align:center;position:relative;top:5px;left:1px;width:<%=win_w-1%>px;height:<%=win_hs-1%>px;">
<%if prj_pack[:total_by_day].has_key?(date) then%>
<%=sprintf("%1.2f", prj_pack[:total_by_day][date])%>
<%end%>
</div>
</div>
</div>
<%
end
%>
<!--日毎の合計時間表示-->
<div style="position:absolute;top:<%=win_hs*2%>px;left:<%=ofst_l%>px;">
<div style="font-size:0.8em;">
<div style="text-align:center;position:relative;top:1px;left:1px;width:<%=win_w-2%>px;height:<%=win_hs-2%>px;">
<%if @month_pack[:total_by_day].has_key?(date) then%>
<%= sprintf("%1.2f", @month_pack[:total_by_day][date])%>
<%end%>
</div>
</div>
</div>
<!--otherの時間表示-->
<%if @month_pack[:other]!=0 then%>
<div style="position:absolute;top:<%=ofst_t%>px;left:<%=ofst_l%>px;">
<div style="background:#000;color:#fff;font-size:0.8em;">
<div style="text-align:center;position:relative;top:5px;left:1px;width:<%=win_w-2%>px;height:<%=win_hs-2%>px;">
<%if @month_pack[:other_by_day].has_key?(date) then%>
<%= sprintf("%1.2f", @month_pack[:other_by_day][date])%>
<%end%>
</div>
</div>
</div>
<%end%>
<%end%>
</div>
</div>
</td>
</tr>
</table>
<input type="button"
onclick="location.href='<%=url_for(@link_params.merge(:action=>"member_monthly_data"))%>'"
value="<%=l(:wt_data_download)%>"
/>
<br/>
<script type="text/javascript">
<!--
var scr = document.getElementById("day_scroll");
var tgt = document.getElementById("day_scroll_today");
scr.scrollLeft = tgt.offsetLeft - scr.offsetLeft;
-->
</script>
<div class="wt_add_ticket_block">
<h2><%=l(:wt_add_ticket)%></h2>
<select onchange="if (this.value != '') {
jQuery.ajax({
url: this.value,
data: {asynchronous: true, method: 'get'},
success: function (response) {
jQuery('#input_tickets').replaceWith(response);}
})
return false;}">
<option value=''><%=l(:wt_select_project)%></option>
<option disabled="disabled">---</option>
<%
Project.project_tree(@select_projects) do |prj, level|
next unless prj.active?
next if !User.current.allowed_to?(:log_time, prj)
members = Member.
where(["user_id=:u and project_id=:p",{:u=>User.current.id, :p=>prj.id}]).
all
next if members.size==0
name_prefix = (level > 0 ? '&nbsp;' * 2 * level + '&#187; ': '').html_safe
%>
<option value="<%= url_for(:action=>"ajax_add_tickets_input_select", :prj=>prj.id) %>">
<%= name_prefix + prj.name %>
</option>
<%
end
%>
</select>
<div id="input_tickets" style="display: inline-block;_display: inline;">
<%=l(:wt_input_ticket_numbers)%>
<form action="">
<input type="text"
id="input_ids"
size=32
onKeyPress="if(checkEnter(event)) {
tickets_inputed('<%=url_for(@link_params.merge(:action=>"ajax_add_tickets_insert"))%>');
return false;
}
return event;"
/>
<input type="button"
value="<%=l(:button_apply)%>"
onclick="tickets_inputed('<%=url_for(@link_params.merge(:action=>"ajax_add_tickets_insert"))%>');"
/>
</form>
</div>
</div>
<script>
$('#input_ids').focus();
</script>
\ No newline at end of file
<div id="input_tickets">
<form style="font-size:14px;" action="">
<%
opt = {
:action => 'ajax_add_tickets_input_select',
:prj => params[:prj],
:all => params[:all] || '0',
:other => params[:other] || '0'
}
opt[:all] = opt[:all] == '0' ? '1' : '0' if params.key?(:all_toggle)
opt[:other] = opt[:other] == '0' ? '1' : '0' if params.key?(:other_toggle)
url1 = url_for(opt.merge({:all_toggle => ''}))
url2 = url_for(opt.merge({:other_toggle => ''}) )
link_label1 = opt[:all] == '0' ? l(:wt_opt_disp_ticket_with_closed) : l(:wt_opt_disp_ticket_opened_only)
link_label2 = opt[:other] == '0' ? l(:wt_opt_disp_ticket_with_other_member) : l(:wt_opt_disp_ticket_mine_only)
%>
<a href="#"
onclick="jQuery.ajax({
url: '<%=url1%>',
data: {asynchronous: true, method: 'get'},
success: function (response) {
jQuery('#input_tickets').replaceWith(response);}
});
return false;">
<%= link_label1 %>
</a>
<a href="#"
onclick="jQuery.ajax({
url: '<%=url2%>',
data: {asynchronous: true, method: 'get'},
success: function (response) {
jQuery('#input_tickets').replaceWith(response);}
});return false;">
<%= link_label2 %>
</a>
<br/>
<input type="button"
onclick="tickets_checked('<%=url_for(@link_params.merge(:action=>"ajax_add_tickets_insert"))%>');"
value="<%=l(:wt_apply_checked)%>"/>
<br/>
<div id="tickets_check">
<%
@issues.each do |issue|
next if issue.nil? || !issue.visible? || (opt[:other] == '0' && issue.assigned_to_id != User.current.id) || (issue.closed? && opt[:all] == '0')
%>
<input type="checkbox"
name="ticket_select_check"
value="<%=issue.id%>"
/>
<input type="button"
onclick="tickets_selected('<%=url_for(@link_params.merge(:action=>"ajax_add_tickets_insert"))%>', '<%=issue.id%>');"
value="<%=l(:button_apply)%>"
/>
(<%= link_to_user(issue.assigned_to || '-') %>): <%= wk_pretty_issue_name issue %>
<a href="#"
onclick="window.open('<%=url_for(:controller=>"issues", :action=>"show", :id=>issue.id)%>');">
&#63;
</a>
<br/>
<%end%>
</div>
</form>
<input type="button"
onclick="tickets_checked('<%=url_for(@link_params.merge(:action=>"ajax_add_tickets_insert"))%>');"
value="<%=l(:wt_apply_checked)%>"/>
<br/>
<br/>
</div>
<%if @add_issue then%>
<tr style="background:#ddf;" id="time_entry_pos<%=@add_issue_id%>_<%=@add_count%>">
<td>
<div style="position:relative;width:300px;">
<%=@add_issue.project.name%>
<br/>
<%= link_to(@issueHtml.html_safe, {:controller=>"issues", :action=>"show", :id=>@add_issue.id},
:popup=>true, :class=>'wt_iss_link', :'data-issue'=>@add_issue.id) %>
<%= print_issue_cost(@add_issue) %>
<%if User.current.allowed_to?(:edit_issues, @add_issue.project)%>
<a name="<%='done_ratio'+@add_issue.id.to_s%>"
class="wt_done_ratio"
data-issue="<%= @add_issue.id %>"
href="#"
onclick="JavaScript:
input_done_ratio(
'<%=url_for(@link_params.merge(:action=>"ajax_done_ratio_input"))%>',
<%=@add_issue.id%>);
return false;">
[<%=@add_issue.done_ratio%>&#37;]
</a>
<%else%>
[<%=@add_issue.done_ratio%>&#37;]
<%end%>
<a style="position:absolute;bottom:1px;right:10px;"
href="#"
onclick="JavaScript:
dup_ticket(
'<%=url_for(@link_params.merge(:action=>"ajax_add_tickets_insert"))%>',
'time_entry_pos<%=@add_issue_id%>_<%=@add_count%>',
<%=@add_issue.id%>);
return false;">
+
</a>
</div>
</td>
<td>
<%= text_field_tag("new_time_entry["+@add_issue_id+"]["+@add_count+"][hours]", "", :size=>5, :oninput => "sumDayTimes()") %>
</td>
<% if @is_registerd_backlog then %>
<td>
<% if @add_issue_children_cnt != 0 || @add_issue.closed? then %>
<%= @add_issue.remaining_hours %>
<% else %>
<%= text_field_tag("new_time_entry["+@add_issue_id+"]["+@add_count+"][remaining_hours]", @add_issue.remaining_hours, :size=>5, :oninput => "sumDayTimes()") %>
<% end %>
</td>
<% end %>
<td>
<%= select_tag "new_time_entry["+@add_issue_id+"]["+@add_count+"][activity_id]", options_for_select(@activities,@activity_default), :required => true %>
</td>
<td>
<%
if @add_issue.new_statuses_allowed_to(User.current).length == 0
%>
<%= @add_issue.status %>
<% else %>
<%= select_tag "new_time_entry["+@add_issue_id.to_s+"][0][status_id]", options_for_select(@add_issue.new_statuses_allowed_to(User.current), @add_issue.status), :required => true %>
<% end %>
</td>
<td>
<%= text_field_tag("new_time_entry["+@add_issue_id+"]["+@add_count+"][comments]", "", :size=>80)%>
</td>
<%if @custom_fields.length != 0
dummy_hour = TimeEntry.new(:project => @add_issue.project, :issue => @add_issue, :user => @this_user, :spent_on => @this_date)
dummy_hour.custom_field_values.each do |cfv|
%>
<td><%= custom_field_tag "new_time_entry_"+@add_issue_id+"_"+@add_count, cfv %></td>
<%end end%>
</tr>
<%end%>
<div name="<%='done_ratio'+@issue.id.to_s%>">
<% if @issue.estimated_hours then %>
<%= print_issue_cost(@issue) %>
&#61;
<%= print_issue_cost_rate(@issue) %>
&#37;
<br/>
<% end %>
<form action="">
<%= @issue.done_ratio %>
&#37;
&rarr;
<input type="text"
id="<%='input_ratio'+@issue.id.to_s%>"
size="4"
onKeyPress="if(checkEnter(event)) {
update_done_ratio('<%=url_for(@link_params.merge(:action=>"ajax_done_ratio_update"))%>', <%=@issue.id.to_s%>);
return false;
}
return event; "
value="<%= print_issue_cost_rate(@issue) %>"/>
&#37;
<input type="button"
value="<%=l(:button_apply)%>"
onclick="update_done_ratio('<%=url_for(@link_params.merge(:action=>"ajax_done_ratio_update"))%>',
<%=@issue.id.to_s%>);" />
</form>
</div>
<script>
$('#<%='input_ratio'+@issue.id.to_s%>').focus();
</script>
\ No newline at end of file
<%#
# チケットの進捗%をAjaxUpdateする
%>
<%if User.current.allowed_to?(:edit_issues, @issue.project)%>
<a name="<%='done_ratio'+@issue.id.to_s%>"
href="#"
onclick="input_done_ratio(
'<%=url_for(@link_params.merge(:action=>"ajax_done_ratio_input"))%>',
<%=@issue.id.to_s%>);
return false;">
[<%=@issue.done_ratio%>&#37;]
</a>
<%else%>
[<%=@issue.done_ratio%>&#37;]
<%end%>
\ No newline at end of file
<%
year = params["year"]
month = params["month"]
day = params["day"]
user_id = params["user"]
date = Date.new(year.to_i,month.to_i,day.to_i)
wday_name = l(:wt_week_day_names).split(',')
memo=WtDailyMemo.where(["day=:d and user_id=:u",{:d=>date,:u=>user_id}]).first
if memo then
%>
<textarea id="work_time_memo" name="memo" rows="15" cols="100"><%=memo.description -%></textarea>
<%else%>
<textarea id="work_time_memo" name="memo" rows="15" cols="100"></textarea>
<%end%>
<br/>
<%= submit_tag l(:wt_update) %>
<%= wikitoolbar_for 'work_time_memo' %>
<% if @message != '' %>
<div class="wt_error">
<%=@message.html_safe%>
</div>
<% end %>
<div class="<%=@relay_modified ? 'wt_modified' : ''%>">
=>
<%=@parent_disp.html_safe%>
<%
if User.current.allowed_to?(:edit_work_time_total, @project)
if @parent_disp != ''
%>
<a href="#"
onclick="jQuery.ajax({
url: '<%=url_for(:action=>"ajax_relay_input", :issue_id=>@issue_id.to_s)%>',
data: {asynchronous: true, method: 'get'},
success: function (response) {
jQuery('#ticket_relay_<%=@issue_id.to_s%>').html(response);
}
});
return false;">
[<%=l(:button_change)%>]
</a>
<a href="#"
onclick="jQuery.ajax({
url:'<%=url_for(:action=>'ajax_relay',:issue_id=>@issue_id, :parent_id=>0)%>',
data:{asynchronous:true, method:'get'},
success: function(response) {
jQuery('#ticket_relay_<%=@issue_id%>').html(response);}
});
return false;">
[<%=l(:button_delete)%>]
</a>
<%else%>
<a href="#"
onclick="jQuery.ajax({
url: '<%=url_for(:action=>"ajax_relay_input", :issue_id=>@issue_id.to_s)%>',
data: {asynchronous: true, method: 'get'},
success: function (response) {
jQuery('#ticket_relay_<%=@issue_id.to_s%>').html(response);
}
});
return false;">
[<%=l(:button_add)%>]
</a>
<%
end
end
%>
</div>
<select onchange="JavaScript:if (this.value != '') {
jQuery.ajax({
url:this.value,
data:{asynchronous:true, method:'get'},
success:function(response){
jQuery('#input_area_<%=@issue_id%>').replaceWith(response);
}
});
return false;}">
<option value=''><%=l(:wt_select_project)%></option>
<option disabled="disabled">---</option>
<%
@projects.each do |prj|
next unless prj.active?
next if !prj.visible?
%>
<option value="<%= url_for(:action=>"ajax_relay_input_select", :prj=>prj.id, :issue_id=>@issue_id) %>">
<%= (prj.pos.to_i < 100000) ? prj.pos : '*' %>: <%= prj.name %>
</option>
<%
end
%>
</select>
<div id="input_area_<%=@issue_id%>" style="display: inline-block;_display: inline;">
<%=l(:wt_input_ticket_numbers)%>
<form action="">
<input type="text"
id="input_id_<%=@issue_id%>"
size="8"
onKeyPress="if(checkEnter(event)) {
jQuery.ajax({
url:'<%=url_for(:action=>'ajax_relay',:issue_id=>@issue_id)%>' +
'&parent_id=' + $('#input_id_<%=@issue_id%>').val(),
data:{asynchronous:true, method:'get'},
success: function(response) {
jQuery('#ticket_relay_<%=@issue_id%>').html(response);}
});
return false;
}
return event;"
/>
<input type="button"
value="<%=l(:button_apply)%>"
onclick="jQuery.ajax({
url:'<%=url_for(:action=>'ajax_relay',:issue_id=>@issue_id)%>' +
'&parent_id=' + $('#input_id_<%=@issue_id%>').val(),
data:{asynchronous:true, method:'get'},
success: function(response) {
jQuery('#ticket_relay_<%=@issue_id%>').html(response);}
});
return false;"
/>
</form>
</div>
<a href="#"
onclick="jQuery.ajax({
url: '<%=url_for(:action=>"ajax_relay", :issue_id=>@issue_id.to_s)%>',
data: {asynchronous: true, method: 'get'},
success: function (response) {
jQuery('#ticket_relay_<%=@issue_id.to_s%>').html(response);
}
});
return false;">
<%=l(:button_cancel)%>
</a>
<script>
$('#input_id_<%=@issue_id%>').focus();
</script>
<div id="input_area_<%=@issue_id%>">
<%
opt = {
:action => 'ajax_relay_input_select',
:issue_id => @issue_id,
:prj => params[:prj],
:all => params[:all] || '0'
}
opt[:all] = opt[:all] == '0' ? '1' : '0' if params.key?(:all_toggle)
url1 = url_for(opt.merge({:all_toggle => ''}))
link_label1 = opt[:all] == '0' ? l(:wt_opt_disp_ticket_with_closed) : l(:wt_opt_disp_ticket_opened_only)
%>
<a href="#"
onclick="jQuery.ajax({
url: '<%=url1%>',
data: {asynchronous: true, method: 'get'},
success: function (response) {
jQuery('#input_area_<%=@issue_id%>').html(response);}
});JavaScript:
return false;">
<%= link_label1 %>
</a>
<br/>
<%
@issues.each do |issue|
next if issue.nil? || !issue.visible? || (issue.closed? && opt[:all] == '0')
%>
<div style="font-size:14px;">
<input type="button"
onclick="jQuery.ajax({
url:'<%=url_for(:action=>'ajax_relay', :issue_id=>@issue_id, :parent_id=>issue.id)%>',
data:{asynchronous:true, method:'get'},
success: function(response) {
jQuery('#ticket_relay_<%=@issue_id%>').html(response);}
});
"
value="<%=l(:button_apply)%>"
/>
(<%= link_to_user(issue.assigned_to || '-') %>): <%= wk_pretty_issue_name issue %>
<a href="#"
onclick="window.open('<%=url_for(:controller=>"issues", :action=>"show", :id=>issue.id)%>');
return false;">
&#63;
</a>
<br/>
</div>
<%end%>
</div>
<%=javascript_include_tag 'work_time', :plugin=>'redmine_work_time' %>
<%=stylesheet_link_tag 'work_time', :plugin => 'redmine_work_time' %>
<%= @message.html_safe %>
<div style="text-align:right;">
<%= render :partial=>'select_project' %> <br/>
[<%= link_to(l(:wt_each_member_report), @link_params.merge(:action=>"show")) %>]
[<%= link_to(l(:wt_raw_total), @link_params.merge(:action=>"total")) %>]
[<%= link_to(l(:wt_relay_total), @link_params.merge(:action=>"relay_total")) %>]
</div>
<%
###################################################### チケット関係テーブルの表示
%>
<br/>
<h2>
<%=l(:wt_edit_relay)%>
<%= link_to("<<", @link_params.merge(:day=>@last_month.day, :month=>@last_month.month, :year=>@last_month.year))%>
<%= @first_date.strftime("%Y/%m/%d") %> - <%= @last_date.strftime("%Y/%m/%d") %>
<%= link_to(">>", @link_params.merge(:day=>@next_month.day, :month=>@next_month.month, :year=>@next_month.year))%>
</h2>
<table border="1" id="relay_table">
<%
prjs = WtProjectOrders.where("uid=-1").order("dsp_pos").all
tickets = WtTicketRelay.order("position").all
tic_max = tickets.size
prjs.each do |po|
dsp_prj = po.dsp_prj
dsp_pos = po.dsp_pos
next if (!@prj_cost.has_key?(dsp_prj) || @prj_cost[dsp_prj][-1]==0.0) && (!@r_prj_cost.has_key?(dsp_prj) || @r_prj_cost[dsp_prj][-1]==0.0)
prj =Project.find_by_id(dsp_prj)
%>
<tr style="background:#000;color:#fff;">
<td>
<%if User.current.allowed_to?(:edit_work_time_total, @project) then%>
<a href="#"
style="color:#8ff;"
onclick="JavaScript:
prj_pos(
'<%=url_for(@link_params)%>',
<%=dsp_prj%>,
<%=dsp_pos%>,
<%=prjs.size%>);
return false;">
<%=dsp_pos%>:
</a>
<%end%>
<%=prj.name%>
</td>
<td style="text-align:right;">
<%if @prj_cost.has_key?(dsp_prj) && @prj_cost[dsp_prj][-1]!=0%>
<%=sprintf('%1.2f', @prj_cost[dsp_prj][-1])%>
<%else%>
&nbsp;
<%end%>
</td>
<td style="text-align:right;"><b>
<%if @r_prj_cost.has_key?(dsp_prj) && @r_prj_cost[dsp_prj][-1]!=0%>
<%=sprintf('%1.2f', @r_prj_cost[dsp_prj][-1]) %>
<%else%>
&nbsp;
<%end%>
</b></td>
<td>&nbsp;</td>
</tr>
<%
tic_num = 0
tickets.each do |tic|
issue_id = tic.issue_id
tic_num += 1
if tic.position != tic_num then # 番号が間違っていたらつけなおし
tic.position = tic_num; tic.save
end
# 当該チケットに集計が無かったらスキップ
next unless @issue_cost.has_key?(issue_id) || @r_issue_cost.has_key?(issue_id)
issue = Issue.find_by_id(issue_id)
parent_id = ""
next if issue.nil? # チケットが削除されていたらパス
next if issue.project_id != dsp_prj
if tic.parent && tic.parent != 0 then
parent = Issue.find_by_id(tic.parent)
if parent.nil? then
parentHtml = "<del>Issue:"+tic.parent.to_s+"</del>"
else
parent_id = parent.id
parentHtml = parent.closed? ? "<del>"+parent.to_s+"</del>" : parent.to_s
end
else
parentHtml = ""
end
if @issue_cost.key?(issue_id) &&
@issue_cost[issue_id].key?(-1) &&
@issue_cost[issue_id][-1]!=0 then
cost=sprintf("%.2f",@issue_cost[issue_id][-1])
else
cost="&nbsp"
end
if @r_issue_cost.key?(issue_id) &&
@r_issue_cost[issue_id].key?(-1) &&
@r_issue_cost[issue_id][-1]!=0 then
r_cost=sprintf("%.2f",@r_issue_cost[issue_id][-1])
else
r_cost="&nbsp"
end
%>
<tr>
<td>
<%if User.current.allowed_to?(:edit_work_time_total, @project) then%>
<a href="#"
onclick="JavaScript:
ticket_pos('<%=url_for(@link_params)%>',
<%=issue_id%>,
<%=tic.position%>,
<%=tic_max%>);
return false;">
<%=tic.position%>
</a>
<%end%>
<%= link_to(wk_pretty_issue_name(issue), {:controller=>"issues", :action=>"show", :id=>issue.id}, :popup=>true) %>
<%= print_issue_cost(issue) %>
</td>
<td style="text-align:right;"><%=cost.html_safe%></td>
<td style="text-align:right;"><%=r_cost.html_safe%></td>
<td id="ticket_relay_<%=issue_id%>"></td>
<script>
jQuery.ajax({
url: '<%=url_for(:action=>"ajax_relay", :issue_id=>issue_id.to_s)%>',
data: {asynchronous: true, method: 'get'},
success: function (response) {
jQuery('#ticket_relay_<%=issue_id.to_s%>').html(response);
}
});
</script>
</tr>
<%
end
end
%>
<% if @prj_cost.has_key?(-1) || @r_prj_cost.has_key?(-1) then%>
<tr style="background:#000;color:#fff;">
<td>private</td>
<td style="text-align:right;">
<%if @prj_cost.has_key?(-1) then%>
<%=sprintf('%1.2f', @prj_cost[-1][-1])%>
<%else%>
&nbsp;
<%end%>
</td>
<td style="text-align:right;">
<%if @r_prj_cost.has_key?(-1) then%>
<b><%=sprintf('%1.2f', @r_prj_cost[-1][-1]) if @r_prj_cost[-1][-1]%></b>
<%else%>
&nbsp;
<%end%>
</td>
<td>&nbsp;</td>
</tr>
<% end %>
</table>
<%= submit_tag(l('wt_bulkupdate_relations'),
{:type => 'button',
:onclick => "set_ticket_relay_by_issue_relation('#{url_for(:action=>'ajax_relay', :parent_id=>-1)}')".html_safe}) %>
<div style="text-align:right;">
<%= render :partial=>'select_project' %> <br/>
[<%= link_to(l(:wt_each_member_report), @link_params.merge(:action=>"show")) %>]
[<%= link_to(l(:wt_raw_total), @link_params.merge(:action=>"total")) %>]
[<%= link_to(l(:wt_relay_total), @link_params.merge(:action=>"relay_total")) %>]
</div>
api.total_relay do
api.total_cost @total_cost
api.array :member_cost do
@members.each do |mem_info|
if @member_cost.key?(mem_info[1].id) && @member_cost[mem_info[1].id] > 0 then
api.member_cost do
api.user(:id => mem_info[1].id, :firstname => mem_info[1].firstname, :lastname => mem_info[1].lastname) unless mem_info[1].nil?
api.cost @member_cost[mem_info[1].id]
end
end
end
end
api.array :issues_cost do
@r_issue_cost.each do |issue,cost|
iss = Issue.find_by_id(issue)
api.issue_cost do
api.issue do
api.id iss.id unless iss.nil?
api.tracker(:id => iss.tracker.id, :name => iss.tracker.name) unless iss.tracker.nil?
api.subject iss.subject
end
api.cost cost[-1]
end
end
end
end
<%=javascript_include_tag "work_time", :plugin=>'redmine_work_time' %>
<%=stylesheet_link_tag 'work_time', :plugin => 'redmine_work_time' %>
<%= @message.html_safe %>
<div style="text-align:right;">
<%= render :partial=>'select_project' %> <br/>
[<%= link_to(l(:wt_each_member_report), @link_params.merge(:action=>"show")) %>]
[<%= link_to(l(:wt_edit_relay), @link_params.merge(:action=>"edit_relay")) %>]
[<%= link_to(l(:wt_raw_total), @link_params.merge(:action=>"total")) %>]
</div>
<h2>
<%=l(:wt_relay_total)%>
<%= link_to("<<", @link_params.merge(:day=>@last_month.day, :month=>@last_month.month, :year=>@last_month.year))%>
<%= @first_date.strftime("%Y/%m/%d") %> - <%= @last_date.strftime("%Y/%m/%d") %>
<%= link_to(">>", @link_params.merge(:day=>@next_month.day, :month=>@next_month.month, :year=>@next_month.year))%>
</h2>
<%
if !User.current.allowed_to?(:view_work_time_other_member, @project) then
return
end
############################################## 集計表 #####################
%>
<table border="1">
<tr valign="top">
<td>
</td>
<td style="background:#ddd;"></td>
<%
max = @members.size
@members.each do |mem_info|
pos = mem_info[0]
user = mem_info[1]
%>
<td align="center">
<%if User.current.allowed_to?(:edit_work_time_total, @project) then%>
<a href="#"
onclick="JavaScript:
member_pos(
'<%=url_for(@link_params)%>',
<%=user.id%>,
<%=pos%>,
<%=max%>);
return false;">
<%=pos%>
</a>
<%end%>
<div style="top:2px;width:56px;font-size:10px;">
<%= link_to(user, @link_params.merge(:action=>"show", :user=>user.id))%>
</div>
</td>
<%
end
%>
</tr>
<tr>
<td style="background:#ddd;">
</td>
<td style="background:#ddd;text-align:right;">
<%=sprintf('%1.2f', @total_cost)%>
</td>
<%
#---------------------------------------各人の合計を表示
@members.each do |mem_info|
user=mem_info[1]
%>
<td style="background:#ddd;text-align:right;">
<%= (@member_cost.key?(user.id) && @member_cost[user.id] !=0 ) ? sprintf('%1.2f', @member_cost[user.id]) : " "%>
</td>
<%
end
%>
</tr>
<%
prjs = WtProjectOrders.where("uid=-1").order("dsp_pos").all
tickets = WtTicketRelay.order("position").all
tic_max = tickets.size
#-------------------------------------- チケット行のループ
prjs.each do |po|
dsp_prj = po.dsp_prj
dsp_pos = po.dsp_pos
next unless @r_prj_cost.key?(dsp_prj) # 値の無いプロジェクトはパス
next unless @r_prj_cost[dsp_prj].key?(-1) # 値の無いプロジェクトはパス
next if @r_prj_cost[dsp_prj][-1] == 0 # 値の無いプロジェクトはスパ
prj =Project.find(dsp_prj)
%>
<tr style="background:#000;color:#fff;">
<td>
<%if User.current.allowed_to?(:edit_work_time_total, @project) then%>
<a href="#"
style="color:#8ff;"
onclick="JavaScript:
prj_pos(
'<%=url_for(@link_params)%>',
<%=dsp_prj%>,
<%=dsp_pos%>,
<%=prjs.size%>);
return false;">
<%=dsp_pos%>:
</a>
<%end%>
<%=prj.name%>
</td>
<td style="text-align:right;"> <%=sprintf('%1.2f', (@r_prj_cost[dsp_prj])[-1])%> </td>
<%
@members.each do |mem_info|
user=mem_info[1]
uid=user.id
%>
<td style="text-align:right;">
<%= @r_prj_cost[dsp_prj].key?(uid) ? sprintf('%1.2f', (@r_prj_cost[dsp_prj])[uid]) : " "%>
</td>
<%
end
%>
</tr>
<%
tickets.each do |tic|
issue_id = tic.issue_id
next unless @r_issue_cost.key?(issue_id) # 値の無いチケットはパス
next unless @r_issue_cost[issue_id].key?(-1) # 値の無いチケットはパス
next if @r_issue_cost[issue_id][-1] == 0 # 値の無いチケットはパス
issue = Issue.find_by_id(issue_id)
next if issue.nil? # チケットが削除されていたらパス
next if issue.project_id != dsp_prj # このプロジェクトに表示するチケットでない場合はパス
%>
<tr>
<td>
<%if User.current.allowed_to?(:edit_work_time_total, @project) then%>
<a href="#"
onclick="JavaScript:
ticket_pos(
'<%=url_for(@link_params)%>',
<%=issue_id%>,
<%=tic.position%>,
<%=tic_max%>);
return false;">
<%=tic.position%>
</a>
<%end%>
<%= link_to( wk_pretty_issue_name(issue), {:controller=>"issues", :action=>"show", :id=>issue.id}, :popup=>true) %>
<%= print_issue_cost(issue) %>
</td>
<td style="background:#ddd;text-align:right;">
<%=sprintf('%1.2f', (@r_issue_cost[issue_id])[-1])%>
</td>
<%
@members.each do |mem_info|
user=mem_info[1]
%>
<td style="text-align:right;">
<% if @r_issue_cost.key?(issue_id) && @r_issue_cost[issue_id].key?(user.id) then %>
<%= sprintf('%1.2f', (@r_issue_cost[issue_id])[user.id]) %>
<%else%>
&nbsp;
<%end%>
</td>
<%
end
%>
</tr>
<%
end
end
if @r_prj_cost.has_key?(-1) then
%>
<tr style="background:#000;color:#fff;">
<td>private</td>
<td style="text-align:right;"> <%=sprintf('%1.2f', (@r_prj_cost[-1])[-1])%> </td>
<%
@members.each do |mem_info|
user=mem_info[1]
uid=user.id
%>
<td style="text-align:right;">
<%= @r_prj_cost[-1].key?(uid) ? sprintf('%1.2f', (@r_prj_cost[-1])[uid]) : " "%>
</td>
<%end%>
</tr>
<%end%>
</table>
<input type="button"
onclick="location.href='<%=url_for(@link_params.merge(:action=>"relay_total_data"))%>'"
value="<%=l(:wt_data_download)%>"
/>
<input type="button"
onclick="location.href='<%=url_for(@link_params.merge(:action=>"relay_total_data_with_act"))%>'"
value="<%=l(:wt_data_download_with_act)%>"
/>
<div style="text-align:right;">
<%= render :partial=>'select_project' %> <br/>
[<%= link_to(l(:wt_each_member_report), @link_params.merge(:action=>"show")) %>]
[<%= link_to(l(:wt_edit_relay), @link_params.merge(:action=>"edit_relay")) %>]
[<%= link_to(l(:wt_raw_total), @link_params.merge(:action=>"total")) %>]
</div>
<%=javascript_include_tag "work_time", :plugin=>'redmine_work_time' %>
<%=stylesheet_link_tag 'work_time', :plugin => 'redmine_work_time' %>
<%= @message.html_safe %>
<div class="contextual">
<%= render :partial=>'select_project' %>
<%if User.current.allowed_to?(:view_work_time_other_member, @project) then%>
<%= render :partial=>'select_user', :locals=>{:link_params=>@link_params} %>
<%= link_to(l(:wt_relay_total), @link_params.merge(:action=>"relay_total")) %>
<%end%>
<%if User.current.admin then%>
<%if WtHolidays.where(["holiday=:h and deleted_on is null",{:h=>@this_date}]).all.size == 0 then %>
<input type="button"
onclick="location.href='<%=url_for(@link_params.merge(:set_holiday=>@this_date))%>'"
value="<%=l(:wt_set_holiday)%>"
/>
<%else%>
<input type="button"
onclick="location.href='<%=url_for(@link_params.merge(:del_holiday=>@this_date))%>'"
value="<%=l(:wt_del_holiday)%>"
/>
<%end%>
<%end%>
</div>
<%= render :partial=>'user_month_table' %>
<br/>
<hr/>
<%= form_tag @link_params do %>
<h2>
<%=l(:wt_daily_report)%>
<%=@this_date.strftime("%Y-%m-%d")%>
</h2>
<%= hidden_field_tag('year', @this_date.year) %>
<%= hidden_field_tag('month', @this_date.month) %>
<%= hidden_field_tag('day', @this_date.day) %>
<%= hidden_field_tag('user', @this_uid) %>
<%= hidden_field_tag('prj', @restrict_project) %>
<table style="background: #eeeeee;"><tr><td>
<table style="display:inline-block; border:0;">
<tr>
<td><%=l(:wt_legend)%>:</td>
<td class='wt_iss_default' width='100px' align='center'><%=l(:wt_style_default)%></td>
<td class='wt_iss_assigned' width='100px' align='center'><%=l(:wt_style_assigned)%></td>
<td class='wt_iss_worked' width='100px' align='center'><%=l(:wt_style_worked)%></td>
<td class='wt_iss_assigned_worked' width='100px' align='center'><%=l(:wt_style__assigned_worked)%></td>
<td class='wt_iss_overdue' width='100px' align='center'><%=l(:wt_style_overdue)%>
<td class='wt_iss_assigned_overdue' width='100px' align='center'><%=l(:wt_style_assigned_overdue)%>
</td><td class='wt_iss_overdue_worked' width='100px' align='center'><%=l(:wt_style_overdue_worked)%></td>
<td class='wt_iss_assigned_overdue_worked' width='100px' align='center'><%=l(:wt_style_assigned_overdue_worked)%></td>
</tr>
</table>
</td></tr></table>
<%= render :partial=>'user_day_table' %>
<%if @this_uid==@crnt_uid || User.current.allowed_to?(:edit_work_time_other_member, @project) %>
<%= submit_tag l(:wt_update) %>
&#58;
<input type="button"
onclick="location.href='<%=url_for(@link_params.merge(:ticket_del=>"closed"))%>'"
value="<%=l(:wt_delete_closed_tickets)%>"
/>
<div id="add_ticket_area" style="display: inline-block;_display: inline;">
<input type="button"
onclick="jQuery.ajax({
url: '<%=url_for(:action=>"ajax_add_tickets_input")%>',
data:{asynchronous:true, method:'get'},
success: function(response){
jQuery('#add_ticket_area').replaceWith(response);
}
});
return false;"
value="<%=l(:wt_add_ticket)%>"
/>
</div>
<%end%>
<%#------------------------- Legend for the daily table%>
<br/>
<br/>
<hr/>
<h2 id="memo">
<%=link_to(@this_date.strftime("%Y-%m-%d")+'('+@wday_name[@this_date.wday]+') '+@this_user.to_s,
@link_params.merge(:anchor=>"memo"))
%>
</h2>
<%#------------------------------------------- Wiki表示#%>
<div id="memo-wiki">
<%
memo=WtDailyMemo.where(["day=:d and user_id=:u",{:d=>@this_date,:u=>@this_uid}]).first
if memo then # この日のメモがある場合
%>
<div class="wiki wt_memo_wiki_block">
<%=textilizable(memo.description) %>
<div style="text-align:right;">
(update:<%=memo.updated_on.localtime.strftime("%Y-%m-%d %H:%M")%>)
</div>
</div>
<%end%>
<%
memo=WtDailyMemo.where(["day<:d and user_id=:u",{:d=>@this_date,:u=>@this_uid}]).order("day DESC").first
if memo then
d = memo.day
%>
[<%=link_to(l(:wt_pre_memo), @link_params.merge(:anchor=>"memo", :day=>d.day, :month=>d.month, :year=>d.year))%>]
<%end%>
<%if @this_uid==@crnt_uid then%>
[<a href="#"
onclick="jQuery.ajax({
url: '<%=url_for(@link_params.merge(:action=>"ajax_memo_edit"))%>',
data:{asynchronous:true, method:'get'},
success: function(response){
jQuery('#memo-wiki').html(response);
}
});
return false;">
<%=l(:wt_edit_memo)%>
</a>]
<%end%>
<%
memo=WtDailyMemo.where(["day>:d and user_id=:u",{:d=>@this_date,:u=>@this_uid}]).order("day").first
if memo then
d = memo.day
%>
[<%= link_to(l(:wt_next_memo), @link_params.merge(:anchor=>"memo", :day=>d.day, :month=>d.month, :year=>d.year))%>]
<%end%>
</div>
<br/>
<%if User.current.allowed_to?(:view_work_time_other_member, @project) then%>
<%= render :partial=>'select_user', :locals=>{:link_params=>@link_params.merge(:anchor=>"memo")} %>
<%end%>
<%end%>
<%=javascript_include_tag "work_time", :plugin=>'redmine_work_time' %>
<%=stylesheet_link_tag 'work_time', :plugin => 'redmine_work_time' %>
<%= @message.html_safe %>
<div style="text-align:right;">
<%= render :partial=>'select_project' %> <br/>
[<%= link_to(l(:wt_each_member_report), @link_params.merge(:action=>"show")) %>]
[<%= link_to(l(:wt_edit_relay), @link_params.merge(:action=>"edit_relay")) %>]
[<%= link_to(l(:wt_relay_total), @link_params.merge(:action=>"relay_total")) %>]
</div>
<h2>
<%=l(:wt_raw_total)%>
<%=link_to("<<", @link_params.merge(:day=>@last_month.day, :month=>@last_month.month, :year=>@last_month.year))%>
<%= @first_date.strftime("%Y/%m/%d") %> - <%= @last_date.strftime("%Y/%m/%d") %>
<%=link_to(">>", @link_params.merge(:day=>@next_month.day, :month=>@next_month.month, :year=>@next_month.year))%>
</h2>
<%
if !User.current.allowed_to?(:view_work_time_other_member, @project) then
return
end
############################################## 集計表 #####################
%>
<table border="1">
<tr valign="top">
<td>
</td>
<td style="background:#ddd;"></td>
<%
max = @members.size
@members.each do |mem_info|
pos=mem_info[0]
user=mem_info[1]
%>
<td align="center">
<%if User.current.allowed_to?(:edit_work_time_total, @project) then%>
<a href="#"
onclick="JavaScript:
member_pos(
'<%=url_for(@link_params)%>',
<%=user.id%>,
<%=pos%>,
<%=max%>);
return false;">
<%=pos%>
</a>
<%end%>
<div style="top:2px;width:56px;font-size:10px;">
<%= link_to(user, @link_params.merge(:action=>"show", :user=>user.id))%>
</div>
</td>
<%
end
%>
</tr>
<tr>
<td style="background:#ddd;">
</td>
<td style="background:#ddd;text-align:right;">
<%=sprintf('%1.2f', @total_cost)%>
</td>
<%
#---------------------------------------各人の合計を表示
@members.each do |mem_info|
user=mem_info[1]
%>
<td style="background:#ddd;text-align:right;">
<%= (@member_cost.key?(user.id) && @member_cost[user.id] !=0 ) ? sprintf('%1.2f', @member_cost[user.id]) : " "%>
</td>
<%
end
%>
</tr>
<%
prjs = WtProjectOrders.where("uid=-1").order("dsp_pos").all
tickets = WtTicketRelay.order("position").all
tic_max = tickets.size
#-------------------------------------- チケット行のループ
prjs.each do |po|
dsp_prj = po.dsp_prj
dsp_pos = po.dsp_pos
next unless @prj_cost.key?(dsp_prj) # 値の無いプロジェクトはパス
next unless @prj_cost[dsp_prj].key?(-1) # 値の無いプロジェクトはパス
next if @prj_cost[dsp_prj][-1] == 0 # 値の無いプロジェクトはスパ
prj =Project.find(dsp_prj)
%>
<tr style="background:#000;color:#fff;">
<td>
<%if User.current.allowed_to?(:edit_work_time_total, @project) then%>
<a href="#"
style="color:#8ff;"
onclick="JavaScript:
prj_pos(
'<%=url_for(@link_params)%>',
<%=dsp_prj%>,
<%=dsp_pos%>,
<%=prjs.size%>);
return false;">
<%=dsp_pos%>:
</a>
<%end%>
<%=prj.name%>
</td>
<td style="text-align:right;"> <%=sprintf('%1.2f', (@prj_cost[dsp_prj])[-1])%> </td>
<%
@members.each do |mem_info|
user=mem_info[1]
uid=user.id
%>
<td style="text-align:right;">
<%= @prj_cost[dsp_prj].key?(uid) ? sprintf('%1.2f', (@prj_cost[dsp_prj])[uid]) : " "%>
</td>
<%
end
%>
</tr>
<%
tickets.each do |tic|
issue_id = tic.issue_id
next unless @issue_cost.key?(issue_id) # 値の無いチケットはパス
next unless @issue_cost[issue_id].key?(-1) # 値の無いチケットはパス
next if @issue_cost[issue_id][-1] == 0 # 値の無いチケットはパス
issue = Issue.find_by_id(issue_id)
next if issue.nil? # チケットが削除されていたらパス
next if issue.project_id != dsp_prj # このプロジェクトに表示するチケットでない場合はパス
%>
<tr>
<td>
<%if User.current.allowed_to?(:edit_work_time_total, @project) then%>
<a href="#"
onclick="JavaScript:
ticket_pos(
'<%=url_for(@link_params)%>',
<%=issue_id%>,
<%=tic.position%>,
<%=tic_max%>);
return false;">
<%=tic.position%>
</a>
<%end%>
<%= link_to(wk_pretty_issue_name(issue), {:controller=>"issues", :action=>"show", :id=>issue.id}, :popup=>true) %>
<%= print_issue_cost(issue) %>
</td>
<td style="background:#ddd;text-align:right;">
<%=sprintf('%1.2f', (@issue_cost[issue_id])[-1])%>
</td>
<%
@members.each do |mem_info|
user=mem_info[1]
%>
<td style="text-align:right;">
<% if @issue_cost.key?(issue_id) && @issue_cost[issue_id].key?(user.id) then %>
<%= sprintf('%1.2f', (@issue_cost[issue_id])[user.id]) %>
<%else%>
&nbsp;
<%end%>
</td>
<%
end
%>
</tr>
<%
end
end
if @prj_cost.has_key?(-1) then
%>
<tr style="background:#000;color:#fff;">
<td>private</td>
<td style="text-align:right;"> <%=sprintf('%1.2f', (@prj_cost[-1])[-1])%> </td>
<%
@members.each do |mem_info|
user=mem_info[1]
uid=user.id
%>
<td style="text-align:right;">
<%= @prj_cost[-1].key?(uid) ? sprintf('%1.2f', (@prj_cost[-1])[uid]) : " "%>
</td>
<%end%>
</tr>
<%end%>
</table>
<input type="button"
onclick="location.href='<%=url_for(@link_params.merge(:action=>"total_data"))%>'"
value="<%=l(:wt_data_download)%>"
/>
<input type="button"
onclick="location.href='<%=url_for(@link_params.merge(:action=>"total_data_with_act"))%>'"
value="<%=l(:wt_data_download_with_act)%>"
/>
<div align="right">
<%= render :partial=>'select_project' %> <br/>
[<%= link_to(l(:wt_each_member_report), @link_params.merge(:action=>"show")) %>]
[<%= link_to(l(:wt_edit_relay), @link_params.merge(:action=>"edit_relay")) %>]
[<%= link_to(l(:wt_relay_total), @link_params.merge(:action=>"relay_total")) %>]
</div>
function ticket_pos(url, issue, pos, max)
{
var new_pos = prompt("Destination No.", pos);
if(new_pos != null) {
if((new_pos>=1) && (new_pos<=max))
location.replace(url+"&ticket_pos="+issue+"_"+new_pos);
else
alert("Out of range!");
}
}
function prj_pos(url, prj, pos, max)
{
var new_pos = prompt("Destination No.", pos);
if(new_pos != null) {
if((new_pos>=1) && (new_pos<=max))
location.replace(url+"&prj_pos="+prj+"_"+new_pos);
else
alert("Out of range!");
}
}
function member_pos(url, user_id, pos, max)
{
var new_pos = prompt("Distination No.", pos);
if(new_pos != null) {
if((new_pos>=1) && (new_pos<=max))
location.replace(url+"&member_pos="+user_id+"_"+new_pos);
else
alert("Out of rnage!");
}
}
function set_ticket_relay_by_issue_relation(ajax_url) {
$('[id^=ticket_relay_]').each(function(){
var issue_id = $(this).attr('id').replace(/.*([^_]+)$/, "$1");
jQuery.ajax({
url: ajax_url + '&issue_id=' + issue_id,
data:{asynchronous:true, method:'get'},
success: function(response) {
jQuery('#ticket_relay_'+issue_id).html(response);
}
});
})
}
function input_done_ratio(ajax_url, issue_id) {
jQuery.ajax({
url: ajax_url + "&issue_id=" + issue_id,
data: {asynchronous: true, method: 'get'},
success: function (response) {
jQuery('[name="done_ratio'+ issue_id+'"]:first').replaceWith(response);
}
});
}
function update_done_ratio(ajax_url, issue_id) {
var done_ratio = $('#input_ratio'+issue_id).val();
jQuery.ajax({
url:ajax_url+"&issue_id="+issue_id+"&done_ratio="+done_ratio,
data:{asynchronous:true, method:'get'},
success:function(response){
jQuery('[name="done_ratio'+ issue_id+'"]').replaceWith(response);
}
});
}
function checkEnter(e)
{
if (!e) var e = window.event;
if(e.keyCode == 13)
return true;
else
return false;
}
//------------------------------------------------- for show.html.erb
var add_ticket_count = 1;
function dup_ticket(ajax_url, insert_pos, id)
{
jQuery.ajax({
url:ajax_url+"&add_issue="+id+"&count="+add_ticket_count,
data:{asynchronous:true, method:'get'},
success:function(response){
jQuery('#'+insert_pos).after(response);
}
});
add_ticket_count ++;
}
function tickets_insert(ajax_url, tickets)
{
for(i=0; i<tickets.length;i++) {
jQuery.ajax({
url:ajax_url+"&add_issue="+tickets[i]+"&count="+add_ticket_count,
data:{asynchronous:true, method:'get'},
success:function(response){
jQuery('#time_input_table_bottom').before(response);
}
});
add_ticket_count ++;
}
}
function tickets_inputed(ajax_url)
{
var vals = document.getElementById("input_ids").value;
var tickets = vals.split(',');
tickets_insert(ajax_url, tickets);
}
function tickets_selected(ajax_url, issue_id)
{
var tickets = [issue_id];
tickets_insert(ajax_url, tickets);
}
function tickets_checked(ajax_url)
{
var $checked = $('[name="ticket_select_check"]:checked');
var tickets = $checked.map(function(i,e){return $(this).val()});
tickets_insert(ajax_url, tickets);
}
function statusUpdateOnDailyTable(name) {
obj = document.getElementsByName(name)[0];
obj.style.backgroundColor = '#cfc';
index = obj.selectedIndex;
v = obj.options[index].value;
obj.options[index].value = 'M'+v;
}
//------------- for user_day_table.html.erb
function sumDayTimes() {
var total=0;
var dayInputs;
// List all Input elemnets of the page
dayInputs = document.getElementsByTagName("input");
for (var i=0; i<dayInputs.length; i++) {
// Consider only those with an id containing the strings 'time_entry' and 'hours'
if ((dayInputs[i].id.indexOf("time_entry") >= 0) && (dayInputs[i].id.indexOf("hours") >= 0)) {
var val = dayInputs[i].value;
if (val) {
var vals = val.match(/^([\d\.]+)$/);
if (vals) {
// add the number to the total if it is a valid number
total = total + parseFloat(vals[1]);
}
else {
vals = val.match(/^(\d+)m$/);
if(vals) {
total = total + parseFloat(vals[1])/60;
}
else {
vals = val.match(/^(\d+):(\d+)$/);
if(vals) {
total = total + parseFloat(vals[1]) + parseFloat(vals[2])/60;
}
}
}
}
}
}
// Set the total value to the new number, changing the style to indicate
// it is not saved, and adding the saved value as a flyover indication
var originalValue;
document.getElementById("currentTotal").innerHTML = total.toFixed(2);
document.getElementById("currentTotal").style = 'color:#FF0000;';
return true;
}
h1 {
margin-top: 0;
margin-bottom: 0
}
h2 {
margin-top: 0;
margin-bottom: 0
}
div.wt_modified {
background: #cfc;
}
div.wt_error {
background: #faa;
}
div.wt_memo_wiki_block {
background: #ffb;
}
div.wt_add_ticket_block {
background: #ddd;
border: 1px solid black;
}
/* use day table */
td.wt_iss_default {
background: #fff;
}
td.wt_iss_worked {
background: #cfc;
}
td.wt_iss_overdue {
background: #ffc;
}
td.wt_iss_overdue_worked {
background: #ccc;
}
td.wt_iss_assigned {
background: #cff;
}
td.wt_iss_assigned_worked {
background: #ccf;
}
td.wt_iss_assigned_overdue {
background: #fcc;
}
td.wt_iss_assigned_overdue_worked {
background: #fcf;
}
ca:
work_time: "WorkTime"
wt_update: "Update"
wt_month_names: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec"
wt_week_day_names: "Sun,Mon,Tue,Wed,Thu,Fri,Sat"
wt_monthly_report: "Monthly Report"
wt_daily_report: "Daily Report"
wt_each_member_report: "Member Report"
wt_raw_total: "Monthly Report(not relayed)"
wt_relay_total: "Monthly Report(relayed)"
wt_edit_relay: "Ticket Relay Editor"
wt_ticket: "Ticket"
wt_add_ticket: "Add ticket"
wt_no_permission: "No permission"
wt_loop_relay: "Ticket relation looped"
wt_set_holiday: "set holiday on this date"
wt_del_holiday: "del holiday on this date"
wt_apply_checked: "apply all checked"
wt_select_project: "Restrict project..."
wt_select_user: "Select user..."
wt_edit_memo: "Edit memo"
wt_pre_memo: "pre. memo"
wt_next_memo: "next memo"
wt_data_list: "Data list"
wt_input_ticket_numbers: "or input ticket numbers"
wt_delete_closed_tickets: "delete closed tickets"
wt_data_download: "data download"
wt_data_download_with_act: "data download(each activity)"
wt_opt_disp_ticket_with_closed: "[display closed ticket]"
wt_opt_disp_ticket_opened_only: "[display opened ticket only]"
wt_opt_disp_ticket_with_other_member: "[display other members ticket]"
wt_opt_disp_ticket_mine_only: "[display my ticket only]"
wt_bulkupdate_relations: "bulkupdate to parent"
permission_view_work_time_tab: "View Work time tab"
permission_view_work_time_other_member: "View other members' work time"
permission_edit_work_time_total: "Edit work time totals"
permission_edit_work_time_other_member: "Edit other members' work time"
wt_saved_value: "Saved timed: "
wt_legend: "Legend"
wt_style_default: "By default"
wt_style_assigned: "Assigned"
wt_style_worked: "Worked on"
wt_style__assigned_worked: "Assigned and worked on"
wt_style_overdue: "Overdue"
wt_style_assigned_overdue: "Assigned and overdue"
wt_style_overdue_worked: "Overdue and worked on"
wt_style_assigned_overdue_worked: "Assigned, overdue and worked on"
wt_account_start_day: "Company start day"
de:
work_time: "Zeiterfassung"
wt_update: "Aktualisieren"
wt_month_names: "Jan,Feb,Mar,Apr,Mai,Jun,Jul,Aug,Sep,Okt,Nov,Dez"
wt_week_day_names: "So,Mo,Di,Mi,Do,Fr,Sa"
wt_monthly_report: "Monatsbericht"
wt_daily_report: "Tagesbericht"
wt_each_member_report: "Bericht pro Benutzer"
wt_raw_total: "Monatsbericht (ohne Fortschreibung)"
wt_edit_relay: "Aufwände fortschreiben"
wt_relay_total: "Monatsbericht"
wt_ticket: "Ticket"
wt_add_ticket: "Ticket hinzufügen"
wt_no_permission: "Keine Berechtigung"
wt_loop_relay: "Zyklus bei der Aufwandsfortschreibung!"
wt_set_holiday: "Tag zum Urlaubs-/Feiertag machen"
wt_del_holiday: "Tag zum Arbeitstag machen"
wt_apply_checked: "Alle ausgewählten Einträge übernehmen"
wt_select_project: "Projektauswahl"
wt_select_user: "Benutzerauswahl"
wt_edit_memo: "Memo ändern"
wt_pre_memo: "Vorheriges Memo"
wt_next_memo: "Nächstes Memo"
wt_data_list: "Datenliste"
wt_input_ticket_numbers: "oder Ticket-Nr. direkt eingeben"
wt_delete_closed_tickets: "delete closed tickets"
wt_data_download: "Daten laden"
wt_data_download_with_act: "Daten laden(each activity)"
wt_opt_disp_ticket_with_closed: "[display closed ticket]"
wt_opt_disp_ticket_opened_only: "[display opened ticket only]"
wt_opt_disp_ticket_with_other_member: "[display other members ticket]"
wt_opt_disp_ticket_mine_only: "[display my ticket only]"
wt_bulkupdate_relations: "bulkupdate to parent"
permission_view_work_time_tab: "View Work time tab"
permission_view_work_time_other_member: "View other members' work time"
permission_edit_work_time_total: "Edit work time totals"
permission_edit_work_time_other_member: "Edit other members' work time"
wt_saved_value: "Saved timed: "
wt_legend: "Legend"
wt_style_default: "By default"
wt_style_assigned: "Assigned"
wt_style_worked: "Worked on"
wt_style__assigned_worked: "Assigned and worked on"
wt_style_overdue: "Overdue"
wt_style_assigned_overdue: "Assigned and overdue"
wt_style_overdue_worked: "Overdue and worked on"
wt_style_assigned_overdue_worked: "Assigned, overdue and worked on"
wt_account_start_day: "Company start day"
en:
work_time: "WorkTime"
wt_update: "Update"
wt_month_names: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec"
wt_week_day_names: "Sun,Mon,Tue,Wed,Thu,Fri,Sat"
wt_monthly_report: "Monthly Report"
wt_daily_report: "Daily Report"
wt_each_member_report: "Member Report"
wt_raw_total: "Monthly Report(not relayed)"
wt_relay_total: "Monthly Report(relayed)"
wt_edit_relay: "Ticket Relay Editor"
wt_ticket: "Ticket"
wt_add_ticket: "Add ticket"
wt_no_permission: "No permission"
wt_loop_relay: "Ticket relation looped"
wt_set_holiday: "set holiday on this date"
wt_del_holiday: "del holiday on this date"
wt_apply_checked: "apply all checked"
wt_select_project: "Restrict project..."
wt_select_user: "Select user..."
wt_edit_memo: "Edit memo"
wt_pre_memo: "pre. memo"
wt_next_memo: "next memo"
wt_data_list: "Data list"
wt_input_ticket_numbers: "or input ticket numbers"
wt_delete_closed_tickets: "delete closed tickets"
wt_data_download: "data download"
wt_data_download_with_act: "data download(each activity)"
wt_opt_disp_ticket_with_closed: "[display closed ticket]"
wt_opt_disp_ticket_opened_only: "[display opened ticket only]"
wt_opt_disp_ticket_with_other_member: "[display other members ticket]"
wt_opt_disp_ticket_mine_only: "[display my ticket only]"
wt_bulkupdate_relations: "bulkupdate to parent"
permission_view_work_time_tab: "View Work time tab"
permission_view_work_time_other_member: "View other members' work time"
permission_edit_work_time_total: "Edit work time totals"
permission_edit_work_time_other_member: "Edit other members' work time"
wt_saved_value: "Saved timed: "
wt_legend: "Legend"
wt_style_default: "By default"
wt_style_assigned: "Assigned"
wt_style_worked: "Worked on"
wt_style__assigned_worked: "Assigned and worked on"
wt_style_overdue: "Overdue"
wt_style_assigned_overdue: "Assigned and overdue"
wt_style_overdue_worked: "Overdue and worked on"
wt_style_assigned_overdue_worked: "Assigned, overdue and worked on"
wt_account_start_day: "Company start day"
es:
work_time: "Agenda"
wt_update: "Actualizar"
wt_month_names: "Ene,Feb,Mar,Abr,May,Jun,Jul,Ago,Sep,Oct,Nov,Dic"
wt_week_day_names: "Dom,Lun,Mar,Mie,Jue,Vie,Sab"
wt_monthly_report: "Informe mensual"
wt_daily_report: "Informe diario"
wt_each_member_report: "Informe de miembro"
wt_raw_total: "Informe mensual(no se retransmite)"
wt_edit_relay: "Editor transmisión de peticiones"
wt_relay_total: "Informe mensual de peticiones"
wt_ticket: "Petición"
wt_add_ticket: "Añade petición"
wt_no_permission: "Sin permiso"
wt_loop_relay: "Transmisión de petición en bucle"
wt_set_holiday: "Establece vacaciones en esta fecha"
wt_del_holiday: "Elimina vacaciones en esta fecha"
wt_apply_checked: "Aplica a todos los seleccionados"
wt_select_project: "Seleccione proyecto..."
wt_select_user: "Seleccione usuario..."
wt_edit_memo: "Edita memorandum"
wt_pre_memo: "Anterior memorandum"
wt_next_memo: "Siguiente memorandum"
wt_data_list: "Lista de datos"
wt_input_ticket_numbers: "o introduzca numero de petición"
wt_delete_closed_tickets: "delete closed tickets"
wt_data_download: "data download"
wt_data_download_with_act: "data download(each activity)"
wt_opt_disp_ticket_with_closed: "[display closed ticket]"
wt_opt_disp_ticket_opened_only: "[display opened ticket only]"
wt_opt_disp_ticket_with_other_member: "[display other members ticket]"
wt_opt_disp_ticket_mine_only: "[display my ticket only]"
wt_bulkupdate_relations: "bulkupdate to parent"
permission_view_work_time_tab: "View Work time tab"
permission_view_work_time_other_member: "View other members' work time"
permission_edit_work_time_total: "Edit work time totals"
permission_edit_work_time_other_member: "Edit other members' work time"
wt_saved_value: "Saved timed: "
wt_legend: "Legend"
wt_style_default: "By default"
wt_style_assigned: "Assigned"
wt_style_worked: "Worked on"
wt_style__assigned_worked: "Assigned and worked on"
wt_style_overdue: "Overdue"
wt_style_assigned_overdue: "Assigned and overdue"
wt_style_overdue_worked: "Overdue and worked on"
wt_style_assigned_overdue_worked: "Assigned, overdue and worked on"
wt_account_start_day: "Company start day"
fr:
work_time: "Temps de travail"
wt_update: "Mettre à jour"
wt_month_names: "Jan,Fév,Mar,Avr,Mai,Juin,Juil,Août,Sep,Oct,Nov,Déc"
wt_week_day_names: "Dim,Lun,Mar,Mer,Jeu,Ven,Sam"
wt_monthly_report: "Rapport mensuel"
wt_daily_report: "Rapport journalier"
wt_each_member_report: "Rapport utilisateur"
wt_raw_total: "Rapport mensuel(non relayé)"
wt_relay_total: "Rapport mensuel (relayé)"
wt_edit_relay: "Ticket Relay Editor"
wt_ticket: "Demande"
wt_add_ticket: "Ajouter une demande"
wt_no_permission: "Vous n'avez pas les droits"
wt_loop_relay: "Boucle infinie sur une demande"
wt_set_holiday: "Placer cette date en jour férié"
wt_del_holiday: "Retirer cette date des jours fériés"
wt_apply_checked: "Appliquer pour toutes les cases cochées"
wt_select_project: "Restreindre à un projet"
wt_select_user: "Choisir un utilisateur"
wt_edit_memo: "Éditer la note"
wt_pre_memo: "Note précédente"
wt_next_memo: "Note suivante"
wt_data_list: "Liste brute"
wt_input_ticket_numbers: "ou entrez le numéro de la demande"
wt_delete_closed_tickets: "Supprimer les demandes fermées"
wt_data_download: "Téléchargement des données"
wt_data_download_with_act: "Téléchargement des données(each activity)"
wt_opt_disp_ticket_with_closed: "[afficher les demandes fermés]"
wt_opt_disp_ticket_opened_only: "[n'afficher que les demandes ouvertes]"
wt_opt_disp_ticket_with_other_member: "[afficher les demandes des autres membres]"
wt_opt_disp_ticket_mine_only: "[n'afficher que mes demandes]"
wt_bulkupdate_relations: "mise à jour en bloc du parent"
permission_view_work_time_tab: "Afficher l'onglet Temps de travail"
permission_view_work_time_other_member: "Afficher les temps des autres membres"
permission_edit_work_time_total: "Modifier les totaux de temps de travail"
permission_edit_work_time_other_member: "Modifier les temps des autres membres"
wt_saved_value: "Temps sauvegardé : "
wt_legend: "Légende"
wt_style_default: "Par défaut"
wt_style_assigned: "Affecté"
wt_style_worked: "Travail en cours"
wt_style__assigned_worked: "Affecté et travail en cours"
wt_style_overdue: "En retard"
wt_style_assigned_overdue: "Affecté et en retard"
wt_style_overdue_worked: "En retard et travail en cours"
wt_style_assigned_overdue_worked: "Affecté, en retard et travail en cours"
wt_account_start_day: "Company start day"
it:
work_time: "Tempo di lavoro"
wt_update: "Aggiorna"
wt_month_names: "Gen,Feb,Mar,Apr,Mag,Giu,Lug,Ago,Set,Ott,Nov,Dic"
wt_week_day_names: "Dom,Lun,Mar,Mer,Gio,Ven,Sab"
wt_monthly_report: "Report Mensile"
wt_daily_report: "Report Giornaliero"
wt_each_member_report: "Report Utente"
wt_raw_total: "Report Mensile (not relayed)"
wt_edit_relay: "Editor segnalazioni trasmesse"
wt_relay_total: "Report Mensile Segnalazioni Relayed"
wt_ticket: "Segnalazione"
wt_add_ticket: "Aggiungi segnalazione"
wt_no_permission: "Non autorizzato"
wt_loop_relay: "Ticket relation looped"
wt_set_holiday: "Imposta giorno come festivo"
wt_del_holiday: "Canc giorno come festivo"
wt_apply_checked: "Applica a selezionati"
wt_select_project: "Seleziona progetto..."
wt_select_user: "Seleziona utente..."
wt_edit_memo: "Modifica nota"
wt_pre_memo: "Nota precedente"
wt_next_memo: "Prossima nota"
wt_data_list: "Lista Dati"
wt_input_ticket_numbers: "o inserisci i numeri delle segnalazioni"
wt_delete_closed_tickets: "Elimina segnalazioni chiuse"
wt_data_download: "download di dati"
wt_data_download_with_act: "download di dati(each activity)"
wt_opt_disp_ticket_with_closed: "[mostra segnalazioni chiuse]"
wt_opt_disp_ticket_opened_only: "[mostra solo segnalazioni aperte]"
wt_opt_disp_ticket_with_other_member: "[mostra segnalazioni di altri membri]"
wt_opt_disp_ticket_mine_only: "[mostra solo le mie segnalazioni]"
wt_bulkupdate_relations: "bulkupdate to parent"
permission_view_work_time_tab: "View Work time tab"
permission_view_work_time_other_member: "View other members' work time"
permission_edit_work_time_total: "Edit work time totals"
permission_edit_work_time_other_member: "Edit other members' work time"
wt_saved_value: "Saved timed: "
wt_legend: "Legend"
wt_style_default: "By default"
wt_style_assigned: "Assigned"
wt_style_worked: "Worked on"
wt_style__assigned_worked: "Assigned and worked on"
wt_style_overdue: "Overdue"
wt_style_assigned_overdue: "Assigned and overdue"
wt_style_overdue_worked: "Overdue and worked on"
wt_style_assigned_overdue_worked: "Assigned, overdue and worked on"
wt_account_start_day: "Company start day"
ja:
work_time: "工数"
wt_update: "更新"
wt_month_names: "1,2,3,4,5,6,7,8,9,10,11,12"
wt_week_day_names: "日,月,火,水,木,金,土"
wt_monthly_report: "月間工数表"
wt_daily_report: "日毎工数"
wt_each_member_report: "個人工数集計"
wt_raw_total: "月間集計(付替なし)"
wt_relay_total: "月間集計(付替あり)"
wt_edit_relay: "チケット付替設定"
wt_ticket: "チケット"
wt_add_ticket: "チケット追加"
wt_no_permission: "権限がありません"
wt_loop_relay: "チケット関係がループしています"
wt_set_holiday: "この日を休日に設定"
wt_del_holiday: "この日の休日を解除"
wt_apply_checked: "チェックを適用"
wt_select_project: "プロジェクト限定"
wt_select_user: "ユーザを選択"
wt_edit_memo: "メモを編集"
wt_pre_memo: "前のメモ"
wt_next_memo: "次のメモ"
wt_data_list: "データリスト"
wt_input_ticket_numbers: "またはチケット番号を入力"
wt_delete_closed_tickets: "終了チケット削除"
wt_data_download: "データダウンロード"
wt_data_download_with_act: "活動別データダウンロード"
wt_opt_disp_ticket_with_closed: "[終了したチケットも表示]"
wt_opt_disp_ticket_opened_only: "[オープン中のチケットのみ表示]"
wt_opt_disp_ticket_with_other_member: "[他のメンバーのチケットも表示]"
wt_opt_disp_ticket_mine_only: "[自分のチケットのみ表示]"
wt_bulkupdate_relations: "親チケットへ一括更新"
permission_view_work_time_tab: "工数入力集計対象者"
permission_view_work_time_other_member: "他のメンバーの工数の表示"
permission_edit_work_time_total: "工数集計の設定"
permission_edit_work_time_other_member: "他のメンバーの工数の入力"
wt_saved_value: "保存時間: "
wt_legend: "チケット表示凡例"
wt_style_default: "通常表示"
wt_style_assigned: "担当期間"
wt_style_worked: "書込"
wt_style__assigned_worked: "担当期間,書込"
wt_style_overdue: "期限超過"
wt_style_assigned_overdue: "担当,期限超過"
wt_style_overdue_worked: "期限超過,書込"
wt_style_assigned_overdue_worked: "担当,超過,書込"
wt_account_start_day: "集計開始日"
# Translation by Ki Won Kim (http://xyz37.blog.me, xyz37@naver.com)
ko:
work_time: "작업 시간"
wt_update: "수정"
wt_month_names: "1월,2월,3월,4월,5월,6월,7월,8월,9월,10월,11월,12월"
wt_week_day_names: "일,월,화,수,목,금,토"
wt_monthly_report: "월간 보고"
wt_daily_report: "일간 보고"
wt_each_member_report: "사용자 보고"
wt_raw_total: "월간 보고(연동 없음)"
wt_edit_relay: "티켓 연동 편집기"
wt_relay_total: "연동된 티켓 월간 보고"
wt_ticket: "티켓"
wt_add_ticket: "티켓 추가"
wt_no_permission: "권한 없음"
wt_loop_relay: "티켓 관계가 반복(Looping) 됩니다."
wt_set_holiday: " 날짜를 휴일로 지정"
wt_del_holiday: " 날짜를 휴일에서 제거"
wt_apply_checked: "선택 항목 적용"
wt_select_project: "프로젝트 선택..."
wt_select_user: "사용자 선택..."
wt_edit_memo: "메모 수정"
wt_pre_memo: "이전 메모"
wt_next_memo: "다음 메모"
wt_data_list: "데이터 목록"
wt_input_ticket_numbers: "또는 티켓 번호를 입력하세요."
wt_delete_closed_tickets: "완료된 티켓 삭제"
wt_data_download: "데이터 다운로드"
wt_data_download_with_act: "데이터 다운로드(each activity)"
wt_opt_disp_ticket_with_closed: "[display closed ticket]"
wt_opt_disp_ticket_opened_only: "[display opened ticket only]"
wt_opt_disp_ticket_with_other_member: "[display other members ticket]"
wt_opt_disp_ticket_mine_only: "[display my ticket only]"
wt_bulkupdate_relations: "bulkupdate to parent"
permission_view_work_time_tab: "View Work time tab"
permission_view_work_time_other_member: "View other members' work time"
permission_edit_work_time_total: "Edit work time totals"
permission_edit_work_time_other_member: "Edit other members' work time"
wt_saved_value: "Saved timed: "
wt_legend: "Legend"
wt_style_default: "By default"
wt_style_assigned: "Assigned"
wt_style_worked: "Worked on"
wt_style__assigned_worked: "Assigned and worked on"
wt_style_overdue: "Overdue"
wt_style_assigned_overdue: "Assigned and overdue"
wt_style_overdue_worked: "Overdue and worked on"
wt_style_assigned_overdue_worked: "Assigned, overdue and worked on"
wt_account_start_day: "Company start day"
"no":
work_time: "Arbeidstimer"
wt_update: "Oppdater"
wt_month_names: "Jan,Feb,Mar,Apr,Mai,Jun,Jul,Aug,Sep,Okt,Nov,Des"
wt_week_day_names: "Søn,Man,Tir,Ons,Tor,Fre,Lør"
wt_monthly_report: "Månedsrapport"
wt_daily_report: "Dagsrapport"
wt_each_member_report: "Medlemsrapport"
wt_raw_total: "Månedsrapport (ikke samlet)"
wt_relay_total: "Månedsrapport (samlet)"
wt_edit_relay: "Samle poster"
wt_ticket: "Poster"
wt_add_ticket: "Legg til post"
wt_no_permission: "Ikke tilgang"
wt_loop_relay: "Samlekobling i løkke"
wt_set_holiday: "merk dato som feriedag"
wt_del_holiday: "fjern feriedagmerking dat"
wt_apply_checked: "Legg til valgte poster"
wt_select_project: "Begrens prosjekt..."
wt_select_user: "Velg bruker..."
wt_edit_memo: "Endre notat"
wt_pre_memo: "forr. notat"
wt_next_memo: "neste notat"
wt_data_list: "Data list"
wt_input_ticket_numbers: "eller legg inn saksnummer"
wt_delete_closed_tickets: "Slett lukkede poster"
wt_data_download: "Last ned data"
wt_data_download_with_act: "Last ned data(each activity)"
wt_opt_disp_ticket_with_closed: "[vis lukkede saker]"
wt_opt_disp_ticket_opened_only: "[vis bare åpne saker]"
wt_opt_disp_ticket_with_other_member: "[vis andre brukeres saker]"
wt_opt_disp_ticket_mine_only: "[vis bare mine saker]"
wt_bulkupdate_relations: "Samle alle til sin forelder"
permission_view_work_time_tab: "Vise arbeidstime-fane"
permission_view_work_time_other_member: "Vise andres arbeidstimer"
permission_edit_work_time_total: "Endre oppsummerte arbeidstimer"
permission_edit_work_time_other_member: "Endre andres arbeidstimer"
wt_saved_value: "Lagret timer: "
wt_legend: "Nøkkel"
wt_style_default: "Forvalgt"
wt_style_assigned: "Tildelt"
wt_style_worked: "Jobbet med"
wt_style__assigned_worked: "Tildelt og jobbet med"
wt_style_overdue: "Over tidsfrist"
wt_style_assigned_overdue: "Tildelt og over tidsfrist"
wt_style_overdue_worked: "Over tidsfrist og jobbet med"
wt_style_assigned_overdue_worked: "Tildelt, over tidsfrist og jobbet med"
wt_account_start_day: "Company start day"
po:
work_time: "WorkTime"
wt_update: "Update"
wt_month_names: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec"
wt_week_day_names: "Sun,Mon,Tue,Wed,Thu,Fri,Sat"
wt_monthly_report: "Monthly Report"
wt_daily_report: "Daily Report"
wt_each_member_report: "Member Report"
wt_raw_total: "Monthly Report(not relayed)"
wt_relay_total: "Rapport mensuel (relayed)"
wt_edit_relay: "Ticket Relay Editor"
wt_ticket: "Ticket"
wt_add_ticket: "Add ticket"
wt_no_permission: "No permission"
wt_loop_relay: "Ticket relation looped"
wt_set_holiday: "set holiday on this date"
wt_del_holiday: "del holiday on this date"
wt_apply_checked: "apply all checked"
wt_select_project: "Restrict project..."
wt_select_user: "Select user..."
wt_edit_memo: "Edit memo"
wt_pre_memo: "pre. memo"
wt_next_memo: "next memo"
wt_data_list: "Data list"
wt_input_ticket_numbers: "or input ticket numbers"
wt_delete_closed_tickets: "delete closed tickets"
wt_data_download: "data download"
wt_data_download_with_act: "data download(each activity)"
wt_opt_disp_ticket_with_closed: "[display closed ticket]"
wt_opt_disp_ticket_opened_only: "[display opened ticket only]"
wt_opt_disp_ticket_with_other_member: "[display other members ticket]"
wt_opt_disp_ticket_mine_only: "[display my ticket only]"
wt_bulkupdate_relations: "bulkupdate to parent"
permission_view_work_time_tab: "View Work time tab"
permission_view_work_time_other_member: "View other members' work time"
permission_edit_work_time_total: "Edit work time totals"
permission_edit_work_time_other_member: "Edit other members' work time"
wt_saved_value: "Saved timed: "
wt_legend: "Legend"
wt_style_default: "By default"
wt_style_assigned: "Assigned"
wt_style_worked: "Worked on"
wt_style__assigned_worked: "Assigned and worked on"
wt_style_overdue: "Overdue"
wt_style_assigned_overdue: "Assigned and overdue"
wt_style_overdue_worked: "Overdue and worked on"
wt_style_assigned_overdue_worked: "Assigned, overdue and worked on"
wt_account_start_day: "Company start day"
pt-BR:
work_time: "Agenda"
wt_update: "Atualização"
wt_month_names: "Jan,Fev,Mar,Abr,Mai,Jun,Jul,Ago,Set,Out,Nov,Dez"
wt_week_day_names: "Dom,Seg,Ter,Qua,Qui,Sex,Sab"
wt_monthly_report: "Relatório Mensal"
wt_daily_report: "Relatório Diário"
wt_each_member_report: "Relatório Membro"
wt_raw_total: "Relatório Mensal(não reenviado)"
wt_edit_relay: "Editor de etarefas enviada"
wt_relay_total: "Relatório mensal de tarefas reenviadas"
wt_ticket: "Tarefa"
wt_add_ticket: "Nova tarefa"
wt_no_permission: "Sem permissão"
wt_no_permission_del: "Não é possível excluir porque pedidos de horas-homem"
wt_loop_relay: "Ticket relation looped"
wt_set_holiday: "define feriado nesta data"
wt_del_holiday: "define data normal"
wt_apply_checked: "Aplicar selecionados"
wt_select_project: "Selecione projeto..."
wt_select_user: "Selecione usuário..."
wt_edit_memo: "Edita anotação"
wt_pre_memo: "prev anotação"
wt_next_memo: "prox anotação"
wt_data_list: "Lista de data"
wt_input_ticket_numbers: "ou inclua o número da tarefa"
wt_delete_closed_tickets: "apagar tarefas fechadas"
wt_data_download: "download de dados"
wt_data_download_with_act: "download de dados(each activity)"
wt_opt_disp_ticket_with_closed: "[exibe tarefa fechada]"
wt_opt_disp_ticket_opened_only: "[exibe somente tafera aberta]"
wt_opt_disp_ticket_with_other_member: "[exibe tarefa de outros membros]"
wt_opt_disp_ticket_mine_only: "[existe somente minha tarefa]"
wt_bulkupdate_relations: "bulkupdate to parent"
permission_view_work_time_tab: "Ver a tab tempo de trabalho"
permission_view_work_time_other_member: "Ver o tempo de trabalho de outros membros"
permission_edit_work_time_total: "Edit work time totals"
permission_edit_work_time_other_member: "Editar o tempo de trabalho de outros membros"
wt_saved_value: "Tempo salvo: "
wt_legend: "Legenda"
wt_style_default: "Por padrão"
wt_style_assigned: "Atribuído"
wt_style_worked: "Trabalhando em"
wt_style__assigned_worked: "Atrasado e trabalhando em"
wt_style_overdue: "Atrasada"
wt_style_assigned_overdue: "Atribuído e em atraso"
wt_style_overdue_worked: "Atrasada e trabalhado"
wt_style_assigned_overdue_worked: "Atribuída, atrasada e trabalhando em"
wt_account_start_day: "Empresa começar dia"
ru:
work_time: "Рабочий отчёт"
wt_update: "Обновить"
wt_month_names: "Янв,Фев,Мар,Апр,Май,Июн,Июл,Авг,Сен,Окт,Ноя,Дек"
wt_week_day_names: "Вск,Пон,Втр,Срд,Чет,Пят,Суб"
wt_monthly_report: "Ежемесячный отчёт"
wt_daily_report: "Ежедневный отчёт"
wt_each_member_report: "Отчёт по пользователям"
wt_raw_total: "Отчёт за месяц (не связанный)"
wt_relay_total: "Отчёт за месяц (связанный)"
wt_edit_relay: "Редактор связей задач"
wt_ticket: "Задача"
wt_add_ticket: "Добавить задачу"
wt_no_permission: "Ограничение прав"
wt_loop_relay: "Взаимосвязь задач"
wt_set_holiday: "установить выходной на дату"
wt_del_holiday: "удалить выходной на дату"
wt_apply_checked: "применить все отмеченные"
wt_select_project: "Отфильтровать по проектам..."
wt_select_user: "Выбор пользователя..."
wt_edit_memo: "Редактировать примечание"
wt_pre_memo: "предыдущее примечание"
wt_next_memo: "следующе примечание"
wt_data_list: "Список дат"
wt_input_ticket_numbers: "или введите номера задач (через запятую)"
wt_delete_closed_tickets: "удалить закрытые задачи"
wt_data_download: "экспорт данных"
wt_data_download_with_act: "экспорт данных(each activity)"
wt_opt_disp_ticket_with_closed: "[отобразить закрытые задачи]"
wt_opt_disp_ticket_opened_only: "[отобразить только открытые задачи]"
wt_opt_disp_ticket_with_other_member: "[отобразить задачи других участников]"
wt_opt_disp_ticket_mine_only: "[отобразить только мои задачи]"
wt_bulkupdate_relations: "массовое обновление связанных"
permission_view_work_time_tab: "Просмотр закладки рабочего времени"
permission_view_work_time_other_member: "Просмотр рабочего времени других участников"
permission_edit_work_time_total: "Редактирование рабочего времени"
permission_edit_work_time_other_member: "Редактирование рабочего времени других участников"
wt_saved_value: "Сохранённое время: "
wt_legend: "Соответствие цветов"
wt_style_default: "По умолчанию"
wt_style_assigned: "Назначенные"
wt_style_worked: "В работе"
wt_style__assigned_worked: "Назначенные и в работе"
wt_style_overdue: "Просроченные"
wt_style_assigned_overdue: "Назначенные и просроченные"
wt_style_overdue_worked: "Просроченные и в работе"
wt_style_assigned_overdue_worked: "Назначенные, в работе и просроченные"
wt_account_start_day: "Company start day"
tr:
work_time: "ÇalışmaZamanı"
wt_update: "Güncelle"
wt_month_names: "Oca,Şub,Mar,Nis,May,Haz,Tem,Ağu,Eyl,Eki,Kas,Ara"
wt_week_day_names: "Paz,Pzt,Sal,Çar,Per,Cum,Cmt"
wt_monthly_report: "Aylık Rapor"
wt_daily_report: "Günlük Rapor"
wt_each_member_report: "Kullanıcı Raporu"
wt_raw_total: "Aylık Rapor(aktarımsız)"
wt_edit_relay: "İş Aktarım Düzenleyici"
wt_relay_total: "Aktarılmış İş Aylık Rapor"
wt_ticket: "İş"
wt_add_ticket: "İş ekle"
wt_no_permission: "Yetki yok"
wt_loop_relay: "İş ilişkileri dögülü"
wt_set_holiday: "bu tarihe tatil koy"
wt_del_holiday: "bu tarihteki tatili sil"
wt_apply_checked: "seçililere uygula"
wt_select_project: "Birim seç..."
wt_select_user: "Kullanıcı seç..."
wt_edit_memo: "Not düzenle"
wt_pre_memo: "önceki not"
wt_next_memo: "sonraki not"
wt_data_list: "Veri Liste"
wt_input_ticket_numbers: "veya numarası gir"
wt_delete_closed_tickets: "kapalı işleri sil"
wt_data_download: "veri indir"
wt_data_download_with_act: "veri indir(each activity)"
wt_opt_disp_ticket_with_closed: "[kapalı işleri göster]"
wt_opt_disp_ticket_opened_only: "[sadece açık işleri göster]"
wt_opt_disp_ticket_with_other_member: "[başkalarının işlerini göster]"
wt_opt_disp_ticket_mine_only: "[sadece kendi işlerimi göster]"
wt_bulkupdate_relations: "üst işi toplu güncelle"
permission_view_work_time_tab: "ÇalışmaZamanı sekmesini gör"
permission_view_work_time_other_member: "Başka kişilerin çalışma zamanını gör"
permission_edit_work_time_total: "Çalışma zamanı toplamlarını düzenle"
permission_edit_work_time_other_member: "Başka kiçinin çalışma zamanını düzenle"
wt_saved_value: "Saklanmış değer: "
wt_legend: "İşaretler"
wt_style_default: "Öntanımlı"
wt_style_assigned: "Atanmış"
wt_style_worked: "Çalışılmış"
wt_style__assigned_worked: "Atanmış ve çalışılmış"
wt_style_overdue: "Zamanı geçmiş"
wt_style_assigned_overdue: "Atanmış ve zamanı geçmiş"
wt_style_overdue_worked: "Zamanı geçmiş ve çalışılmış"
wt_style_assigned_overdue_worked: "Atanmış, zamanı geçmiş, çalışılmış"
wt_account_start_day: "Company start day"
zh:
work_time: "工时日志"
wt_update: "更新"
wt_month_names: "一月,二月,三月,四月,五月,六月,七月,八月,九月,十月,十一月,十二月"
wt_week_day_names: "周日,周一,周二,周三,周四,周五,周六"
wt_monthly_report: "月度报告"
wt_daily_report: "日报告"
wt_each_member_report: "成员报告"
wt_raw_total: "月度报告(not relayed)"
wt_relay_total: "月度报告(relayed)"
wt_edit_relay: "工作 Relay 编辑器"
wt_ticket: "工作"
wt_add_ticket: "新增工作"
wt_no_permission: "无权限"
wt_loop_relay: "工作关系循环"
wt_set_holiday: "设置当前日期为假期"
wt_del_holiday: "设置当期日期为工作日"
wt_apply_checked: "应用所有已选项"
wt_select_project: "选择项目..."
wt_select_user: "选择用户..."
wt_edit_memo: "编辑备忘录"
wt_pre_memo: "前一备忘录"
wt_next_memo: "后一备忘录"
wt_data_list: "数据清单"
wt_input_ticket_numbers: "请输入编号"
wt_delete_closed_tickets: "删除已关闭的工作"
wt_data_download: "数据下载"
wt_data_download_with_act: "数据下载(按活动)"
wt_opt_disp_ticket_with_closed: "[显示已关闭的工作]"
wt_opt_disp_ticket_opened_only: "[只显示打开的工作]"
wt_opt_disp_ticket_with_other_member: "[显示其他成员的工作]"
wt_opt_disp_ticket_mine_only: "[只显示我的工作]"
wt_bulkupdate_relations: "批量更新到上一级"
permission_view_work_time_tab: "查看工时日志"
permission_view_work_time_other_member: "查看其他成员的工时日志"
permission_edit_work_time_total: "编辑工时日志总计"
permission_edit_work_time_other_member: "编辑其他成员的工时日志"
wt_saved_value: "已节省: "
wt_legend: "图例"
wt_style_default: "按默认"
wt_style_assigned: "已分配"
wt_style_worked: "已处理"
wt_style__assigned_worked: "已分配并已耗费"
wt_style_overdue: "逾期"
wt_style_assigned_overdue: "已分配并已逾期"
wt_style_overdue_worked: "已逾期并已耗费"
wt_style_assigned_overdue_worked: "已分配、已逾期并已耗费"
wt_account_start_day: "统计开始日"
RedmineApp::Application.routes.draw do
match 'work_time/:action', :to => 'work_time#index', :via => [:get, :post]
match 'work_time/:action/:id', :to => 'work_time#show', :via => [:get, :post]
end
class CreateUserIssueMonths < ActiveRecord::Migration
def self.up
create_table :user_issue_months do |t|
t.column :uid, :integer
t.column :issue, :integer
t.column :month, :string
t.column :odr, :integer
end
end
def self.down
drop_table :user_issue_months
end
end
class CreateWtMemberOrders < ActiveRecord::Migration
def self.up
create_table :wt_member_orders do |t|
t.column :user_id, :integer
t.column :position, :integer
end
end
def self.down
drop_table :wt_member_orders
end
end
class CreateWtTicketRelays < ActiveRecord::Migration
def self.up
create_table :wt_ticket_relays do |t|
t.column :issue_id, :integer
t.column :position, :integer
t.column :parent, :integer
end
end
def self.down
drop_table :wt_ticket_relays
end
end
class AddPrjToMemOdr < ActiveRecord::Migration
def self.up
add_column :wt_member_orders, :prj_id, :integer, :default => nil
end
def self.down
remove_column :wt_member_orders, :prj_id
end
end
class CreateWtDailyMemos < ActiveRecord::Migration
def self.up
create_table :wt_daily_memos do |t|
t.column :day, :date
t.column :user_id, :integer
t.column :created_on, :timestamp
t.column :updated_on, :timestamp
t.column :description, :text
end
end
def self.down
drop_table :wt_daily_memos
end
end
class CreateWtProjectOrders < ActiveRecord::Migration
def self.up
create_table :wt_project_orders do |t|
t.column :prj, :integer
t.column :uid, :integer
t.column :dsp_prj, :integer
t.column :dsp_pos, :integer
end
end
def self.down
drop_table :wt_project_orders
end
end
class CreateWtHolidays < ActiveRecord::Migration
def self.up
create_table :wt_holidays do |t|
t.column :holiday, :date
t.column :created_on, :datetime
t.column :created_by, :integer
t.column :deleted_on, :datetime
t.column :deleted_by, :integer
end
end
def self.down
drop_table :wt_holidays
end
end
class RemoveMonthFromUserIssueMonth < ActiveRecord::Migration
def self.up
remove_column :user_issue_months, :month
end
def self.down
add_column :user_issue_months, :month, :string, :default => nil
end
end
class RemovePrjFromWtProjectOrders < ActiveRecord::Migration
def self.up
remove_column :wt_project_orders, :prj
end
def self.down
add_column :wt_project_orders, :prj, :integer, :default => nil
end
end
require 'redmine'
Redmine::Plugin.register :redmine_work_time do
name 'Redmine Work Time plugin'
author 'Tomohisa Kusukawa'
description 'A plugin to view and update TimeEntry by each user'
version '0.3.4'
url 'http://www.redmine.org/plugins/redmine_work_time'
author_url 'http://about.me/tkusukawa'
project_module :work_time do
permission :view_work_time_tab, {:work_time =>
[:show,:member_monthly_data,
:total,:total_data,:edit_relay,:relay_total,:relay_total_data,
:total_data_with_act, :relay_total_data_with_act,
:register_project_settings,
]}
permission :view_work_time_other_member, {:work_time =>
[:show,:member_monthly_data,
:total,:total_data,:edit_relay,:relay_total,:relay_total_data,
:total_data_with_act, :relay_total_data_with_act,
:register_project_settings,
]}
permission :edit_work_time_total, {}
permission :edit_work_time_other_member, {}
end
menu :account_menu, :work_time,
{:controller => 'work_time', :action => 'index'},
:before => :my_account,
:caption => :work_time,
:if => Proc.new{User.current.logged? && Setting.plugin_redmine_work_time['show_account_menu']}
menu :project_menu, :work_time,
{:controller => 'work_time', :action => 'show'}, :caption => :work_time,
:after => :gantt
settings :default => {'account_start_days' => {}, 'show_account_menu' => 'true'},
:partial => 'settings/work_time_settings'
Rails.configuration.to_prepare do
require_dependency 'projects_helper'
unless ProjectsHelper.included_modules.include? WorkTimeProjectsHelperPatch
ProjectsHelper.send(:include, WorkTimeProjectsHelperPatch)
end
end
end
require_dependency 'projects_helper'
module WorkTimeProjectsHelperPatch
def self.included base # :nodoc:
base.send :include, ProjectsHelperMethodsWorkTime
base.class_eval do
alias_method_chain :project_settings_tabs, :work_time
end
end
end
module ProjectsHelperMethodsWorkTime
def project_settings_tabs_with_work_time
tabs = project_settings_tabs_without_work_time
action = {:name => 'work_time',
:controller => 'work_time',
:action => :show,
:partial => 'settings/work_time_project_settings', :label => :work_time}
tabs << action if User.current.allowed_to?(:edit_work_time_total, @project)
tabs
end
end
Redmineプラグイン(WorkTime) 作成覚書
cd $RAILS_ROOT
***プラグインの雛形生成***
# ruby script/generate redmine_plugin work_time
***バージョン管理に登録***
# cd vendor/plugins/redmine_work_time
# hg init
# hg commit -A
***init.rbの編集***
# vi init.rb
# cat init.rb
require 'redmine'
Redmine::Plugin.register :redmine_work_time do
name 'Redmine Work Time plugin'
author 'Tomohisa Kusukawa'
description 'A plugin to view and update TimeEntry by each user'
version '0.0.1'
project_module :work_time do
permission :view_work_time_tab, {:work_time => [:show]}, :public => true
end
menu :project_menu, :work_time, {:controller => 'work_time', :action => 'show'}, :caption => :work_time
end
*** モデル(DBテーブル)の作成 ***
# ruby script/generate redmine_plugin_model work_time user_issue_month uid:integer issue:integer month:string odr:integer
exists app/models/
create test/unit/
create test/fixtures/
create app/models/user_issue_month.rb
create test/unit/user_issue_month_test.rb
create test/fixtures/user_issue_months.yml
exists db/migrate
create db/migrate/20090104004624_create_user_issue_months.rb
# mv db/migrate/20090104004624_create_user_issue_months.rb db/migrate/001_create_user_issue_months.rb
# ruby script/generate redmine_plugin_model work_time wt_member_order user_id:integer position:integer
exists app/models/
exists test/unit/
exists test/fixtures/
create app/models/wt_member_order.rb
create test/unit/wt_member_order_test.rb
create test/fixtures/wt_member_orders.yml
exists db/migrate
create db/migrate/20090131105945_create_wt_member_orders.rb
# mv db/migrate/20090131105945_create_wt_member_orders.rb db/migrate/002_create_wt_member_orders.rb
# ruby script/generate redmine_plugin_model work_time wt_ticket_relay issue_id:integer position:integer parent:integer
exists app/models/
exists test/unit/
exists test/fixtures/
create app/models/wt_ticket_relay.rb
create test/unit/wt_ticket_relay_test.rb
create test/fixtures/wt_ticket_relays.yml
exists db/migrate
create db/migrate/20090131110021_create_wt_ticket_relays.rb
# mv db/migrate/20090131110021_create_wt_ticket_relays.rb db/migrate/003_create_wt_ticket_relays.rb
# vi db/migrate/004_add_prj_to_mem_odr.rb
# ruby script/generate redmine_plugin_model work_time wt_daily_memo day:date user_id:integer created_on:timestamp updated_on:timestamp description:text
exists app/models/
exists test/unit/
exists test/fixtures/
create app/models/wt_daily_memo.rb
create test/unit/wt_daily_memo_test.rb
create test/fixtures/wt_daily_memos.yml
exists db/migrate
create db/migrate/20090221151021_create_wt_daily_memos.rb
# mv db/migrate/20090221151021_create_wt_daily_memos.rb db/migrate/005_create_wt_daily_memos.rb
# rake db:migrate_plugins RAILS_ENV=production
*** コントローラの作成 ***
# ruby script/generate redmine_plugin_controller work_time work_time show
exists app/controllers/
exists app/helpers/
create app/views/work_time
create test/functional/
create app/controllers/work_time_controller.rb
create test/functional/work_time_controller_test.rb
create app/helpers/work_time_helper.rb
create app/views/work_time/show.html.erb
# cd $RAILS_ROOT/vendor/plugins/redmine_work_time/app/controllers/
# vi work_time_controller.rb
*** ビューの編集 ***
# cd $RAILS_ROOT/vendor/plugins/redmine_work_time/app/view/work_time/
# vi show.html.erb
######################################################################### version 0.0.33
ユーザーの月毎表示におけるチケットトータル工数の表示を左側に変更
######################################################################### version 0.0.34
ユーザ毎の工数表示をプロジェクト毎にまとめて表示するように変更
# cd $RAILS_ROOT
# ruby script/generate redmine_plugin_model work_time wt_project_orders prj:integer uid:integer dsp_prj:integer dsp_pos:integer
exists app/models/
exists test/unit/
exists test/fixtures/
create app/models/wt_project_orders.rb
create test/unit/wt_project_orders_test.rb
create test/fixtures/wt_project_orders.yml
exists db/migrate
create db/migrate/20090531095136_create_wt_project_orders.rb
# cd vendor/plugins/redmine_work_time/db/migrate/
# mv 20090531095136_create_wt_project_orders.rb 006_create_wt_project_orders.rb
# cd $RAILS_ROOT
# rake db:migrate_plugins RAILS_ENV=production
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
one:
id: 1
uid: 1
issue: 1
month: MyString
odr: 1
two:
id: 2
uid: 1
issue: 1
month: MyString
odr: 1
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
one:
id: 1
day: 2009-02-22
user_id: 1
created_on: 2009-02-22 00:10:21
updated_on: 2009-02-22 00:10:21
description: MyText
two:
id: 2
day: 2009-02-22
user_id: 1
created_on: 2009-02-22 00:10:21
updated_on: 2009-02-22 00:10:21
description: MyText
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
one:
id: 1
holiday: 2009-09-12
created_on: 2009-09-12 18:48:19
created_by: 1
deleted_on: 2009-09-12 18:48:19
deleted_by: 1
two:
id: 2
holiday: 2009-09-12
created_on: 2009-09-12 18:48:19
created_by: 1
deleted_on: 2009-09-12 18:48:19
deleted_by: 1
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
one:
id: 1
user_id: 1
position: 1
prj_id: 1
two:
id: 2
user_id: 1
position: 1
prj_id: 1
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
one:
id: 1
prj: 1
uid: 1
dsp_prj: 1
dsp_pos: 1
two:
id: 2
prj: 1
uid: 1
dsp_prj: 1
dsp_pos: 1
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
one:
id: 1
issue_id: 1
position: 1
parent: 1
two:
id: 2
issue_id: 1
position: 1
parent: 1
require File.dirname(__FILE__) + '/../test_helper'
class WorkTimeControllerTest < ActionController::TestCase
# Replace this with your real tests.
def test_truth
assert true
end
end
# Load the normal Rails helper
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 File.dirname(__FILE__) + '/../test_helper'
class UserIssueMonthTest < Test::Unit::TestCase
fixtures :user_issue_months
# Replace this with your real tests.
def test_truth
assert true
end
end
require File.dirname(__FILE__) + '/../test_helper'
class WtDailyMemoTest < Test::Unit::TestCase
fixtures :wt_daily_memos
# Replace this with your real tests.
def test_truth
assert true
end
end
require File.dirname(__FILE__) + '/../test_helper'
class WtHolidaysTest < Test::Unit::TestCase
fixtures :wt_holidays
# Replace this with your real tests.
def test_truth
assert true
end
end
require File.dirname(__FILE__) + '/../test_helper'
class WtMemberOrderTest < Test::Unit::TestCase
fixtures :wt_member_orders
# Replace this with your real tests.
def test_truth
assert true
end
end
require File.dirname(__FILE__) + '/../test_helper'
class WtProjectOrdersTest < Test::Unit::TestCase
fixtures :wt_project_orders
# Replace this with your real tests.
def test_truth
assert true
end
end
require File.dirname(__FILE__) + '/../test_helper'
class WtTicketRelayTest < Test::Unit::TestCase
fixtures :wt_ticket_relays
# Replace this with your real tests.
def test_truth
assert true
end
end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment