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
d14e6e6a
Commit
d14e6e6a
authored
Apr 27, 2017
by
Clement Ho
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'multiple-assignees-fe-sidebar' into multiple-assignees-issue-board-sidebar
parents
4e473119
d3f7e156
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
58 additions
and
63 deletions
+58
-63
app/assets/javascripts/sidebar/components/assignees/assignees.js
...ets/javascripts/sidebar/components/assignees/assignees.js
+6
-3
app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.js
...scripts/sidebar/components/assignees/sidebar_assignees.js
+26
-19
app/assets/javascripts/sidebar/sidebar_mediator.js
app/assets/javascripts/sidebar/sidebar_mediator.js
+7
-18
app/assets/javascripts/sidebar/stores/sidebar_store.js
app/assets/javascripts/sidebar/stores/sidebar_store.js
+18
-22
app/views/shared/issuable/_sidebar.html.haml
app/views/shared/issuable/_sidebar.html.haml
+1
-1
No files found.
app/assets/javascripts/sidebar/components/assignees/assignees.js
View file @
d14e6e6a
...
...
@@ -79,6 +79,9 @@ export default {
renderAssignee
(
index
)
{
return
!
this
.
showLess
||
(
index
<
this
.
defaultRenderCount
&&
this
.
showLess
);
},
avatarUrl
(
user
)
{
return
user
.
avatarUrl
||
user
.
avatar_url
;
},
assigneeUrl
(
user
)
{
return
`
${
this
.
rootPath
}${
user
.
username
}
`
;
},
...
...
@@ -118,7 +121,7 @@ export default {
width="24"
class="avatar avatar-inline s24"
:alt="assigneeAlt(user)"
:src="
user.avatarUrl
"
:src="
avatarUrl(user)
"
/>
<span class="author">
{{ user.name }}
...
...
@@ -158,7 +161,7 @@ export default {
width="32"
class="avatar avatar-inline s32"
:alt="assigneeAlt(firstUser)"
:src="
firstUser.avatarUrl
"
:src="
avatarUrl(firstUser)
"
/>
<span class="author">
{{ firstUser.name }}
...
...
@@ -185,7 +188,7 @@ export default {
width="32"
class="avatar avatar-inline s32"
:alt="assigneeAlt(user)"
:src="
user.avatarUrl
"
:src="
avatarUrl(user)
"
/>
</a>
</div>
...
...
app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.js
View file @
d14e6e6a
/* global Flash */
import
AssigneeTitle
from
'
./assignee_title
'
;
import
Assignees
from
'
./assignees
'
;
...
...
@@ -20,39 +22,45 @@ export default {
'
assignee-title
'
:
AssigneeTitle
,
assignees
:
Assignees
,
},
computed
:
{
numberOfAssignees
()
{
return
this
.
store
.
selectedUserIds
.
length
;
},
},
methods
:
{
assignSelf
()
{
// Notify gl dropdown that we are now assigning to current user
this
.
$el
.
parentElement
.
dispatchEvent
(
new
Event
(
'
assignYourself
'
));
this
.
mediator
.
assignYourself
();
this
.
save
User
s
();
this
.
save
Assignee
s
();
},
save
User
s
()
{
save
Assignee
s
()
{
this
.
loading
=
true
;
function
setLoadingFalse
()
{
this
.
loading
=
false
;
}
const
setLoadingFalseWrapper
=
setLoadingFalse
.
bind
(
this
);
this
.
mediator
.
saveSelectedUsers
(
this
.
field
)
.
then
(
setLoadingFalseWrapper
)
.
catch
(
setLoadingFalseWrapper
);
this
.
mediator
.
saveAssignees
(
this
.
field
)
.
then
(
setLoadingFalse
.
bind
(
this
))
.
catch
(()
=>
{
setLoadingFalse
();
return
new
Flash
(
'
Error occurred when saving assignees
'
);
});
},
},
created
()
{
this
.
removeAssignee
=
this
.
store
.
removeAssignee
.
bind
(
this
.
store
);
this
.
addAssignee
=
this
.
store
.
addAssignee
.
bind
(
this
.
store
);
this
.
removeAllAssignees
=
this
.
store
.
removeAllAssignees
.
bind
(
this
.
store
);
// Get events from glDropdown
eventHub
.
$on
(
'
sidebar.removeUser
'
,
this
.
store
.
removeUserId
.
bind
(
this
.
store
));
eventHub
.
$on
(
'
sidebar.addUser
'
,
this
.
store
.
addUserId
.
bind
(
this
.
store
));
eventHub
.
$on
(
'
sidebar.removeAllUsers
'
,
this
.
store
.
removeAllUserIds
.
bind
(
this
.
store
));
eventHub
.
$on
(
'
sidebar.saveUsers
'
,
this
.
saveUsers
);
eventHub
.
$on
(
'
sidebar.removeAssignee
'
,
this
.
removeAssignee
);
eventHub
.
$on
(
'
sidebar.addAssignee
'
,
this
.
addAssignee
);
eventHub
.
$on
(
'
sidebar.removeAllAssignees
'
,
this
.
removeAllAssignees
);
eventHub
.
$on
(
'
sidebar.saveAssignees
'
,
this
.
saveAssignees
);
},
beforeDestroy
()
{
eventHub
.
$off
(
'
sidebar.removeAssignee
'
,
this
.
removeAssignee
);
eventHub
.
$off
(
'
sidebar.addAssignee
'
,
this
.
addAssignee
);
eventHub
.
$off
(
'
sidebar.removeAllAssignees
'
,
this
.
removeAllAssignees
);
eventHub
.
$off
(
'
sidebar.saveAssignees
'
,
this
.
saveAssignees
);
},
beforeMount
()
{
this
.
field
=
this
.
$el
.
dataset
.
field
;
...
...
@@ -60,15 +68,14 @@ export default {
template
:
`
<div>
<assignee-title
:number-of-assignees="store.
selectedUserId
s.length"
:number-of-assignees="store.
assignee
s.length"
:loading="loading"
:editable="store.editable"
/>
<assignees
class="value"
v-if="!loading"
:root-path="store.rootPath"
:users="store.
renderedUser
s"
:users="store.
assignee
s"
@assign-self="assignSelf"
/>
</div>
...
...
app/assets/javascripts/sidebar/sidebar_mediator.js
View file @
d14e6e6a
...
...
@@ -15,33 +15,22 @@ export default class SidebarMediator {
}
assignYourself
()
{
this
.
store
.
add
UserId
(
this
.
store
.
currentUserId
);
this
.
store
.
add
Assignee
(
this
.
store
.
currentUser
);
}
saveSelectedUsers
(
field
)
{
return
new
Promise
((
resolve
,
reject
)
=>
{
const
selected
=
this
.
store
.
selectedUserIds
;
saveAssignees
(
field
)
{
const
selected
=
this
.
store
.
assignees
.
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]
this
.
service
.
update
(
field
,
selected
.
length
===
0
?
[
0
]
:
selected
)
.
then
((
response
)
=>
{
const
data
=
response
.
json
();
this
.
store
.
processUserData
(
data
);
resolve
();
})
.
catch
(()
=>
{
reject
();
return
new
Flash
(
'
Error occurred when saving users
'
);
});
});
// If there are no ids, that means we have to unassign (which is id = 0)
// And it only accepts an array, hence [0]
return
this
.
service
.
update
(
field
,
selected
.
length
===
0
?
[
0
]
:
selected
);
}
fetch
()
{
this
.
service
.
get
()
.
then
((
response
)
=>
{
const
data
=
response
.
json
();
this
.
store
.
process
User
Data
(
data
);
this
.
store
.
process
Assignee
Data
(
data
);
this
.
store
.
processTimeTrackingData
(
data
);
})
.
catch
(()
=>
new
Flash
(
'
Error occured when fetching sidebar data
'
));
...
...
app/assets/javascripts/sidebar/stores/sidebar_store.js
View file @
d14e6e6a
export
default
class
SidebarStore
{
constructor
(
store
)
{
if
(
!
SidebarStore
.
singleton
)
{
const
{
currentUser
Id
,
rootPath
,
editable
}
=
store
;
this
.
currentUser
Id
=
currentUserId
;
const
{
currentUser
,
rootPath
,
editable
}
=
store
;
this
.
currentUser
=
currentUser
;
this
.
rootPath
=
rootPath
;
this
.
editable
=
editable
;
this
.
timeEstimate
=
0
;
this
.
totalTimeSpent
=
0
;
this
.
humanTimeEstimate
=
''
;
this
.
humanTimeSpent
=
''
;
this
.
selectedUserIds
=
[];
this
.
renderedUsers
=
[];
this
.
assignees
=
[];
SidebarStore
.
singleton
=
this
;
}
...
...
@@ -18,17 +17,9 @@ export default class SidebarStore {
return
SidebarStore
.
singleton
;
}
process
User
Data
(
data
)
{
process
Assignee
Data
(
data
)
{
if
(
data
.
assignees
)
{
this
.
renderedUsers
=
data
.
assignees
.
map
(
a
=>
{
a
.
avatarUrl
=
a
.
avatar_url
;
delete
a
.
avatar_url
;
return
a
;
});
this
.
removeAllUserIds
();
this
.
renderedUsers
.
map
(
u
=>
this
.
addUserId
(
u
.
id
));
this
.
assignees
=
data
.
assignees
;
}
}
...
...
@@ -39,18 +30,23 @@ export default class SidebarStore {
this
.
humanTimeSpent
=
data
.
human_time_spent
;
}
addUserId
(
id
)
{
// Prevent duplicate user id's from being added
if
(
this
.
selectedUserIds
.
indexOf
(
id
)
===
-
1
)
{
this
.
selectedUserIds
.
push
(
id
);
addAssignee
(
assignee
)
{
if
(
!
this
.
findAssignee
(
assignee
))
{
this
.
assignees
.
push
(
assignee
);
}
}
removeUserId
(
id
)
{
this
.
selectedUserIds
=
this
.
selectedUserIds
.
filter
(
uid
=>
uid
!==
id
);
findAssignee
(
findAssignee
)
{
return
this
.
assignees
.
filter
(
assignee
=>
assignee
.
id
===
findAssignee
.
id
)[
0
];
}
removeAssignee
(
removeAssignee
)
{
if
(
removeAssignee
)
{
this
.
assignees
=
this
.
assignees
.
filter
(
assignee
=>
assignee
.
id
!==
removeAssignee
.
id
);
}
}
removeAll
UserId
s
()
{
this
.
selectedUserId
s
=
[];
removeAll
Assignee
s
()
{
this
.
assignee
s
=
[];
}
}
app/views/shared/issuable/_sidebar.html.haml
View file @
d14e6e6a
...
...
@@ -219,7 +219,7 @@
gl
.
sidebarOptions
=
{
endpoint
:
"
#{
issuable_json_path
(
issuable
)
}
"
,
editable
:
#{
can_edit_issuable
?
true
:
false
}
,
currentUser
Id
:
#{
current_user
.
id
}
,
currentUser
:
#{
current_user
.
to_json
(
only:
[
:username
,
:id
,
:name
],
methods: :avatar_url
)
}
,
rootPath
:
"
#{
root_path
}
"
};
...
...
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