Improved manual todos

Based on feedback from !4502
This commit is contained in:
Phil Hughes 2016-06-17 09:01:03 +01:00
parent f011b86beb
commit 85fab13eba
8 changed files with 85 additions and 28 deletions

View file

@ -51,11 +51,15 @@ class @Sidebar
$this = $(e.currentTarget)
$todoLoading = $('.js-issuable-todo-loading')
$btnText = $('.js-issuable-todo-text', $this)
ajaxType = if $this.attr('data-id') then 'PATCH' else 'POST'
ajaxUrlExtra = if $this.attr('data-id') then "/#{$this.attr('data-id')}" else ''
ajaxType = if $this.attr('data-delete-path') then 'DELETE' else 'POST'
if $this.attr('data-delete-path')
url = "#{$this.attr('data-delete-path')}"
else
url = "#{$this.data('url')}"
$.ajax(
url: "#{$this.data('url')}#{ajaxUrlExtra}"
url: url
type: ajaxType
dataType: 'json'
data:
@ -82,15 +86,15 @@ class @Sidebar
else
$todoPendingCount.removeClass 'hidden'
if data.todo?
if data.delete_path?
$btn
.attr 'aria-label', $btn.data('mark-text')
.attr 'data-id', data.todo.id
.attr 'data-delete-path', data.delete_path
$btnText.text $btn.data('mark-text')
else
$btn
.attr 'aria-label', $btn.data('todo-text')
.removeAttr 'data-id'
.removeAttr 'data-delete-path'
$btnText.text $btn.data('todo-text')
sidebarDropdownLoading: (e) ->

View file

@ -1,18 +1,13 @@
class Projects::TodosController < Projects::ApplicationController
before_action :authorize_read_issue!, only: [:create]
def create
todos = TodoService.new.mark_todo(issuable, current_user)
todo = TodoService.new.mark_todo(issuable, current_user)
render json: {
todo: todos,
count: current_user.todos.pending.count,
}
end
def update
current_user.todos.find_by_id(params[:id]).update(state: :done)
render json: {
count: current_user.todos.pending.count,
todo: todo,
count: TodosFinder.new(current_user, state: :pending).execute.count,
delete_path: dashboard_todo_path(todo)
}
end
@ -22,7 +17,13 @@ class Projects::TodosController < Projects::ApplicationController
@issuable ||= begin
case params[:issuable_type]
when "issue"
@project.issues.find(params[:issuable_id])
issue = @project.issues.find(params[:issuable_id])
if can?(current_user, :read_issue, issue)
issue
else
render_404
end
when "merge_request"
@project.merge_requests.find(params[:issuable_id])
end

View file

@ -67,9 +67,9 @@ module IssuablesHelper
end
end
def has_todo(issuable)
unless current_user.nil?
current_user.todos.find_by(target_id: issuable.id, state: :pending)
def issuable_todo(issuable)
if issuable
current_user.todos.find_by(target: issuable, state: :pending)
end
end

View file

@ -12,7 +12,7 @@ module TodosHelper
when Todo::ASSIGNED then 'assigned you'
when Todo::MENTIONED then 'mentioned you on'
when Todo::BUILD_FAILED then 'The build failed for your'
when Todo::MARKED then 'marked this as a Todo for'
when Todo::MARKED then 'added a todo for'
end
end

View file

@ -1,4 +1,4 @@
- todo = has_todo(issuable)
- todo = issuable_todo(issuable)
%aside.right-sidebar{ class: sidebar_gutter_collapsed_class }
.issuable-sidebar
- can_edit_issuable = can?(current_user, :"admin_#{issuable.to_ability_name}", @project)
@ -9,12 +9,12 @@
%a.gutter-toggle.pull-right.js-sidebar-toggle{ role: "button", href: "#", aria: { label: "Toggle sidebar" } }
= sidebar_gutter_toggle_icon
- if current_user
%button.btn.btn-default.issuable-header-btn.pull-right.js-issuable-todo{ type: "button", aria: { label: (todo.nil? ? "Add Todo" : "Mark Done") }, data: { todo_text: "Add Todo", mark_text: "Mark Done", id: (todo.id unless todo.nil?), issuable: issuable.id, issuable_type: issuable.class.name.underscore, url: namespace_project_todos_path(@project.namespace, @project) } }
%button.btn.btn-default.issuable-header-btn.pull-right.js-issuable-todo{ type: "button", aria: { label: (todo.nil? ? "Add Todo" : "Mark Done") }, data: { todo_text: "Add Todo", mark_text: "Mark Done", id: (todo.id unless todo.nil?), issuable: issuable.id, issuable_type: issuable.class.name.underscore, url: namespace_project_todos_path(@project.namespace, @project), delete_path: (dashboard_todo_path(todo) if todo) } }
%span.js-issuable-todo-text
- if todo.nil?
Add Todo
- else
- if todo
Mark Done
- else
Add Todo
= icon('spin spinner', class: 'hidden js-issuable-todo-loading')
= form_for [@project.namespace.becomes(Namespace), @project, issuable], remote: true, format: :json, html: {class: 'issuable-context-form inline-update js-issuable-update'} do |f|

View file

@ -797,7 +797,7 @@ Rails.application.routes.draw do
end
end
resources :todos, only: [:create, :update], constraints: { id: /\d+/ }
resources :todos, only: [:create, :update]
resources :uploads, only: [:create] do
collection do

View file

@ -0,0 +1,42 @@
require('spec_helper')
describe Projects::TodosController do
let(:user) { create(:user) }
let(:project) { create(:project) }
let(:issue) { create(:issue, project: project) }
describe 'POST #create' do
before do
sign_in(user)
project.team << [user, :developer]
end
it 'should create todo for issue' do
expect do
post(:create, namespace_id: project.namespace.path,
project_id: project.path,
issuable_id: issue.id,
issuable_type: "issue")
end.to change { user.todos.count }.by(1)
expect(response.status).to eq(200)
end
end
describe 'POST #create when not authorized' do
before do
sign_in(user)
end
it 'should create todo for issue' do
expect do
post(:create, namespace_id: project.namespace.path,
project_id: project.path,
issuable_id: issue.id,
issuable_type: "issue")
end.to change { user.todos.count }.by(0)
expect(response.status).to eq(404)
end
end
end

View file

@ -20,6 +20,12 @@ feature 'Manually create a todo item from issue', feature: true, js: true do
page.within '.header-content .todos-pending-count' do
expect(page).to have_content '1'
end
visit namespace_project_issue_path(project.namespace, project, issue)
page.within '.header-content .todos-pending-count' do
expect(page).to have_content '1'
end
end
it 'should mark a todo as done' do
@ -29,5 +35,9 @@ feature 'Manually create a todo item from issue', feature: true, js: true do
end
expect(page).to have_selector('.todos-pending-count', visible: false)
visit namespace_project_issue_path(project.namespace, project, issue)
expect(page).to have_selector('.todos-pending-count', visible: false)
end
end