Redmine 3.4.4
This commit is contained in:
commit
64924a6376
2112 changed files with 259028 additions and 0 deletions
11
app/views/timelog/_date_range.html.erb
Normal file
11
app/views/timelog/_date_range.html.erb
Normal file
|
@ -0,0 +1,11 @@
|
|||
<%= render :partial => 'queries/query_form' %>
|
||||
|
||||
<div class="tabs hide-when-print">
|
||||
<% query_params = request.query_parameters %>
|
||||
<ul>
|
||||
<li><%= link_to(l(:label_details), _time_entries_path(@project, nil, :params => query_params),
|
||||
:class => (action_name == 'index' ? 'selected' : nil)) %></li>
|
||||
<li><%= link_to(l(:label_report), _report_time_entries_path(@project, nil, :params => query_params),
|
||||
:class => (action_name == 'report' ? 'selected' : nil)) %></li>
|
||||
</ul>
|
||||
</div>
|
76
app/views/timelog/_form.html.erb
Normal file
76
app/views/timelog/_form.html.erb
Normal file
|
@ -0,0 +1,76 @@
|
|||
<%= error_messages_for 'time_entry' %>
|
||||
<%= back_url_hidden_field_tag %>
|
||||
|
||||
<div class="box tabular">
|
||||
<% if @time_entry.new_record? && params[:project_id] %>
|
||||
<%= hidden_field_tag 'project_id', params[:project_id] %>
|
||||
<% elsif @time_entry.new_record? && params[:issue_id] %>
|
||||
<%= hidden_field_tag 'issue_id', params[:issue_id] %>
|
||||
<% else %>
|
||||
<p><%= f.select :project_id, project_tree_options_for_select(Project.allowed_to(:log_time).to_a, :selected => @time_entry.project, :include_blank => true), :required => true %></p>
|
||||
<% end %>
|
||||
|
||||
<p>
|
||||
<%= f.text_field :issue_id, :size => 6, :required => Setting.timelog_required_fields.include?('issue_id') %>
|
||||
<span id="time_entry_issue">
|
||||
<%= link_to_issue(@time_entry.issue) if @time_entry.issue.try(:visible?) %>
|
||||
</span>
|
||||
</p>
|
||||
<p><%= f.date_field :spent_on, :size => 10, :required => true %><%= calendar_for('time_entry_spent_on') %></p>
|
||||
<p><%= f.hours_field :hours, :size => 6, :required => true %></p>
|
||||
<p><%= f.text_field :comments, :size => 100, :maxlength => 1024, :required => Setting.timelog_required_fields.include?('comments') %></p>
|
||||
<p><%= f.select :activity_id, activity_collection_for_select_options(@time_entry), :required => true %></p>
|
||||
<% @time_entry.custom_field_values.each do |value| %>
|
||||
<p><%= custom_field_tag_with_label :time_entry, value %></p>
|
||||
<% end %>
|
||||
<%= call_hook(:view_timelog_edit_form_bottom, { :time_entry => @time_entry, :form => f }) %>
|
||||
</div>
|
||||
|
||||
<%= javascript_tag do %>
|
||||
$(document).ready(function(){
|
||||
$('#time_entry_project_id').change(function(){
|
||||
$('#time_entry_issue_id').val('');
|
||||
});
|
||||
$('#time_entry_project_id, #time_entry_issue_id').change(function(){
|
||||
$.ajax({
|
||||
url: '<%= escape_javascript(@time_entry.new_record? ? new_time_entry_path(:format => 'js') : edit_time_entry_path(:format => 'js')) %>',
|
||||
type: 'post',
|
||||
data: $(this).closest('form').serialize()
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
observeAutocompleteField('time_entry_issue_id',
|
||||
function(request, callback) {
|
||||
var url = '<%= j auto_complete_issues_path %>';
|
||||
var data = {
|
||||
term: request.term
|
||||
};
|
||||
var project_id;
|
||||
<% if @time_entry.new_record? && @project %>
|
||||
project_id = '<%= @project.id %>';
|
||||
<% else %>
|
||||
project_id = $('#time_entry_project_id').val();
|
||||
<% end %>
|
||||
if(project_id){
|
||||
data['project_id'] = project_id;
|
||||
} else {
|
||||
data['scope'] = 'all';
|
||||
}
|
||||
|
||||
$.get(url, data, null, 'json')
|
||||
.done(function(data){
|
||||
callback(data);
|
||||
})
|
||||
.fail(function(jqXHR, status, error){
|
||||
callback([]);
|
||||
});
|
||||
},
|
||||
{
|
||||
select: function(event, ui) {
|
||||
$('#time_entry_issue').text('');
|
||||
$('#time_entry_issue_id').val(ui.item.value).change();
|
||||
}
|
||||
}
|
||||
);
|
||||
<% end %>
|
70
app/views/timelog/_list.html.erb
Normal file
70
app/views/timelog/_list.html.erb
Normal file
|
@ -0,0 +1,70 @@
|
|||
<%= form_tag({}, :data => {:cm_url => time_entries_context_menu_path}) do -%>
|
||||
<%= hidden_field_tag 'back_url', url_for(:params => request.query_parameters), :id => nil %>
|
||||
<div class="autoscroll">
|
||||
<table class="list odd-even time-entries">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="checkbox hide-when-print">
|
||||
<%= check_box_tag 'check_all', '', false, :class => 'toggle-selection',
|
||||
:title => "#{l(:button_check_all)}/#{l(:button_uncheck_all)}" %>
|
||||
</th>
|
||||
<% @query.inline_columns.each do |column| %>
|
||||
<%= column_header(@query, column) %>
|
||||
<% end %>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% grouped_query_results(entries, @query) do |entry, group_name, group_count, group_totals| -%>
|
||||
<% if group_name %>
|
||||
<% reset_cycle %>
|
||||
<tr class="group open">
|
||||
<td colspan="<%= @query.inline_columns.size + 2 %>">
|
||||
<span class="expander" onclick="toggleRowGroup(this);"> </span>
|
||||
<span class="name"><%= group_name %></span>
|
||||
<% if group_count %>
|
||||
<span class="count"><%= group_count %></span>
|
||||
<% end %>
|
||||
<span class="totals"><%= group_totals %></span>
|
||||
<%= link_to_function("#{l(:button_collapse_all)}/#{l(:button_expand_all)}",
|
||||
"toggleAllRowGroups(this)", :class => 'toggle-all') %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
<tr id="time-entry-<%= entry.id %>" class="time-entry <%= cycle("odd", "even") %> hascontextmenu">
|
||||
<td class="checkbox hide-when-print"><%= check_box_tag("ids[]", entry.id, false, :id => nil) %></td>
|
||||
<% @query.inline_columns.each do |column| %>
|
||||
<%= content_tag('td', column_content(column, entry), :class => column.css_classes) %>
|
||||
<% end %>
|
||||
<td class="buttons">
|
||||
<% if entry.editable_by?(User.current) -%>
|
||||
<%= link_to l(:button_edit), edit_time_entry_path(entry),
|
||||
:title => l(:button_edit),
|
||||
:class => 'icon-only icon-edit' %>
|
||||
<%= link_to l(:button_delete), time_entry_path(entry),
|
||||
:data => {:confirm => l(:text_are_you_sure)},
|
||||
:method => :delete,
|
||||
:title => l(:button_delete),
|
||||
:class => 'icon-only icon-del' %>
|
||||
<% end -%>
|
||||
</td>
|
||||
</tr>
|
||||
<% @query.block_columns.each do |column|
|
||||
if (text = column_content(column, issue)) && text.present? -%>
|
||||
<tr class="<%= current_cycle %>">
|
||||
<td colspan="<%= @query.inline_columns.size + 1 %>" class="<%= column.css_classes %>">
|
||||
<% if query.block_columns.count > 1 %>
|
||||
<span><%= column.caption %></span>
|
||||
<% end %>
|
||||
<%= text %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end -%>
|
||||
<% end -%>
|
||||
<% end -%>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<% end -%>
|
||||
|
||||
<%= context_menu %>
|
19
app/views/timelog/_report_criteria.html.erb
Normal file
19
app/views/timelog/_report_criteria.html.erb
Normal file
|
@ -0,0 +1,19 @@
|
|||
<% @report.hours.collect {|h| h[criterias[level]].to_s}.uniq.each do |value| %>
|
||||
<% hours_for_value = select_hours(hours, criterias[level], value) -%>
|
||||
<% next if hours_for_value.empty? -%>
|
||||
<tr class="<%= criterias.length > level+1 ? 'subtotal' : 'last-level' %>">
|
||||
<%= ("<td></td>" * level).html_safe %>
|
||||
<td class="name"><%= format_criteria_value(@report.available_criteria[criterias[level]], value) %></td>
|
||||
<%= ("<td></td>" * (criterias.length - level - 1)).html_safe -%>
|
||||
<% total = 0 -%>
|
||||
<% @report.periods.each do |period| -%>
|
||||
<% sum = sum_hours(select_hours(hours_for_value, @report.columns, period.to_s)); total += sum -%>
|
||||
<td class="hours"><%= html_hours(format_hours(sum)) if sum > 0 %></td>
|
||||
<% end -%>
|
||||
<td class="hours"><%= html_hours(format_hours(total)) if total > 0 %></td>
|
||||
</tr>
|
||||
<% if criterias.length > level+1 -%>
|
||||
<%= render(:partial => 'report_criteria', :locals => {:criterias => criterias, :hours => hours_for_value, :level => (level + 1)}) %>
|
||||
<% end -%>
|
||||
|
||||
<% end %>
|
66
app/views/timelog/bulk_edit.html.erb
Normal file
66
app/views/timelog/bulk_edit.html.erb
Normal file
|
@ -0,0 +1,66 @@
|
|||
<h2><%= l(:label_bulk_edit_selected_time_entries) %></h2>
|
||||
|
||||
<% if @unsaved_time_entries.present? %>
|
||||
<div id="errorExplanation">
|
||||
<span>
|
||||
<%= l(:notice_failed_to_save_time_entries,
|
||||
:count => @unsaved_time_entries.size,
|
||||
:total => @saved_time_entries.size,
|
||||
:ids => @unsaved_time_entries.map {|i| "##{i.id}"}.join(', ')) %>
|
||||
</span>
|
||||
<ul>
|
||||
<% bulk_edit_error_messages(@unsaved_time_entries).each do |message| %>
|
||||
<li><%= message %></li>
|
||||
<% end %>
|
||||
</ul>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<ul id="bulk-selection">
|
||||
<% @time_entries.each do |entry| %>
|
||||
<%= content_tag 'li',
|
||||
link_to("#{format_date(entry.spent_on)} - #{entry.project}: #{l(:label_f_hour_plural, :value => entry.hours)}", edit_time_entry_path(entry)) %>
|
||||
<% end %>
|
||||
</ul>
|
||||
|
||||
<%= form_tag(bulk_update_time_entries_path, :id => 'bulk_edit_form') do %>
|
||||
<%= @time_entries.collect {|i| hidden_field_tag('ids[]', i.id, :id => nil)}.join.html_safe %>
|
||||
<div class="box tabular">
|
||||
<div>
|
||||
<p>
|
||||
<label for="time_entry_issue_id"><%= l(:field_issue) %></label>
|
||||
<%= text_field :time_entry, :issue_id, :size => 6 %>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<label for="time_entry_spent_on"><%= l(:field_spent_on) %></label>
|
||||
<%= date_field :time_entry, :spent_on, :size => 10 %><%= calendar_for('time_entry_spent_on') %>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<label for="time_entry_hours"><%= l(:field_hours) %></label>
|
||||
<%= text_field :time_entry, :hours, :size => 6 %>
|
||||
</p>
|
||||
|
||||
<% if @available_activities.any? %>
|
||||
<p>
|
||||
<label for="time_entry_activity_id"><%= l(:field_activity) %></label>
|
||||
<%= select_tag('time_entry[activity_id]', content_tag('option', l(:label_no_change_option), :value => '') + options_from_collection_for_select(@available_activities, :id, :name)) %>
|
||||
</p>
|
||||
<% end %>
|
||||
|
||||
<p>
|
||||
<label for="time_entry_comments"><%= l(:field_comments) %></label>
|
||||
<%= text_field(:time_entry, :comments, :size => 100) %>
|
||||
</p>
|
||||
|
||||
<% @custom_fields.each do |custom_field| %>
|
||||
<p><label><%= h(custom_field.name) %></label> <%= custom_field_tag_for_bulk_edit('time_entry', custom_field, @time_entries) %></p>
|
||||
<% end %>
|
||||
|
||||
<%= call_hook(:view_time_entries_bulk_edit_details_bottom, { :time_entries => @time_entries }) %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p><%= submit_tag l(:button_submit) %></p>
|
||||
<% end %>
|
6
app/views/timelog/edit.html.erb
Normal file
6
app/views/timelog/edit.html.erb
Normal file
|
@ -0,0 +1,6 @@
|
|||
<h2><%= l(:label_spent_time) %></h2>
|
||||
|
||||
<%= labelled_form_for @time_entry, :url => time_entry_path(@time_entry), :html => {:multipart => true} do |f| %>
|
||||
<%= render :partial => 'form', :locals => {:f => f} %>
|
||||
<%= submit_tag l(:button_save) %>
|
||||
<% end %>
|
2
app/views/timelog/edit.js.erb
Normal file
2
app/views/timelog/edit.js.erb
Normal file
|
@ -0,0 +1,2 @@
|
|||
$('#time_entry_activity_id').html('<%= escape_javascript options_for_select(activity_collection_for_select_options(@time_entry), @time_entry.activity_id) %>');
|
||||
$('#time_entry_issue').html('<%= escape_javascript link_to_issue(@time_entry.issue) if @time_entry.issue.try(:visible?) %>');
|
18
app/views/timelog/index.api.rsb
Normal file
18
app/views/timelog/index.api.rsb
Normal file
|
@ -0,0 +1,18 @@
|
|||
api.array :time_entries, api_meta(:total_count => @entry_count, :offset => @offset, :limit => @limit) do
|
||||
@entries.each do |time_entry|
|
||||
api.time_entry do
|
||||
api.id time_entry.id
|
||||
api.project(:id => time_entry.project_id, :name => time_entry.project.name) unless time_entry.project.nil?
|
||||
api.issue(:id => time_entry.issue_id) unless time_entry.issue.nil?
|
||||
api.user(:id => time_entry.user_id, :name => time_entry.user.name) unless time_entry.user.nil?
|
||||
api.activity(:id => time_entry.activity_id, :name => time_entry.activity.name) unless time_entry.activity.nil?
|
||||
api.hours time_entry.hours
|
||||
api.comments time_entry.comments
|
||||
api.spent_on time_entry.spent_on
|
||||
api.created_on time_entry.created_on
|
||||
api.updated_on time_entry.updated_on
|
||||
|
||||
render_api_custom_values time_entry.custom_field_values, api
|
||||
end
|
||||
end
|
||||
end
|
51
app/views/timelog/index.html.erb
Normal file
51
app/views/timelog/index.html.erb
Normal file
|
@ -0,0 +1,51 @@
|
|||
<div class="contextual">
|
||||
<%= link_to l(:button_log_time),
|
||||
_new_time_entry_path(@project, @query.filtered_issue_id),
|
||||
:class => 'icon icon-time-add' if User.current.allowed_to?(:log_time, @project, :global => true) %>
|
||||
</div>
|
||||
|
||||
<h2><%= @query.new_record? ? l(:label_spent_time) : @query.name %></h2>
|
||||
|
||||
<%= form_tag(_time_entries_path(@project, nil), :method => :get, :id => 'query_form') do %>
|
||||
<%= render :partial => 'date_range' %>
|
||||
<% end %>
|
||||
|
||||
<% if @query.valid? %>
|
||||
<% if @entries.empty? %>
|
||||
<p class="nodata"><%= l(:label_no_data) %></p>
|
||||
<% else %>
|
||||
<%= render_query_totals(@query) %>
|
||||
<%= render :partial => 'list', :locals => { :entries => @entries }%>
|
||||
<span class="pagination"><%= pagination_links_full @entry_pages, @entry_count %></span>
|
||||
|
||||
<% other_formats_links do |f| %>
|
||||
<%= f.link_to_with_query_parameters 'Atom', :key => User.current.rss_key %>
|
||||
<%= f.link_to_with_query_parameters 'CSV', {}, :onclick => "showModal('csv-export-options', '330px'); return false;" %>
|
||||
<% end %>
|
||||
|
||||
<div id="csv-export-options" style="display:none;">
|
||||
<h3 class="title"><%= l(:label_export_options, :export_format => 'CSV') %></h3>
|
||||
<%= form_tag(_time_entries_path(@project, nil, :format => 'csv'), :method => :get, :id => 'csv-export-form') do %>
|
||||
<%= query_as_hidden_field_tags @query %>
|
||||
<p>
|
||||
<label><%= radio_button_tag 'c[]', '', true %> <%= l(:description_selected_columns) %></label><br />
|
||||
<label><%= radio_button_tag 'c[]', 'all_inline' %> <%= l(:description_all_columns) %></label>
|
||||
</p>
|
||||
<p class="buttons">
|
||||
<%= submit_tag l(:button_export), :name => nil, :onclick => "hideModal(this);" %>
|
||||
<%= submit_tag l(:button_cancel), :name => nil, :onclick => "hideModal(this);", :type => 'button' %>
|
||||
</p>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<% content_for :sidebar do %>
|
||||
<%= render_sidebar_queries(TimeEntryQuery, @project) %>
|
||||
<% end %>
|
||||
|
||||
<% html_title(@query.new_record? ? l(:label_spent_time) : @query.name, l(:label_details)) %>
|
||||
|
||||
<% content_for :header_tags do %>
|
||||
<%= auto_discovery_link_tag(:atom, {:issue_id => @issue, :format => 'atom', :key => User.current.rss_key}, :title => l(:label_spent_time)) %>
|
||||
<% end %>
|
7
app/views/timelog/new.html.erb
Normal file
7
app/views/timelog/new.html.erb
Normal file
|
@ -0,0 +1,7 @@
|
|||
<h2><%= l(:label_spent_time) %></h2>
|
||||
|
||||
<%= labelled_form_for @time_entry, :url => time_entries_path, :html => {:multipart => true} do |f| %>
|
||||
<%= render :partial => 'form', :locals => {:f => f} %>
|
||||
<%= submit_tag l(:button_create) %>
|
||||
<%= submit_tag l(:button_create_and_continue), :name => 'continue' %>
|
||||
<% end %>
|
2
app/views/timelog/new.js.erb
Normal file
2
app/views/timelog/new.js.erb
Normal file
|
@ -0,0 +1,2 @@
|
|||
$('#time_entry_activity_id').html('<%= escape_javascript options_for_select(activity_collection_for_select_options(@time_entry), @time_entry.activity_id) %>');
|
||||
$('#time_entry_issue').html('<%= escape_javascript link_to_issue(@time_entry.issue) if @time_entry.issue.try(:visible?) %>');
|
76
app/views/timelog/report.html.erb
Normal file
76
app/views/timelog/report.html.erb
Normal file
|
@ -0,0 +1,76 @@
|
|||
<div class="contextual">
|
||||
<%= link_to l(:button_log_time),
|
||||
_new_time_entry_path(@project, @issue),
|
||||
:class => 'icon icon-time-add' if User.current.allowed_to?(:log_time, @project, :global => true) %>
|
||||
</div>
|
||||
|
||||
<h2><%= @query.new_record? ? l(:label_spent_time) : @query.name %></h2>
|
||||
|
||||
<%= form_tag(_report_time_entries_path(@project, nil), :method => :get, :id => 'query_form') do %>
|
||||
<% @report.criteria.each do |criterion| %>
|
||||
<%= hidden_field_tag 'criteria[]', criterion, :id => nil %>
|
||||
<% end %>
|
||||
<%= render :partial => 'timelog/date_range' %>
|
||||
|
||||
<p><label for='columns'><%= l(:label_details) %></label>: <%= select_tag 'columns', options_for_select([[l(:label_year), 'year'],
|
||||
[l(:label_month), 'month'],
|
||||
[l(:label_week), 'week'],
|
||||
[l(:label_day_plural).titleize, 'day']], @report.columns),
|
||||
:onchange => "this.form.submit();" %>
|
||||
|
||||
<label for='criterias'><%= l(:button_add) %></label>: <%= select_tag('criteria[]', options_for_select([[]] + (@report.available_criteria.keys - @report.criteria).collect{|k| [l_or_humanize(@report.available_criteria[k][:label]), k]}),
|
||||
:onchange => "this.form.submit();",
|
||||
:style => 'width: 200px',
|
||||
:disabled => (@report.criteria.length >= 3),
|
||||
:id => "criterias") %>
|
||||
<%= link_to l(:button_clear), {:params => request.query_parameters.merge(:criteria => nil)}, :class => 'icon icon-reload' %></p>
|
||||
<% end %>
|
||||
|
||||
<% if @query.valid? %>
|
||||
<% unless @report.criteria.empty? %>
|
||||
<% if @report.hours.empty? %>
|
||||
<p class="nodata"><%= l(:label_no_data) %></p>
|
||||
<% else %>
|
||||
<div class="autoscroll">
|
||||
<table class="list" id="time-report">
|
||||
<thead>
|
||||
<tr>
|
||||
<% @report.criteria.each do |criteria| %>
|
||||
<th><%= l_or_humanize(@report.available_criteria[criteria][:label]) %></th>
|
||||
<% end %>
|
||||
<% columns_width = (40 / (@report.periods.length+1)).to_i %>
|
||||
<% @report.periods.each do |period| %>
|
||||
<th class="period" style="width:<%= columns_width %>%;"><%= period %></th>
|
||||
<% end %>
|
||||
<th class="total" style="width:<%= columns_width %>%;"><%= l(:label_total_time) %></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<%= render :partial => 'report_criteria', :locals => {:criterias => @report.criteria, :hours => @report.hours, :level => 0} %>
|
||||
<tr class="total">
|
||||
<td><%= l(:label_total_time) %></td>
|
||||
<%= ('<td></td>' * (@report.criteria.size - 1)).html_safe %>
|
||||
<% total = 0 -%>
|
||||
<% @report.periods.each do |period| -%>
|
||||
<% sum = sum_hours(select_hours(@report.hours, @report.columns, period.to_s)); total += sum -%>
|
||||
<td class="hours"><%= html_hours(format_hours(sum)) if sum > 0 %></td>
|
||||
<% end -%>
|
||||
<td class="hours"><%= html_hours(format_hours(total)) if total > 0 %></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<% other_formats_links do |f| %>
|
||||
<%= f.link_to_with_query_parameters 'CSV' %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<% content_for :sidebar do %>
|
||||
<%= render_sidebar_queries(TimeEntryQuery, @project) %>
|
||||
<% end %>
|
||||
|
||||
<% html_title(@query.new_record? ? l(:label_spent_time) : @query.name, l(:label_report)) %>
|
||||
|
14
app/views/timelog/show.api.rsb
Normal file
14
app/views/timelog/show.api.rsb
Normal file
|
@ -0,0 +1,14 @@
|
|||
api.time_entry do
|
||||
api.id @time_entry.id
|
||||
api.project(:id => @time_entry.project_id, :name => @time_entry.project.name) unless @time_entry.project.nil?
|
||||
api.issue(:id => @time_entry.issue_id) unless @time_entry.issue.nil?
|
||||
api.user(:id => @time_entry.user_id, :name => @time_entry.user.name) unless @time_entry.user.nil?
|
||||
api.activity(:id => @time_entry.activity_id, :name => @time_entry.activity.name) unless @time_entry.activity.nil?
|
||||
api.hours @time_entry.hours
|
||||
api.comments @time_entry.comments
|
||||
api.spent_on @time_entry.spent_on
|
||||
api.created_on @time_entry.created_on
|
||||
api.updated_on @time_entry.updated_on
|
||||
|
||||
render_api_custom_values @time_entry.custom_field_values, api
|
||||
end
|
Loading…
Add table
Add a link
Reference in a new issue