Redmine 3.4.4

This commit is contained in:
Manuel Cillero 2018-02-02 22:19:29 +01:00
commit 64924a6376
2112 changed files with 259028 additions and 0 deletions

View 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>

View 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 %>

View 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);">&nbsp;</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 %>

View 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 %>

View 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 %>

View 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 %>

View 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?) %>');

View 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

View 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 %>

View 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 %>

View 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?) %>');

View 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)) %>

View 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