Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
ccc6ab88
Commit
ccc6ab88
authored
Sep 17, 2020
by
Samantha Ming
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Revert "Merge branch 'revert-
d81fd9e9
' into 'master'"
This reverts merge request !42625
parent
015df081
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
179 additions
and
8 deletions
+179
-8
app/assets/javascripts/issuable_context.js
app/assets/javascripts/issuable_context.js
+1
-0
app/assets/javascripts/sidebar/sidebar_mediator.js
app/assets/javascripts/sidebar/sidebar_mediator.js
+12
-0
app/assets/javascripts/sidebar/stores/sidebar_store.js
app/assets/javascripts/sidebar/stores/sidebar_store.js
+29
-0
app/assets/javascripts/users_select/index.js
app/assets/javascripts/users_select/index.js
+31
-7
app/helpers/issuables_helper.rb
app/helpers/issuables_helper.rb
+6
-0
app/views/projects/merge_requests/show.html.haml
app/views/projects/merge_requests/show.html.haml
+1
-1
app/views/shared/issuable/_sidebar.html.haml
app/views/shared/issuable/_sidebar.html.haml
+5
-0
app/views/shared/issuable/_sidebar_reviewers.html.haml
app/views/shared/issuable/_sidebar_reviewers.html.haml
+56
-0
locale/gitlab.pot
locale/gitlab.pot
+6
-0
spec/helpers/issuables_helper_spec.rb
spec/helpers/issuables_helper_spec.rb
+32
-0
No files found.
app/assets/javascripts/issuable_context.js
View file @
ccc6ab88
...
...
@@ -6,6 +6,7 @@ import UsersSelect from './users_select';
export
default
class
IssuableContext
{
constructor
(
currentUser
)
{
this
.
userSelect
=
new
UsersSelect
(
currentUser
);
this
.
reviewersSelect
=
new
UsersSelect
(
currentUser
,
'
.js-reviewer-search
'
);
import
(
/* webpackChunkName: 'select2' */
'
select2/select2
'
)
.
then
(()
=>
{
...
...
app/assets/javascripts/sidebar/sidebar_mediator.js
View file @
ccc6ab88
...
...
@@ -40,6 +40,17 @@ export default class SidebarMediator {
return
this
.
service
.
update
(
field
,
data
);
}
saveReviewers
(
field
)
{
const
selected
=
this
.
store
.
reviewers
.
map
(
u
=>
u
.
id
);
// If there are no ids, that means we have to unassign (which is id = 0)
// And it only accepts an array, hence [0]
const
reviewers
=
selected
.
length
===
0
?
[
0
]
:
selected
;
const
data
=
{
reviewer_ids
:
reviewers
};
return
this
.
service
.
update
(
field
,
data
);
}
setMoveToProjectId
(
projectId
)
{
this
.
store
.
setMoveToProjectId
(
projectId
);
}
...
...
@@ -55,6 +66,7 @@ export default class SidebarMediator {
processFetchedData
(
data
)
{
this
.
store
.
setAssigneeData
(
data
);
this
.
store
.
setReviewerData
(
data
);
this
.
store
.
setTimeTrackingData
(
data
);
this
.
store
.
setParticipantsData
(
data
);
this
.
store
.
setSubscriptionsData
(
data
);
...
...
app/assets/javascripts/sidebar/stores/sidebar_store.js
View file @
ccc6ab88
...
...
@@ -18,8 +18,10 @@ export default class SidebarStore {
this
.
humanTimeSpent
=
''
;
this
.
timeTrackingLimitToHours
=
timeTrackingLimitToHours
;
this
.
assignees
=
[];
this
.
reviewers
=
[];
this
.
isFetching
=
{
assignees
:
true
,
reviewers
:
true
,
participants
:
true
,
subscriptions
:
true
,
};
...
...
@@ -42,6 +44,13 @@ export default class SidebarStore {
}
}
setReviewerData
(
data
)
{
this
.
isFetching
.
reviewers
=
false
;
if
(
data
.
reviewers
)
{
this
.
reviewers
=
data
.
reviewers
;
}
}
setTimeTrackingData
(
data
)
{
this
.
timeEstimate
=
data
.
time_estimate
;
this
.
totalTimeSpent
=
data
.
total_time_spent
;
...
...
@@ -75,20 +84,40 @@ export default class SidebarStore {
}
}
addReviewer
(
reviewer
)
{
if
(
!
this
.
findReviewer
(
reviewer
))
{
this
.
reviewers
.
push
(
reviewer
);
}
}
findAssignee
(
findAssignee
)
{
return
this
.
assignees
.
find
(
assignee
=>
assignee
.
id
===
findAssignee
.
id
);
}
findReviewer
(
findReviewer
)
{
return
this
.
reviewers
.
find
(
reviewer
=>
reviewer
.
id
===
findReviewer
.
id
);
}
removeAssignee
(
removeAssignee
)
{
if
(
removeAssignee
)
{
this
.
assignees
=
this
.
assignees
.
filter
(
assignee
=>
assignee
.
id
!==
removeAssignee
.
id
);
}
}
removeReviewer
(
removeReviewer
)
{
if
(
removeReviewer
)
{
this
.
reviewers
=
this
.
reviewers
.
filter
(
reviewer
=>
reviewer
.
id
!==
removeReviewer
.
id
);
}
}
removeAllAssignees
()
{
this
.
assignees
=
[];
}
removeAllReviewers
()
{
this
.
reviewers
=
[];
}
setAssigneesFromRealtime
(
data
)
{
this
.
assignees
=
data
;
}
...
...
app/assets/javascripts/users_select/index.js
View file @
ccc6ab88
...
...
@@ -19,6 +19,7 @@ import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
window
.
emitSidebarEvent
=
window
.
emitSidebarEvent
||
$
.
noop
;
function
UsersSelect
(
currentUser
,
els
,
options
=
{})
{
const
elsClassName
=
els
?.
toString
().
match
(
'
.(.+$)
'
)[
1
];
const
$els
=
$
(
els
||
'
.js-user-search
'
);
this
.
users
=
this
.
users
.
bind
(
this
);
this
.
user
=
this
.
user
.
bind
(
this
);
...
...
@@ -127,9 +128,16 @@ function UsersSelect(currentUser, els, options = {}) {
.
find
(
`input[name='
${
$dropdown
.
data
(
'
fieldName
'
)}
'][value=
${
firstSelectedId
}
]`
);
firstSelected
.
remove
();
emitSidebarEvent
(
'
sidebar.removeAssignee
'
,
{
id
:
firstSelectedId
,
});
if
(
$dropdown
.
hasClass
(
elsClassName
))
{
emitSidebarEvent
(
'
sidebar.removeReviewer
'
,
{
id
:
firstSelectedId
,
});
}
else
{
emitSidebarEvent
(
'
sidebar.removeAssignee
'
,
{
id
:
firstSelectedId
,
});
}
}
}
};
...
...
@@ -392,7 +400,11 @@ function UsersSelect(currentUser, els, options = {}) {
defaultLabel
,
hidden
()
{
if
(
$dropdown
.
hasClass
(
'
js-multiselect
'
))
{
emitSidebarEvent
(
'
sidebar.saveAssignees
'
);
if
(
$dropdown
.
hasClass
(
elsClassName
))
{
emitSidebarEvent
(
'
sidebar.saveReviewers
'
);
}
else
{
emitSidebarEvent
(
'
sidebar.saveAssignees
'
);
}
}
if
(
!
$dropdown
.
data
(
'
alwaysShowSelectbox
'
))
{
...
...
@@ -428,10 +440,18 @@ function UsersSelect(currentUser, els, options = {}) {
previouslySelected
.
each
((
index
,
element
)
=>
{
element
.
remove
();
});
emitSidebarEvent
(
'
sidebar.removeAllAssignees
'
);
if
(
$dropdown
.
hasClass
(
elsClassName
))
{
emitSidebarEvent
(
'
sidebar.removeAllReviewers
'
);
}
else
{
emitSidebarEvent
(
'
sidebar.removeAllAssignees
'
);
}
}
else
if
(
isActive
)
{
// user selected
emitSidebarEvent
(
'
sidebar.addAssignee
'
,
user
);
if
(
$dropdown
.
hasClass
(
elsClassName
))
{
emitSidebarEvent
(
'
sidebar.addReviewer
'
,
user
);
}
else
{
emitSidebarEvent
(
'
sidebar.addAssignee
'
,
user
);
}
// Remove unassigned selection (if it was previously selected)
const
unassignedSelected
=
$dropdown
...
...
@@ -448,7 +468,11 @@ function UsersSelect(currentUser, els, options = {}) {
}
// User unselected
emitSidebarEvent
(
'
sidebar.removeAssignee
'
,
user
);
if
(
$dropdown
.
hasClass
(
elsClassName
))
{
emitSidebarEvent
(
'
sidebar.removeReviewer
'
,
user
);
}
else
{
emitSidebarEvent
(
'
sidebar.removeAssignee
'
,
user
);
}
}
if
(
getSelected
().
find
(
u
=>
u
===
gon
.
current_user_id
))
{
...
...
app/helpers/issuables_helper.rb
View file @
ccc6ab88
...
...
@@ -386,6 +386,12 @@ module IssuablesHelper
end
end
def
reviewer_sidebar_data
(
reviewer
,
merge_request:
nil
)
{
avatar_url:
reviewer
.
avatar_url
,
name:
reviewer
.
name
,
username:
reviewer
.
username
}.
tap
do
|
data
|
data
[
:can_merge
]
=
merge_request
.
can_be_merged_by?
(
reviewer
)
if
merge_request
end
end
def
issuable_squash_option?
(
issuable
,
project
)
if
issuable
.
persisted?
issuable
.
squash
...
...
app/views/projects/merge_requests/show.html.haml
View file @
ccc6ab88
...
...
@@ -92,7 +92,7 @@
.loading.hide
.spinner.spinner-md
=
render
'shared/issuable/sidebar'
,
issuable_sidebar:
@issuable_sidebar
,
assignees:
@merge_request
.
assignees
,
source_branch:
@merge_request
.
source_branch
=
render
'shared/issuable/sidebar'
,
issuable_sidebar:
@issuable_sidebar
,
assignees:
@merge_request
.
assignees
,
reviewers:
@merge_request
.
reviewers
,
source_branch:
@merge_request
.
source_branch
-
if
@merge_request
.
can_be_reverted?
(
current_user
)
=
render
"projects/commit/change"
,
type:
'revert'
,
commit:
@merge_request
.
merge_commit
,
title:
@merge_request
.
title
...
...
app/views/shared/issuable/_sidebar.html.haml
View file @
ccc6ab88
...
...
@@ -5,6 +5,7 @@
-
signed_in
=
!!
issuable_sidebar
.
dig
(
:current_user
,
:id
)
-
can_edit_issuable
=
issuable_sidebar
.
dig
(
:current_user
,
:can_edit
)
-
add_page_startup_api_call
"
#{
issuable_sidebar
[
:issuable_json_path
]
}
?serializer=sidebar_extras"
-
reviewers
=
local_assigns
.
fetch
(
:reviewers
,
nil
)
-
if
Feature
.
enabled?
(
:vue_issuable_sidebar
,
@project
.
group
)
%aside
#js-vue-issuable-sidebar
{
data:
{
signed_in:
signed_in
,
...
...
@@ -28,6 +29,10 @@
.block.assignee.qa-assignee-block
=
render
"shared/issuable/sidebar_assignees"
,
issuable_sidebar:
issuable_sidebar
,
assignees:
assignees
-
if
reviewers
.block.reviewer.qa-reviewer-block
=
render
"shared/issuable/sidebar_reviewers"
,
issuable_sidebar:
issuable_sidebar
,
reviewers:
reviewers
=
render_if_exists
'shared/issuable/sidebar_item_epic'
,
issuable_sidebar:
issuable_sidebar
-
if
issuable_sidebar
[
:supports_milestone
]
...
...
app/views/shared/issuable/_sidebar_reviewers.html.haml
0 → 100644
View file @
ccc6ab88
-
issuable_type
=
issuable_sidebar
[
:type
]
-
signed_in
=
!!
issuable_sidebar
.
dig
(
:current_user
,
:id
)
#js-vue-sidebar-reviewers
{
data:
{
field:
issuable_type
,
signed_in:
signed_in
}
}
.title.hide-collapsed
=
_
(
'Reviewer'
)
=
loading_icon
(
css_class:
'gl-vertical-align-text-bottom'
)
.selectbox.hide-collapsed
-
if
reviewers
.
none?
=
hidden_field_tag
"
#{
issuable_type
}
[reviewer_ids][]"
,
0
,
id:
nil
-
else
-
reviewers
.
each
do
|
reviewer
|
=
hidden_field_tag
"
#{
issuable_type
}
[reviewer_ids][]"
,
reviewer
.
id
,
id:
nil
,
data:
reviewer_sidebar_data
(
reviewer
,
merge_request:
@merge_request
)
-
options
=
{
toggle_class:
'js-reviewer-search js-author-search'
,
title:
_
(
'Request review from'
),
filter:
true
,
dropdown_class:
'dropdown-menu-user dropdown-menu-selectable dropdown-menu-author'
,
placeholder:
_
(
'Search users'
),
data:
{
first_user:
issuable_sidebar
.
dig
(
:current_user
,
:username
),
current_user:
true
,
iid:
issuable_sidebar
[
:iid
],
issuable_type:
issuable_type
,
project_id:
issuable_sidebar
[
:project_id
],
author_id:
issuable_sidebar
[
:author_id
],
field_name:
"
#{
issuable_type
}
[reviewer_ids][]"
,
issue_update:
issuable_sidebar
[
:issuable_json_path
],
ability_name:
issuable_type
,
null_user:
true
,
display:
'static'
}
}
-
dropdown_options
=
reviewers_dropdown_options
(
issuable_type
)
-
title
=
dropdown_options
[
:title
]
-
options
[
:toggle_class
]
+=
' js-multiselect js-save-user-data'
-
data
=
{
field_name:
"
#{
issuable_type
}
[reviewer_ids][]"
}
-
data
[
:multi_select
]
=
true
-
data
[
'dropdown-title'
]
=
title
-
data
[
'dropdown-header'
]
=
dropdown_options
[
:data
][
:'dropdown-header'
]
-
data
[
'max-select'
]
=
dropdown_options
[
:data
][
:'max-select'
]
if
dropdown_options
[
:data
][
:'max-select'
]
-
options
[
:data
].
merge!
(
data
)
-
if
experiment_enabled?
(
:invite_members_version_a
)
&&
can_import_members?
-
options
[
:dropdown_class
]
+=
' dropdown-extended-height'
-
options
[
:footer_content
]
=
true
-
options
[
:wrapper_class
]
=
'js-sidebar-reviewer-dropdown'
=
dropdown_tag
(
title
,
options:
options
)
do
%ul
.dropdown-footer-list
%li
=
link_to
_
(
'Invite Members'
),
project_project_members_path
(
@project
),
title:
_
(
'Invite Members'
),
data:
{
'is-link'
:
true
,
'track-event'
:
'click_invite_members'
,
'track-label'
:
'edit_reviewer'
}
-
else
=
dropdown_tag
(
title
,
options:
options
)
locale/gitlab.pot
View file @
ccc6ab88
...
...
@@ -21606,6 +21606,9 @@ msgstr ""
msgid "Request parameter %{param} is missing."
msgstr ""
msgid "Request review from"
msgstr ""
msgid "Request to link SAML account must be authorized"
msgstr ""
...
...
@@ -21876,6 +21879,9 @@ msgstr ""
msgid "ReviewApp|Enable Review App"
msgstr ""
msgid "Reviewer"
msgstr ""
msgid "Reviewing"
msgstr ""
...
...
spec/helpers/issuables_helper_spec.rb
View file @
ccc6ab88
...
...
@@ -306,6 +306,38 @@ RSpec.describe IssuablesHelper do
end
end
describe
'#reviewer_sidebar_data'
do
let
(
:user
)
{
create
(
:user
)
}
subject
{
helper
.
reviewer_sidebar_data
(
user
,
merge_request:
merge_request
)
}
context
'without merge_request'
do
let
(
:merge_request
)
{
nil
}
it
'returns hash of reviewer data'
do
is_expected
.
to
eql
({
avatar_url:
user
.
avatar_url
,
name:
user
.
name
,
username:
user
.
username
})
end
end
context
'with merge_request'
do
let
(
:merge_request
)
{
build
(
:merge_request
)
}
where
(
can_merge:
[
true
,
false
])
with_them
do
before
do
allow
(
merge_request
).
to
receive
(
:can_be_merged_by?
).
and_return
(
can_merge
)
end
it
{
is_expected
.
to
include
({
can_merge:
can_merge
})}
end
end
end
describe
'#issuable_squash_option?'
do
using
RSpec
::
Parameterized
::
TableSyntax
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment