diff --git a/app/controllers/tasks_controller.rb b/app/controllers/tasks_controller.rb index c7e46250..9fd7211e 100644 --- a/app/controllers/tasks_controller.rb +++ b/app/controllers/tasks_controller.rb @@ -1,21 +1,21 @@ # encoding: utf-8 class TasksController < ApplicationController #auto_complete_for :user, :nick - + def index @non_group_tasks = Task.non_group.includes(assignments: :user) @groups = Workgroup.includes(open_tasks: {assignments: :user}) end - + def user @unaccepted_tasks = Task.unaccepted_tasks_for(current_user) @accepted_tasks = Task.accepted_tasks_for(current_user) end - + def new @task = Task.new(current_user_id: current_user.id) end - + def create @task = Task.new(params[:task]) if params[:periodic] @@ -27,24 +27,25 @@ class TasksController < ApplicationController render :template => "tasks/new" end end - + def show @task = Task.find(params[:id]) end - + def edit @task = Task.find(params[:id]) + @periodic = !!params[:periodic] @task.current_user_id = current_user.id - if @task.periodic? - flash.now[:alert] = I18n.t('tasks.edit.warning_periodic').html_safe - end end - + def update @task = Task.find(params[:id]) + task_group = @task.periodic_task_group was_periodic = @task.periodic? + prev_due_date = @task.due_date @task.attributes=(params[:task]) if @task.errors.empty? && @task.save + task_group.update_tasks_including(@task, prev_due_date) if params[:periodic] flash[:notice] = I18n.t('tasks.update.notice') if was_periodic && !@task.periodic? flash[:notice] = I18n.t('tasks.update.notice_converted') @@ -58,7 +59,7 @@ class TasksController < ApplicationController render :template => "tasks/edit" end end - + def destroy task = Task.find(params[:id]) # Save user_ids to update apple statistics after destroy @@ -73,7 +74,7 @@ class TasksController < ApplicationController redirect_to tasks_url, :notice => I18n.t('tasks.destroy.notice') end - + # assign current_user to the task and set the assignment to "accepted" # if there is already an assignment, only accepted will be set to true def accept @@ -85,23 +86,23 @@ class TasksController < ApplicationController end redirect_to user_tasks_path, :notice => I18n.t('tasks.accept.notice') end - + # deletes assignment between current_user and given task def reject Task.find(params[:id]).users.delete(current_user) redirect_to :action => "index" end - + def set_done Task.find(params[:id]).update_attribute :done, true redirect_to tasks_url, :notice => I18n.t('tasks.set_done.notice') end - + # Shows all tasks, which are already done def archive @tasks = Task.done.page(params[:page]).per(@per_page).order('tasks.updated_on DESC').includes(assignments: :user) end - + # shows workgroup (normal group) to edit weekly_tasks_template def workgroup @group = Group.find(params[:workgroup_id]) diff --git a/app/models/periodic_task_group.rb b/app/models/periodic_task_group.rb index 5e8d2e69..b7ccceeb 100644 --- a/app/models/periodic_task_group.rb +++ b/app/models/periodic_task_group.rb @@ -25,6 +25,22 @@ class PeriodicTaskGroup < ActiveRecord::Base end end + def update_tasks_including(template_task, prev_due_date) + group_tasks = tasks + [template_task] + due_date_delta = template_task.due_date - prev_due_date + tasks.each do |task| + task.update!(name: template_task.name, + description: template_task.description, + duration: template_task.duration, + required_users: template_task.required_users, + workgroup: template_task.workgroup, + due_date: task.due_date + due_date_delta) + end + group_tasks.each do |task| + task.update_columns(periodic_task_group_id: self.id) + end + end + protected # @return [Number] Number of days between two periodic tasks diff --git a/app/views/tasks/_form.html.haml b/app/views/tasks/_form.html.haml index 78925c41..077836ba 100644 --- a/app/views/tasks/_form.html.haml +++ b/app/views/tasks/_form.html.haml @@ -1,31 +1,11 @@ -- content_for :javascript do - :javascript - $(function() { - $("#task_user_list").tokenInput("#{users_path(:format => :json)}", { - crossDomain: false, - prePopulate: $("#task_user_list").data("pre"), - hintText: '#{escape_javascript(t('.search.hint'))}', - noResultText: '#{escape_javascript(t('.search.noresult'))}', - searchingText: '#{escape_javascript(t('.search.placeholder'))}', - theme: 'facebook' - }); - }); - -- content_for :sidebar do - = render "shared/workgroup_members" - -= simple_form_for @task do |f| - = f.hidden_field :current_user_id - = f.input :name - = f.input :description, as: :text, input_html: {rows: 10} - = f.input :duration, :as => :select, :collection => 1..3 - = f.input :user_list, :as => :string, :input_html => { 'data-pre' => @task.users.map(&:token_attributes).to_json } - = f.input :required_users - = f.association :workgroup - = f.input :due_date, as: :date_picker - = f.input :done - .form-actions - = f.submit class: 'btn btn-primary' - - if @task.new_record? - = f.submit t('.submit.periodic'), name: 'periodic', class: 'btn' - = link_to t('ui.or_cancel'), :back += form.hidden_field :current_user_id += form.input :name += form.input :description, as: :text, input_html: {rows: 10} += form.input :duration, :as => :select, :collection => 1..3 +- unless local_assigns[:periodic] + = form.input :user_list, :as => :string, :input_html => { 'data-pre' => form.object.users.map(&:token_attributes).to_json } += form.input :required_users += form.association :workgroup += form.input :due_date, as: :date_picker +- unless local_assigns[:periodic] + = form.input :done diff --git a/app/views/tasks/_form_sidebar.html.haml b/app/views/tasks/_form_sidebar.html.haml new file mode 100644 index 00000000..c32a6c94 --- /dev/null +++ b/app/views/tasks/_form_sidebar.html.haml @@ -0,0 +1,15 @@ +- content_for :javascript do + :javascript + $(function() { + $("#task_user_list").tokenInput("#{users_path(:format => :json)}", { + crossDomain: false, + prePopulate: $("#task_user_list").data("pre"), + hintText: '#{escape_javascript(t('.search.hint'))}', + noResultText: '#{escape_javascript(t('.search.noresult'))}', + searchingText: '#{escape_javascript(t('.search.placeholder'))}', + theme: 'facebook' + }); + }); + +- content_for :sidebar do + = render "shared/workgroup_members" diff --git a/app/views/tasks/edit.haml b/app/views/tasks/edit.haml index 624324db..35cd9cb5 100644 --- a/app/views/tasks/edit.haml +++ b/app/views/tasks/edit.haml @@ -1,3 +1,15 @@ -- title t('.title') +- title @periodic ? t('.title_periodic') : t('.title') -= render 'form' +- if @task.periodic? && !@periodic + .alert.alert-info= raw t('tasks.edit.warning_periodic') + += render 'form_sidebar' + += simple_form_for @task do |form| + = render 'form', form: form, periodic: @periodic + .form-actions + - if @periodic + = form.submit t('.submit_periodic'), name: 'periodic', class: 'btn btn-primary' + - else + = form.submit class: 'btn btn-primary' + = link_to t('ui.or_cancel'), :back diff --git a/app/views/tasks/new.haml b/app/views/tasks/new.haml index 624324db..277480cf 100644 --- a/app/views/tasks/new.haml +++ b/app/views/tasks/new.haml @@ -1,3 +1,10 @@ - title t('.title') -= render 'form' += render 'form_sidebar' + += simple_form_for @task do |form| + = render 'form', form: form, periodic: nil + .form-actions + = form.submit class: 'btn btn-primary' + = form.submit t('.submit_periodic'), name: 'periodic', class: 'btn' + = link_to t('ui.or_cancel'), :back diff --git a/app/views/tasks/show.haml b/app/views/tasks/show.haml index 93f61269..ba7a36d0 100644 --- a/app/views/tasks/show.haml +++ b/app/views/tasks/show.haml @@ -10,7 +10,7 @@ %dd= simple_format(@task.description) - if @task.due_date.present? %dt= heading_helper Task, :due_date - %dd + %dd = format_date(@task.due_date) - if @task.periodic? %i.icon-repeat{title: t('tasks.repeated')} @@ -30,8 +30,14 @@ - unless @task.done? = link_to t('.mark_done'), set_done_task_path(@task), method: :post, class: 'btn' = link_to t('ui.edit'), edit_task_path(@task), class: 'btn' - = link_to t('ui.delete'), task_path(@task), :method => :delete, :data => {:confirm => t('.confirm_delete_single')}, - class: 'btn btn-danger' - if @task.periodic? - = link_to t('.delete_group'), task_path(@task, periodic: true), method: :delete, - :data => {confirm: t('.confirm_delete_group')}, class: 'btn btn-danger' + = link_to edit_task_path(@task, periodic: true), class: 'btn' do + %i.icon.icon-repeat + = t('.edit_group') + = link_to t('ui.delete'), task_path(@task), method: :delete, class: 'btn btn-danger', + data: {confirm: @task.periodic? ? t('.confirm_delete_single_from_group') : t('.confirm_delete_single')} + - if @task.periodic? + = link_to task_path(@task, periodic: true), method: :delete, class: 'btn btn-danger', + data: {confirm: t('.confirm_delete_group')} do + %i.icon.icon-repeat + = t('.delete_group') diff --git a/config/locales/en.yml b/config/locales/en.yml index cda830a9..9c59a84f 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1624,6 +1624,8 @@ en: notice: Task has been deleted edit: title: Edit task + title_periodic: Edit recurring task + submit_periodic: Save recurring task warning_periodic: "Warning: This task is part of a group of recurring tasks. When saving it will be excluded from the group and it will be converted to a regular task." error_not_found: No workgroup found form: @@ -1654,6 +1656,7 @@ en: pages: Pages new: title: Create new task + submit_periodic: Create recurring task repeated: Task is recurring set_done: notice: The state of the task has been updated @@ -1661,7 +1664,9 @@ en: accept_task: Accept task confirm_delete_group: Really delete this and all subsequent tasks? confirm_delete_single: Are you sure you want to delete the task? + confirm_delete_single_from_group: Are you sure you want to delete this task (and keep related recurring tasks)? delete_group: Delete task and subsequent + edit_group: Edit recurring hours: "%{count}h" mark_done: Mark task as done reject_task: Reject task