Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
heptapod
heptapod
Commits
a6b26594f41b
Commit
9d929cb5
authored
Jul 16, 2018
by
Jarka Kadlecová
Browse files
Revert "Revert "Merge branch 'ee-5481-epic-todos' into 'master'""
This reverts commit 8717c7dad9b5a8fa21ec9a652c54718a6b4c2175.
parent
998a2ccc80b7
Changes
30
Hide whitespace changes
Inline
Side-by-side
app/assets/javascripts/pages/dashboard/todos/index/todos.js
View file @
a6b26594
...
...
@@ -39,6 +39,7 @@ export default class Todos {
}
initFilters
()
{
this
.
initFilterDropdown
(
$
(
'
.js-group-search
'
),
'
group_id
'
,
[
'
text
'
]);
this
.
initFilterDropdown
(
$
(
'
.js-project-search
'
),
'
project_id
'
,
[
'
text
'
]);
this
.
initFilterDropdown
(
$
(
'
.js-type-search
'
),
'
type
'
);
this
.
initFilterDropdown
(
$
(
'
.js-action-search
'
),
'
action_id
'
);
...
...
@@ -53,7 +54,16 @@ export default class Todos {
filterable
:
searchFields
?
true
:
false
,
search
:
{
fields
:
searchFields
},
data
:
$dropdown
.
data
(
'
data
'
),
clicked
:
()
=>
$dropdown
.
closest
(
'
form.filter-form
'
).
submit
(),
clicked
:
()
=>
{
const
$formEl
=
$dropdown
.
closest
(
'
form.filter-form
'
);
const
mutexDropdowns
=
{
group_id
:
'
project_id
'
,
project_id
:
'
group_id
'
,
};
$formEl
.
find
(
`input[name="
${
mutexDropdowns
[
fieldName
]}
"]`
).
remove
();
$formEl
.
submit
();
},
});
}
...
...
app/assets/javascripts/sidebar/components/todo_toggle/todo.vue
0 → 100644
View file @
a6b26594
<
script
>
import
{
__
}
from
'
~/locale
'
;
import
tooltip
from
'
~/vue_shared/directives/tooltip
'
;
import
Icon
from
'
~/vue_shared/components/icon.vue
'
;
import
LoadingIcon
from
'
~/vue_shared/components/loading_icon.vue
'
;
const
MARK_TEXT
=
__
(
'
Mark todo as done
'
);
const
TODO_TEXT
=
__
(
'
Add todo
'
);
export
default
{
directives
:
{
tooltip
,
},
components
:
{
Icon
,
LoadingIcon
,
},
props
:
{
issuableId
:
{
type
:
Number
,
required
:
true
,
},
issuableType
:
{
type
:
String
,
required
:
true
,
},
isTodo
:
{
type
:
Boolean
,
required
:
false
,
default
:
true
,
},
isActionActive
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
collapsed
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
},
computed
:
{
buttonClasses
()
{
return
this
.
collapsed
?
'
btn-blank btn-todo sidebar-collapsed-icon dont-change-state
'
:
'
btn btn-default btn-todo issuable-header-btn float-right
'
;
},
buttonLabel
()
{
return
this
.
isTodo
?
MARK_TEXT
:
TODO_TEXT
;
},
collapsedButtonIconClasses
()
{
return
this
.
isTodo
?
'
todo-undone
'
:
''
;
},
collapsedButtonIcon
()
{
return
this
.
isTodo
?
'
todo-done
'
:
'
todo-add
'
;
},
},
methods
:
{
handleButtonClick
()
{
this
.
$emit
(
'
toggleTodo
'
);
},
},
};
</
script
>
<
template
>
<button
v-tooltip
:class=
"buttonClasses"
:title=
"buttonLabel"
:aria-label=
"buttonLabel"
:data-issuable-id=
"issuableId"
:data-issuable-type=
"issuableType"
type=
"button"
data-container=
"body"
data-placement=
"left"
data-boundary=
"viewport"
@
click=
"handleButtonClick"
>
<icon
v-show=
"collapsed"
:css-classes=
"collapsedButtonIconClasses"
:name=
"collapsedButtonIcon"
/>
<span
v-show=
"!collapsed"
class=
"issuable-todo-inner"
>
{{
buttonLabel
}}
</span>
<loading-icon
v-show=
"isActionActive"
:inline=
"true"
/>
</button>
</
template
>
app/assets/javascripts/vue_shared/components/sidebar/toggle_sidebar.vue
View file @
a6b26594
...
...
@@ -12,6 +12,11 @@ export default {
type
:
Boolean
,
required
:
true
,
},
cssClasses
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
},
computed
:
{
tooltipLabel
()
{
...
...
@@ -30,10 +35,12 @@ export default {
<button
v-tooltip
:title=
"tooltipLabel"
:class=
"cssClasses"
type=
"button"
class=
"btn btn-blank gutter-toggle btn-sidebar-action"
data-container=
"body"
data-placement=
"left"
data-boundary=
"viewport"
@
click=
"toggle"
>
<i
...
...
app/assets/stylesheets/pages/issuable.scss
View file @
a6b26594
...
...
@@ -449,6 +449,7 @@
.todo-undone
{
color
:
$gl-link-color
;
fill
:
$gl-link-color
;
}
.author
{
...
...
app/assets/stylesheets/pages/todos.scss
View file @
a6b26594
...
...
@@ -174,6 +174,18 @@
}
}
@include
media-breakpoint-down
(
lg
)
{
.todos-filters
{
.filter-categories
{
width
:
75%
;
.filter-item
{
margin-bottom
:
10px
;
}
}
}
}
@include
media-breakpoint-down
(
xs
)
{
.todo
{
.avatar
{
...
...
@@ -199,6 +211,10 @@
}
.todos-filters
{
.filter-categories
{
width
:
auto
;
}
.dropdown-menu-toggle
{
width
:
100%
;
}
...
...
app/controllers/concerns/todos_actions.rb
0 → 100644
View file @
a6b26594
module
TodosActions
extend
ActiveSupport
::
Concern
def
create
todo
=
TodoService
.
new
.
mark_todo
(
issuable
,
current_user
)
render
json:
{
count:
TodosFinder
.
new
(
current_user
,
state: :pending
).
execute
.
count
,
delete_path:
dashboard_todo_path
(
todo
)
}
end
end
app/controllers/dashboard/todos_controller.rb
View file @
a6b26594
...
...
@@ -70,7 +70,7 @@ def todos_counts
end
def
todo_params
params
.
permit
(
:action_id
,
:author_id
,
:project_id
,
:type
,
:sort
,
:state
)
params
.
permit
(
:action_id
,
:author_id
,
:project_id
,
:type
,
:sort
,
:state
,
:group_id
)
end
def
redirect_out_of_range
(
todos
)
...
...
app/controllers/projects/todos_controller.rb
View file @
a6b26594
class
Projects::TodosController
<
Projects
::
ApplicationController
before_action
:authenticate_user!
,
only:
[
:create
]
def
create
todo
=
TodoService
.
new
.
mark_todo
(
issuable
,
current_user
)
include
Gitlab
::
Utils
::
StrongMemoize
include
TodosActions
render
json:
{
count:
TodosFinder
.
new
(
current_user
,
state: :pending
).
execute
.
count
,
delete_path:
dashboard_todo_path
(
todo
)
}
end
before_action
:authenticate_user!
,
only:
[
:create
]
private
def
issuable
@issuable
||=
begin
strong_memoize
(
:issuable
)
do
case
params
[
:issuable_type
]
when
"issue"
IssuesFinder
.
new
(
current_user
,
project_id:
@project
.
id
).
find
(
params
[
:issuable_id
])
...
...
app/finders/todos_finder.rb
View file @
a6b26594
...
...
@@ -15,6 +15,7 @@
class
TodosFinder
prepend
FinderWithCrossProjectAccess
include
FinderMethods
include
Gitlab
::
Utils
::
StrongMemoize
requires_cross_project_access
unless:
->
{
project?
}
...
...
@@ -34,9 +35,11 @@ def execute
items
=
by_author
(
items
)
items
=
by_state
(
items
)
items
=
by_type
(
items
)
items
=
by_group
(
items
)
# Filtering by project HAS TO be the last because we use
# the project IDs yielded by the todos query thus far
items
=
by_project
(
items
)
items
=
visible_to_user
(
items
)
sort
(
items
)
end
...
...
@@ -82,6 +85,10 @@ def project?
params
[
:project_id
].
present?
end
def
group?
params
[
:group_id
].
present?
end
def
project
return
@project
if
defined?
(
@project
)
...
...
@@ -100,18 +107,14 @@ def project
@project
end
def
project_ids
(
items
)
ids
=
items
.
except
(
:order
).
select
(
:project_id
)
if
Gitlab
::
Database
.
mysql?
# To make UPDATE work on MySQL, wrap it in a SELECT with an alias
ids
=
Todo
.
except
(
:order
).
select
(
'*'
).
from
(
"(
#{
ids
.
to_sql
}
) AS t"
)
def
group
strong_memoize
(
:group
)
do
Group
.
find
(
params
[
:group_id
])
end
ids
end
def
type?
type
.
present?
&&
%w(Issue MergeRequest)
.
include?
(
type
)
type
.
present?
&&
%w(Issue MergeRequest
Epic
)
.
include?
(
type
)
end
def
type
...
...
@@ -148,12 +151,37 @@ def by_author(items)
def
by_project
(
items
)
if
project?
items
.
where
(
project:
project
)
else
projects
=
Project
.
public_or_visible_to_user
(
current_user
)
items
=
items
.
where
(
project:
project
)
end
items
end
items
.
joins
(
:project
).
merge
(
projects
)
def
by_group
(
items
)
if
group?
groups
=
group
.
self_and_descendants
items
=
items
.
where
(
'project_id IN (?) OR group_id IN (?)'
,
Project
.
where
(
group:
groups
).
select
(
:id
),
groups
.
select
(
:id
)
)
end
items
end
def
visible_to_user
(
items
)
projects
=
Project
.
public_or_visible_to_user
(
current_user
)
groups
=
Group
.
public_or_visible_to_user
(
current_user
)
items
.
joins
(
'LEFT JOIN namespaces ON namespaces.id = todos.group_id'
)
.
joins
(
'LEFT JOIN projects ON projects.id = todos.project_id'
)
.
where
(
'project_id IN (?) OR group_id IN (?)'
,
projects
.
select
(
:id
),
groups
.
select
(
:id
)
)
end
def
by_state
(
items
)
...
...
app/helpers/issuables_helper.rb
View file @
a6b26594
...
...
@@ -131,6 +131,19 @@ def project_dropdown_label(project_id, default_label)
end
end
def
group_dropdown_label
(
group_id
,
default_label
)
return
default_label
if
group_id
.
nil?
return
"Any group"
if
group_id
==
"0"
group
=
::
Group
.
find_by
(
id:
group_id
)
if
group
group
.
full_name
else
default_label
end
end
def
milestone_dropdown_label
(
milestone_title
,
default_label
=
"Milestone"
)
title
=
case
milestone_title
...
...
app/helpers/todos_helper.rb
View file @
a6b26594
...
...
@@ -43,7 +43,7 @@ def todo_target_path(todo)
project_commit_path
(
todo
.
project
,
todo
.
target
,
anchor:
anchor
)
else
path
=
[
todo
.
p
roject
.
namespace
.
becomes
(
Namespace
),
todo
.
projec
t
,
todo
.
target
]
path
=
[
todo
.
p
aren
t
,
todo
.
target
]
path
.
unshift
(
:pipelines
)
if
todo
.
build_failed?
...
...
@@ -167,4 +167,12 @@ def todo_action_subject(todo)
def
show_todo_state?
(
todo
)
(
todo
.
target
.
is_a?
(
MergeRequest
)
||
todo
.
target
.
is_a?
(
Issue
))
&&
%w(closed merged)
.
include?
(
todo
.
target
.
state
)
end
def
todo_group_options
groups
=
current_user
.
authorized_groups
.
map
do
|
group
|
{
id:
group
.
id
,
text:
group
.
full_name
}
end
groups
.
unshift
({
id:
''
,
text:
'Any Group'
}).
to_json
end
end
app/models/concerns/issuable.rb
View file @
a6b26594
...
...
@@ -243,6 +243,12 @@ def open?
opened?
end
def
overdue?
return
false
unless
respond_to?
(
:due_date
)
due_date
.
try
(
:past?
)
||
false
end
def
user_notes_count
if
notes
.
loaded?
# Use the in-memory association to select and count to avoid hitting the db
...
...
app/models/group.rb
View file @
a6b26594
...
...
@@ -39,6 +39,8 @@ class Group < Namespace
has_many
:boards
has_many
:badges
,
class_name:
'GroupBadge'
has_many
:todos
accepts_nested_attributes_for
:variables
,
allow_destroy:
true
validate
:visibility_level_allowed_by_projects
...
...
@@ -82,6 +84,12 @@ def visible_to_user(user)
where
(
id:
user
.
authorized_groups
.
select
(
:id
).
reorder
(
nil
))
end
def
public_or_visible_to_user
(
user
)
where
(
'id IN (?) OR namespaces.visibility_level IN (?)'
,
user
.
authorized_groups
.
select
(
:id
),
Gitlab
::
VisibilityLevel
.
levels_for_user
(
user
))
end
def
select_for_project_authorization
if
current_scope
.
joins_values
.
include?
(
:shared_projects
)
joins
(
'INNER JOIN namespaces project_namespace ON project_namespace.id = projects.namespace_id'
)
...
...
app/models/issue.rb
View file @
a6b26594
...
...
@@ -276,10 +276,6 @@ def visible_to_user?(user = nil)
user
?
readable_by?
(
user
)
:
publicly_visible?
end
def
overdue?
due_date
.
try
(
:past?
)
||
false
end
def
check_for_spam?
project
.
public?
&&
(
title_changed?
||
description_changed?
)
end
...
...
app/models/note.rb
View file @
a6b26594
...
...
@@ -229,6 +229,10 @@ def for_project_noteable?
!
for_personal_snippet?
end
def
for_issuable?
for_issue?
||
for_merge_request?
end
def
skip_project_check?
!
for_project_noteable?
end
...
...
app/models/todo.rb
View file @
a6b26594
...
...
@@ -22,15 +22,18 @@ class Todo < ActiveRecord::Base
belongs_to
:author
,
class_name:
"User"
belongs_to
:note
belongs_to
:project
belongs_to
:group
belongs_to
:target
,
polymorphic:
true
,
touch:
true
# rubocop:disable Cop/PolymorphicAssociations
belongs_to
:user
delegate
:name
,
:email
,
to: :author
,
prefix:
true
,
allow_nil:
true
validates
:action
,
:project
,
:target_type
,
:user
,
presence:
true
validates
:action
,
:target_type
,
:user
,
presence:
true
validates
:author
,
presence:
true
validates
:target_id
,
presence:
true
,
unless: :for_commit?
validates
:commit_id
,
presence:
true
,
if: :for_commit?
validates
:project
,
presence:
true
,
unless: :group_id
validates
:group
,
presence:
true
,
unless: :project_id
scope
:pending
,
->
{
with_state
(
:pending
)
}
scope
:done
,
->
{
with_state
(
:done
)
}
...
...
@@ -44,7 +47,7 @@ class Todo < ActiveRecord::Base
state
:done
end
after_save
:keep_around_commit
after_save
:keep_around_commit
,
if: :commit_id
class
<<
self
# Priority sorting isn't displayed in the dropdown, because we don't show
...
...
@@ -79,6 +82,10 @@ def order_by_labels_priority
end
end
def
parent
project
end
def
unmergeable?
action
==
UNMERGEABLE
end
...
...
app/services/todo_service.rb
View file @
a6b26594
...
...
@@ -262,15 +262,15 @@ def create_assignment_todo(issuable, author, old_assignees = [])
end
end
def
create_mention_todos
(
p
rojec
t
,
target
,
author
,
note
=
nil
,
skip_users
=
[])
def
create_mention_todos
(
p
aren
t
,
target
,
author
,
note
=
nil
,
skip_users
=
[])
# Create Todos for directly addressed users
directly_addressed_users
=
filter_directly_addressed_users
(
p
rojec
t
,
note
||
target
,
author
,
skip_users
)
attributes
=
attributes_for_todo
(
p
rojec
t
,
target
,
author
,
Todo
::
DIRECTLY_ADDRESSED
,
note
)
directly_addressed_users
=
filter_directly_addressed_users
(
p
aren
t
,
note
||
target
,
author
,
skip_users
)
attributes
=
attributes_for_todo
(
p
aren
t
,
target
,
author
,
Todo
::
DIRECTLY_ADDRESSED
,
note
)
create_todos
(
directly_addressed_users
,
attributes
)
# Create Todos for mentioned users
mentioned_users
=
filter_mentioned_users
(
p
rojec
t
,
note
||
target
,
author
,
skip_users
)
attributes
=
attributes_for_todo
(
p
rojec
t
,
target
,
author
,
Todo
::
MENTIONED
,
note
)
mentioned_users
=
filter_mentioned_users
(
p
aren
t
,
note
||
target
,
author
,
skip_users
)
attributes
=
attributes_for_todo
(
p
aren
t
,
target
,
author
,
Todo
::
MENTIONED
,
note
)
create_todos
(
mentioned_users
,
attributes
)
end
...
...
@@ -301,36 +301,36 @@ def attributes_for_target(target)
def
attributes_for_todo
(
project
,
target
,
author
,
action
,
note
=
nil
)
attributes_for_target
(
target
).
merge!
(
project_id:
project
.
id
,
project_id:
project
&
.
id
,
author_id:
author
.
id
,
action:
action
,
note:
note
)
end
def
filter_todo_users
(
users
,
p
rojec
t
,
target
)
reject_users_without_access
(
users
,
p
rojec
t
,
target
).
uniq
def
filter_todo_users
(
users
,
p
aren
t
,
target
)
reject_users_without_access
(
users
,
p
aren
t
,
target
).
uniq
end
def
filter_mentioned_users
(
p
rojec
t
,
target
,
author
,
skip_users
=
[])
def
filter_mentioned_users
(
p
aren
t
,
target
,
author
,
skip_users
=
[])
mentioned_users
=
target
.
mentioned_users
(
author
)
-
skip_users
filter_todo_users
(
mentioned_users
,
p
rojec
t
,
target
)
filter_todo_users
(
mentioned_users
,
p
aren
t
,
target
)
end
def
filter_directly_addressed_users
(
p
rojec
t
,
target
,
author
,
skip_users
=
[])
def
filter_directly_addressed_users
(
p
aren
t
,
target
,
author
,
skip_users
=
[])
directly_addressed_users
=
target
.
directly_addressed_users
(
author
)
-
skip_users
filter_todo_users
(
directly_addressed_users
,
p
rojec
t
,
target
)
filter_todo_users
(
directly_addressed_users
,
p
aren
t
,
target
)
end
def
reject_users_without_access
(
users
,
p
rojec
t
,
target
)
if
target
.
is_a?
(
Note
)
&&
(
target
.
for_issu
e?
||
target
.
for_merge_request?
)
def
reject_users_without_access
(
users
,
p
aren
t
,
target
)
if
target
.
is_a?
(
Note
)
&&
target
.
for_issu
able?
target
=
target
.
noteable
end
if
target
.
is_a?
(
Issuable
)
select_users
(
users
,
:"read_
#{
target
.
to_ability_name
}
"
,
target
)
else
select_users
(
users
,
:read_project
,
p
rojec
t
)
select_users
(
users
,
:read_project
,
p
aren
t
)
end
end
...
...
app/views/dashboard/todos/index.html.haml
View file @
a6b26594
...
...
@@ -30,27 +30,33 @@
.todos-filters
.row-content-block.second-block
=
form_tag
todos_filter_path
(
without:
[
:project_id
,
:author_id
,
:type
,
:action_id
]),
method: :get
,
class:
'filter-form'
do
.filter-item.inline
-
if
params
[
:project_id
].
present?
=
hidden_field_tag
(
:project_id
,
params
[
:project_id
])
=
dropdown_tag
(
project_dropdown_label
(
params
[
:project_id
],
'Project'
),
options:
{
toggle_class:
'js-project-search js-filter-submit'
,
title:
'Filter by project'
,
filter:
true
,
filterInput:
'input#project-search'
,
dropdown_class:
'dropdown-menu-selectable dropdown-menu-project js-filter-submit'
,
placeholder:
'Search projects'
,
data:
{
data:
todo_projects_options
,
default_label:
'Project'
,
display:
'static'
}
})
.filter-item.inline
-
if
params
[
:author_id
].
present?
=
hidden_field_tag
(
:author_id
,
params
[
:author_id
])
=
dropdown_tag
(
user_dropdown_label
(
params
[
:author_id
],
'Author'
),
options:
{
toggle_class:
'js-user-search js-filter-submit js-author-search'
,
title:
'Filter by author'
,
filter:
true
,
filterInput:
'input#author-search'
,
dropdown_class:
'dropdown-menu-user dropdown-menu-selectable dropdown-menu-author js-filter-submit'
,
placeholder:
'Search authors'
,
data:
{
any_user:
'Any Author'
,
first_user:
(
current_user
.
username
if
current_user
),
project_id:
(
@project
.
id
if
@project
),
selected:
params
[
:author_id
],
field_name:
'author_id'
,
default_label:
'Author'
,
todo_filter:
true
,
todo_state_filter:
params
[
:state
]
||
'pending'
}
})
.filter-item.inline
-
if
params
[
:type
].
present?
=
hidden_field_tag
(
:type
,
params
[
:type
])
=
dropdown_tag
(
todo_types_dropdown_label
(
params
[
:type
],
'Type'
),
options:
{
toggle_class:
'js-type-search js-filter-submit'
,
dropdown_class:
'dropdown-menu-selectable dropdown-menu-type js-filter-submit'
,
data:
{
data:
todo_types_options
,
default_label:
'Type'
}
})
.filter-item.inline.actions-filter
-
if
params
[
:action_id
].
present?
=
hidden_field_tag
(
:action_id
,
params
[
:action_id
])
=
dropdown_tag
(
todo_actions_dropdown_label
(
params
[
:action_id
],
'Action'
),
options:
{
toggle_class:
'js-action-search js-filter-submit'
,
dropdown_class:
'dropdown-menu-selectable dropdown-menu-action js-filter-submit'
,
data:
{
data:
todo_actions_options
,
default_label:
'Action'
}
})
=
form_tag
todos_filter_path
(
without:
[
:project_id
,
:author_id
,
:type
,
:action_id
]),
method: :get
,
class:
'filter-form d-sm-flex'
do
.filter-categories.flex-fill
.filter-item.inline
-
if
params
[
:group_id
].
present?
=
hidden_field_tag
(
:group_id
,
params
[
:group_id
])
=
dropdown_tag
(
group_dropdown_label
(
params
[
:group_id
],
'Group'
),
options:
{
toggle_class:
'js-group-search js-filter-submit'
,
title:
'Filter by group'
,
filter:
true
,
filterInput:
'input#group-search'
,
dropdown_class:
'dropdown-menu-selectable dropdown-menu-group js-filter-submit'
,
placeholder:
'Search groups'
,
data:
{
data:
todo_group_options
,
default_label:
'Group'
,
display:
'static'
}
})
.filter-item.inline
-
if
params
[
:project_id
].
present?
=
hidden_field_tag
(
:project_id
,
params
[
:project_id
])
=
dropdown_tag
(
project_dropdown_label
(
params
[
:project_id
],
'Project'
),
options:
{
toggle_class:
'js-project-search js-filter-submit'
,
title:
'Filter by project'
,
filter:
true
,
filterInput:
'input#project-search'
,
dropdown_class:
'dropdown-menu-selectable dropdown-menu-project js-filter-submit'
,
placeholder:
'Search projects'
,
data:
{
data:
todo_projects_options
,
default_label:
'Project'
,
display:
'static'
}
})
.filter-item.inline
-
if
params
[
:author_id
].
present?
=
hidden_field_tag
(
:author_id
,
params
[
:author_id
])
=
dropdown_tag
(
user_dropdown_label
(
params
[
:author_id
],
'Author'
),
options:
{
toggle_class:
'js-user-search js-filter-submit js-author-search'
,
title:
'Filter by author'
,
filter:
true
,
filterInput:
'input#author-search'
,
dropdown_class:
'dropdown-menu-user dropdown-menu-selectable dropdown-menu-author js-filter-submit'
,
placeholder:
'Search authors'
,
data:
{
any_user:
'Any Author'
,
first_user:
(
current_user
.
username
if
current_user
),
project_id:
(
@project
.
id
if
@project
),
selected:
params
[
:author_id
],
field_name:
'author_id'
,
default_label:
'Author'
,
todo_filter:
true
,
todo_state_filter:
params
[
:state
]
||
'pending'
}
})
.filter-item.inline
-
if
params
[
:type
].
present?
=
hidden_field_tag
(
:type
,
params
[
:type
])
=
dropdown_tag
(
todo_types_dropdown_label
(
params
[
:type
],
'Type'
),
options:
{
toggle_class:
'js-type-search js-filter-submit'
,
dropdown_class:
'dropdown-menu-selectable dropdown-menu-type js-filter-submit'
,
data:
{
data:
todo_types_options
,
default_label:
'Type'
}
})
.filter-item.inline.actions-filter
-
if
params
[
:action_id
].
present?
=
hidden_field_tag
(
:action_id
,
params
[
:action_id
])
=
dropdown_tag
(
todo_actions_dropdown_label
(
params
[
:action_id
],
'Action'
),
options:
{
toggle_class:
'js-action-search js-filter-submit'
,
dropdown_class:
'dropdown-menu-selectable dropdown-menu-action js-filter-submit'
,
data:
{
data:
todo_actions_options
,
default_label:
'Action'
}
})
.filter-item.sort-filter
.dropdown