works, basically

This commit is contained in:
Jens Kraemer
2020-04-24 17:20:18 +08:00
parent 70257cdee0
commit 20ccbba2c1
24 changed files with 355 additions and 27 deletions

View File

@@ -1,12 +1,23 @@
# weiter
#
# - update time entry row after context menu stop (reflect saved time)
# - show current time in menu item / window title
# - remember last activity, preselect that in 'new' form
# - same for project, unless we are in a project context
# - focus first field that needs an action, depending on above
#
class StopwatchTimersController < ApplicationController
helper :timelog
before_action :require_login
before_action :find_optional_data, only: %i(new create)
before_action :authorize_log_time, only: %i(new create start stop current)
before_action :find_time_entry, only: %i(edit update start stop)
before_action :authorize_edit_time, only: %i(edit update)
def new
@time_entry = new_time_entry
respond_to :js
load_todays_entries
end
def create
@@ -23,15 +34,54 @@ class StopwatchTimersController < ApplicationController
end
def edit
@entries = load_todays_entries #.where.not(id: @time_entry.id)
end
def update
# todo update entry
if params[:continue]
new
end
end
def start
r = Stopwatch::StartTimer.new(@time_entry).call
if r.success?
@started_time_entry = @time_entry
else
logger.error "unable to start timer: #{r.error}"
end
new unless params[:context]
end
def stop
r = Stopwatch::StopTimer.new().call
unless r.success?
logger.error "unable to stop timer"
end
new unless params[:context]
render action: 'start'
end
def current
timer = Stopwatch::Timer.new User.current
render json: timer.to_json
end
private
def find_time_entry
@time_entry = time_entries.find params[:id]
end
def load_todays_entries
@entries = time_entries.where(spent_on: User.current.today).order(created_on: :asc)
end
def time_entries
TimeEntry.where(user: User.current)
end
def new_time_entry
TimeEntry.new(project: @project, issue: @issue,
user: User.current, spent_on: User.current.today)
@@ -48,4 +98,12 @@ class StopwatchTimersController < ApplicationController
render_404
end
def authorize_log_time
User.current.allowed_to?(:log_time, nil, global: true) or
deny_access
end
def authorize_edit_time
@time_entry.editable_by?(User.current) or deny_access
end
end

View File

@@ -0,0 +1,3 @@
<%= javascript_tag do %>
Stopwatch.currentTimerUrl = '<%= j current_stopwatch_timers_url %>';
<% end %>

View File

@@ -0,0 +1,2 @@
<%= javascript_include_tag "stopwatch", plugin: "stopwatch" %>
<%= stylesheet_link_tag "stopwatch", plugin: "stopwatch" %>

View File

@@ -0,0 +1,10 @@
<% if @time_entries.one? %>
<% time_entry = @time_entries.first %>
<li>
<% if User.current.is_running_timer? time_entry %>
<%= context_menu_link l(:label_stopwatch_stop), stop_stopwatch_timer_path(time_entry, context: '1'), class: 'icon-time', remote: true, method: :put %>
<% else %>
<%= context_menu_link l(:label_stopwatch_start), start_stopwatch_timer_path(time_entry, context: '1'), class: 'icon-time', remote: true, method: :put %>
<% end %>
</li>
<% end %>

View File

@@ -1,11 +1,14 @@
<h3 class="title"><%= l(:label_spent_time) %></h3>
<h3 class="title"><%= l(:button_log_time) %> - <%= format_date User.current.today %></h3>
<%= labelled_form_for @time_entry, url: stopwatch_path, remote: true do |f| %>
<% @time_entry.hours ||= 0 %>
<%= render partial: 'timelog/form', locals: { f: f } %>
<%= render partial: 'entries_list', locals: { entries: @entries } %>
<%= labelled_form_for @time_entry, url: stopwatch_timer_path(@time_entry), method: :put, remote: true do |f| %>
<%= hidden_field_tag :time_entry_id, @time_entry.id %>
<%= render partial: 'entry_form', locals: { f: f } %>
<p class="buttons">
<%= submit_tag l(:button_create) %>
<%= submit_tag l(:button_cancel), name: nil, onclick: "hideModal(this);", type: 'button' %>
<%= submit_tag l(:button_save) %>
<%= submit_tag t('.button_save_and_continue'), name: 'continue' %>
<%#= submit_tag l(:button_cancel), name: nil, onclick: "hideModal(this);", type: 'button' %>
</p>
<% end %>

View File

@@ -0,0 +1,31 @@
<% if entries.any? %>
<table class="list time-entries odd-even">
<thead><tr>
<th><%= l(:label_activity) %></th>
<th><%= l(:label_project) %></th>
<th><%= l(:field_comments) %></th>
<th><%= l(:field_hours) %></th>
<th></th>
</tr></thead>
<tbody>
<% for entry in entries %>
<tr id="time-entry-<%= entry.id %>" class="time-entry <%= cycle "odd", "even" %>">
<td class="activity"><%= entry.activity %></td>
<td class="subject"><%= entry.project %> <%= h(' - ') + link_to_issue(entry.issue, truncate: 50) if entry.issue %></td>
<td class="comments"><%= entry.comments %></td>
<td class="hours"><%= html_hours(format_hours(entry.hours)) %></td>
<td class="buttons">
<% if User.current.is_running_timer?(entry) %>
<%= link_to t(:label_stopwatch_stop), stop_stopwatch_timer_path(entry), remote: true, class: "icon-only icon-time", method: :put %>
<% else %>
<%= link_to t(:label_stopwatch_start), start_stopwatch_timer_path(entry), remote: true, class: "icon-only icon-time", method: :put %>
<% end %>
<%= link_to l(:button_edit), edit_stopwatch_timer_path(entry), remote: true, class: "icon-only icon-edit" if entry.editable_by? User.current %>
</td>
</tr>
<% end -%>
</tbody>
</table>
<% end %>

View File

@@ -0,0 +1,74 @@
<%= error_messages_for 'time_entry' %>
<fieldset class="box tabular">
<legend><%= t @time_entry.new_record? ? '.legend_new' : '.legend_edit' %></legend>
<p><%= f.select :activity_id, activity_collection_for_select_options(@time_entry), :required => true %></p>
<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>
<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.text_field :comments, :size => 100, :maxlength => 1024, :required => Setting.timelog_required_fields.include?('comments') %></p>
<p><%= f.hours_field :hours, :size => 6, :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 }) %>
</fieldset>
<%= 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(@time_entry, 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

@@ -1,12 +1,14 @@
<h3 class="title"><%= l(:button_log_time) %></h3>
<h3 class="title"><%= l(:button_log_time) %> - <%= format_date User.current.today %></h3>
<%= labelled_form_for @time_entry, url: stopwatch_timer_path, method: :post, remote: true do |f| %>
<%= render partial: 'entries_list', locals: { entries: @entries } %>
<%= labelled_form_for @time_entry, url: stopwatch_timers_path, method: :post, remote: true do |f| %>
<% @time_entry.hours ||= 0 %>
<%= render partial: 'timelog/form', locals: { f: f } %>
<%= render partial: 'entry_form', locals: { f: f } %>
<p class="buttons">
<%= submit_tag l(:button_create) %>
<%= submit_tag l(:button_cancel), name: nil, onclick: "hideModal(this);", type: 'button' %>
<%#= submit_tag l(:button_cancel), name: nil, onclick: "hideModal(this);", type: 'button' %>
</p>
<% end %>

View File

@@ -0,0 +1 @@
hideModal();

View File

@@ -0,0 +1,4 @@
hideModal();
$('#ajax-modal').html('<%= j render partial: 'stopwatch_timers/edit' %>');
showModal('ajax-modal', '700px');

View File

@@ -1,2 +1,2 @@
$('#ajax-modal').html('<%= j render partial: 'stopwatch_timers/new' %>');
showModal('ajax-modal', '600px');
showModal('ajax-modal', '700px');

View File

@@ -0,0 +1,9 @@
<% if params[:context] %>
contextMenuHide();
<% else %>
hideModal();
$('#ajax-modal').html('<%= j render partial: 'new' %>');
showModal('ajax-modal', '700px');
<% end %>
Stopwatch.highlightTimer('<%= @started_time_entry.id if @started_time_entry %>');

View File

@@ -0,0 +1,5 @@
hideModal();
<% if params[:continue] %>
$('#ajax-modal').html('<%= j render partial: 'stopwatch_timers/new' %>');
showModal('ajax-modal', '600px');
<% end %>