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
9b156ad3
Commit
9b156ad3
authored
Mar 23, 2017
by
Clement Ho
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[skip ci] add collapsed sidebar assignees
parent
29ffdb55
Changes
17
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
189 additions
and
29 deletions
+189
-29
app/assets/javascripts/right_sidebar.js
app/assets/javascripts/right_sidebar.js
+1
-1
app/assets/javascripts/users_select.js
app/assets/javascripts/users_select.js
+4
-0
app/assets/javascripts/vue_sidebar_assignees/components/assignee_title.js
...cripts/vue_sidebar_assignees/components/assignee_title.js
+2
-1
app/assets/javascripts/vue_sidebar_assignees/components/collapsed/multiple_assignees.js
...ebar_assignees/components/collapsed/multiple_assignees.js
+41
-0
app/assets/javascripts/vue_sidebar_assignees/components/collapsed/no_assignee.js
...vue_sidebar_assignees/components/collapsed/no_assignee.js
+11
-0
app/assets/javascripts/vue_sidebar_assignees/components/collapsed/single_assignee.js
...sidebar_assignees/components/collapsed/single_assignee.js
+16
-0
app/assets/javascripts/vue_sidebar_assignees/components/collapsed/two_assignees.js
...e_sidebar_assignees/components/collapsed/two_assignees.js
+25
-0
app/assets/javascripts/vue_sidebar_assignees/components/expanded/multiple_assignees.js
...debar_assignees/components/expanded/multiple_assignees.js
+0
-0
app/assets/javascripts/vue_sidebar_assignees/components/expanded/no_assignee.js
.../vue_sidebar_assignees/components/expanded/no_assignee.js
+0
-0
app/assets/javascripts/vue_sidebar_assignees/components/expanded/show_more_assignees.js
...ebar_assignees/components/expanded/show_more_assignees.js
+0
-0
app/assets/javascripts/vue_sidebar_assignees/components/expanded/single_assignee.js
..._sidebar_assignees/components/expanded/single_assignee.js
+0
-0
app/assets/javascripts/vue_sidebar_assignees/index.js
app/assets/javascripts/vue_sidebar_assignees/index.js
+34
-12
app/assets/javascripts/vue_sidebar_assignees/stores/sidebar_assignees_store.js
...s/vue_sidebar_assignees/stores/sidebar_assignees_store.js
+2
-1
app/assets/stylesheets/framework/avatar.scss
app/assets/stylesheets/framework/avatar.scss
+11
-0
app/assets/stylesheets/pages/diff.scss
app/assets/stylesheets/pages/diff.scss
+1
-8
app/assets/stylesheets/pages/issuable.scss
app/assets/stylesheets/pages/issuable.scss
+33
-0
app/views/shared/issuable/_sidebar.html.haml
app/views/shared/issuable/_sidebar.html.haml
+8
-6
No files found.
app/assets/javascripts/right_sidebar.js
View file @
9b156ad3
...
...
@@ -145,7 +145,7 @@
Sidebar
.
prototype
.
openDropdown
=
function
(
blockOrName
)
{
var
$block
;
$block
=
_
.
isString
(
blockOrName
)
?
this
.
getBlock
(
blockOrName
)
:
blockOrName
;
$block
.
find
(
'
.edit-link
'
).
trigger
(
'
click
'
);
$block
.
find
(
'
.edit-link
:not(.hidden)
'
).
trigger
(
'
click
'
);
if
(
!
this
.
isOpen
())
{
this
.
setCollapseAfterUpdate
(
$block
);
return
this
.
toggleSidebar
(
'
open
'
);
...
...
app/assets/javascripts/users_select.js
View file @
9b156ad3
...
...
@@ -262,6 +262,10 @@
}
$selectbox
.
hide
();
// Recalculate where .value is because vue might have changed it
$block
=
$selectbox
.
closest
(
'
.block
'
);
$value
=
$block
.
find
(
'
.value
'
);
// display:block overrides the hide-collapse rule
return
$value
.
css
(
'
display
'
,
''
);
},
...
...
app/assets/javascripts/vue_sidebar_assignees/components/assignee_title.js
View file @
9b156ad3
...
...
@@ -3,6 +3,7 @@ export default {
props
:
{
loading
:
{
type
:
Boolean
,
required
:
true
},
numberOfAssignees
:
{
type
:
Number
,
required
:
true
},
editable
:
{
type
:
Boolean
,
required
:
true
},
},
computed
:
{
hasMultipleAssignees
()
{
...
...
@@ -18,7 +19,7 @@ export default {
Assignee
</template>
<i aria-hidden="true" class="fa fa-spinner fa-spin block-loading" :class="{ hidden: !loading }"></i>
<a class="edit-link pull-right" href="#">Edit</a>
<a class="edit-link pull-right"
:class="{ hidden: !editable }"
href="#">Edit</a>
</div>
`
,
};
app/assets/javascripts/vue_sidebar_assignees/components/collapsed/multiple_assignees.js
0 → 100644
View file @
9b156ad3
export
default
{
name
:
'
CollapsedMultipleAssignees
'
,
props
:
{
users
:
{
type
:
Array
,
required
:
true
}
},
computed
:
{
title
()
{
const
max
=
this
.
users
.
length
>
5
?
5
:
this
.
users
.
length
;
const
firstFive
=
this
.
users
.
slice
(
0
,
max
);
const
names
=
[];
firstFive
.
forEach
((
u
)
=>
names
.
push
(
u
.
name
));
if
(
this
.
users
.
length
>
max
)
{
names
.
push
(
`+
${
this
.
users
.
length
-
max
}
more`
);
}
return
names
.
join
(
'
,
'
);
},
counter
()
{
if
(
this
.
users
.
length
>
99
)
{
return
'
99+
'
;
}
else
{
return
`+
${
this
.
users
.
length
-
1
}
`
;
}
},
},
template
:
`
<div class="sidebar-collapsed-icon sidebar-collapsed-user multiple-users"
data-container="body" data-placement="left"
data-toggle="tooltip" title="" :data-original-title="title">
<a class="author_link" :href="'/' + users[0].username">
<img width="24" class="avatar avatar-inline s24 " alt="" :src="users[0].avatarUrl">
<span class="author">{{users[0].name}}</span>
</a>
<a class="author_link" href='#'>
<span class="avatar-counter sidebar-avatar-counter">{{counter}}</span>
</a>
</div>
`
,
};
app/assets/javascripts/vue_sidebar_assignees/components/collapsed/no_assignee.js
0 → 100644
View file @
9b156ad3
export
default
{
name
:
'
CollapsedNoAssignee
'
,
props
:
{
users
:
{
type
:
Array
,
required
:
true
}
},
template
:
`
<div class="sidebar-collapsed-icon sidebar-collapsed-user">
<i aria-hidden="true" class="fa fa-user"></i>
</div>
`
,
};
app/assets/javascripts/vue_sidebar_assignees/components/collapsed/single_assignee.js
0 → 100644
View file @
9b156ad3
export
default
{
name
:
'
CollapsedSingleAssignee
'
,
props
:
{
users
:
{
type
:
Array
,
required
:
true
}
},
template
:
`
<div class="sidebar-collapsed-icon sidebar-collapsed-user"
data-container="body" data-placement="left"
data-toggle="tooltip" title="" :data-original-title="users[0].name">
<a class="author_link" :href="'/' + users[0].username">
<img width="24" class="avatar avatar-inline s24 " alt="" :src="users[0].avatarUrl">
<span class="author">{{users[0].name}}</span>
</a>
</div>
`
,
};
app/assets/javascripts/vue_sidebar_assignees/components/collapsed/two_assignees.js
0 → 100644
View file @
9b156ad3
export
default
{
name
:
'
CollapsedTwoAssignees
'
,
props
:
{
users
:
{
type
:
Array
,
required
:
true
}
},
computed
:
{
title
()
{
return
`
${
this
.
users
[
0
].
name
}
,
${
this
.
users
[
1
].
name
}
`
;
}
},
template
:
`
<div class="sidebar-collapsed-icon sidebar-collapsed-user multiple-users"
data-container="body" data-placement="left"
data-toggle="tooltip" title="" :data-original-title="title">
<a class="author_link" :href="'/' + users[0].username">
<img width="24" class="avatar avatar-inline s24 " alt="" :src="users[0].avatarUrl">
<span class="author">{{users[0].name}}</span>
</a>
<a class="author_link" :href="'/' + users[1].username">
<img width="24" class="avatar avatar-inline s24 " alt="" :src="users[1].avatarUrl">
<span class="author">{{users[1].name}}</span>
</a>
</div>
`
,
};
app/assets/javascripts/vue_sidebar_assignees/components/multiple_assignees.js
→
app/assets/javascripts/vue_sidebar_assignees/components/
expanded/
multiple_assignees.js
View file @
9b156ad3
File moved
app/assets/javascripts/vue_sidebar_assignees/components/no_assignee.js
→
app/assets/javascripts/vue_sidebar_assignees/components/
expanded/
no_assignee.js
View file @
9b156ad3
File moved
app/assets/javascripts/vue_sidebar_assignees/components/show_more_assignees.js
→
app/assets/javascripts/vue_sidebar_assignees/components/
expanded/
show_more_assignees.js
View file @
9b156ad3
File moved
app/assets/javascripts/vue_sidebar_assignees/components/single_assignee.js
→
app/assets/javascripts/vue_sidebar_assignees/components/
expanded/
single_assignee.js
View file @
9b156ad3
File moved
app/assets/javascripts/vue_sidebar_assignees/index.js
View file @
9b156ad3
import
Vue
from
'
vue
'
;
import
AssigneeTitle
from
'
./components/assignee_title
'
;
import
NoAssignee
from
'
./components/no_assignee
'
;
import
SingleAssignee
from
'
./components/single_assignee
'
;
import
MultipleAssignees
from
'
./components/multiple_assignees
'
;
import
NoAssignee
from
'
./components/expanded/no_assignee
'
;
import
SingleAssignee
from
'
./components/expanded/single_assignee
'
;
import
MultipleAssignees
from
'
./components/expanded/multiple_assignees
'
;
import
CollapsedNoAssignee
from
'
./components/collapsed/no_assignee
'
;
import
CollapsedSingleAssignee
from
'
./components/collapsed/single_assignee
'
;
import
CollapsedTwoAssignees
from
'
./components/collapsed/two_assignees
'
;
import
CollapsedMultipleAssignees
from
'
./components/collapsed/multiple_assignees
'
;
import
SidebarAssigneesService
from
'
./services/sidebar_assignees_service
'
;
import
SidebarAssigneesStore
from
'
./stores/sidebar_assignees_store
'
;
...
...
@@ -16,22 +21,24 @@ const sidebarAssigneesOptions = () => ({
const
element
=
document
.
querySelector
(
selector
);
const
path
=
element
.
dataset
.
path
;
const
field
=
element
.
dataset
.
field
;
const
editable
=
element
.
hasAttribute
(
'
data-editable
'
);
const
currentUserId
=
parseInt
(
element
.
dataset
.
userId
,
10
);
const
service
=
new
SidebarAssigneesService
(
path
,
field
);
const
assignees
=
new
SidebarAssigneesStore
(
currentUserId
,
service
);
const
assignees
=
new
SidebarAssigneesStore
(
currentUserId
,
service
,
editable
);
return
{
assignees
,
};
},
computed
:
{
numberOfAssignees
()
{
return
this
.
assignees
.
users
.
length
;
},
componentName
()
{
const
numberOfAssignees
=
this
.
assignees
.
users
.
length
;
if
(
numberOfAssignees
===
0
)
{
if
(
this
.
numberOfAssignees
===
0
)
{
return
'
no-assignee
'
;
}
else
if
(
numberOfAssignees
===
1
)
{
}
else
if
(
this
.
numberOfAssignees
===
1
)
{
return
'
single-assignee
'
;
}
else
{
return
'
multiple-assignees
'
;
...
...
@@ -39,18 +46,33 @@ const sidebarAssigneesOptions = () => ({
},
hideComponent
()
{
return
!
this
.
assignees
.
saved
;
}
},
collapsedComponentName
()
{
if
(
this
.
numberOfAssignees
===
0
)
{
return
'
collapsed-no-assignee
'
;
}
else
if
(
this
.
numberOfAssignees
===
1
)
{
return
'
collapsed-single-assignee
'
;
}
else
if
(
this
.
numberOfAssignees
===
2
)
{
return
'
collapsed-two-assignees
'
;
}
else
{
return
'
collapsed-multiple-assignees
'
;
}
},
},
components
:
{
'
no-assignee
'
:
NoAssignee
,
'
single-assignee
'
:
SingleAssignee
,
'
multiple-assignees
'
:
MultipleAssignees
,
'
assignee-title
'
:
AssigneeTitle
,
'
collapsed-single-assignee
'
:
CollapsedSingleAssignee
,
'
collapsed-no-assignee
'
:
CollapsedNoAssignee
,
'
collapsed-two-assignees
'
:
CollapsedTwoAssignees
,
'
collapsed-multiple-assignees
'
:
CollapsedMultipleAssignees
,
},
template
:
`
<div class="sidebar-assignees">
<assignee-title :numberOfAssignees="assignees.users.length" :loading="assignees.loading" />
<div>
<component :is="collapsedComponentName" :users="assignees.users" />
<assignee-title :numberOfAssignees="assignees.users.length" :loading="assignees.loading" :editable="assignees.editable"/>
<component class="value" :is="componentName" :assignees="assignees" :class="{ hidden: hideComponent }" />
</div>
`
,
...
...
app/assets/javascripts/vue_sidebar_assignees/stores/sidebar_assignees_store.js
View file @
9b156ad3
export
default
class
SidebarAssigneesStore
{
constructor
(
currentUserId
,
service
)
{
constructor
(
currentUserId
,
service
,
editable
)
{
this
.
currentUserId
=
currentUserId
;
this
.
service
=
service
;
this
.
users
=
[];
this
.
saved
=
true
;
this
.
loading
=
false
;
this
.
editable
=
editable
;
}
addUser
(
id
,
name
,
username
,
avatarUrl
,
saved
)
{
...
...
app/assets/stylesheets/framework/avatar.scss
View file @
9b156ad3
...
...
@@ -93,3 +93,14 @@
align-self
:
center
;
}
}
.avatar-counter
{
background-color
:
$gray-darkest
;
color
:
$white-light
;
border
:
1px
solid
$white-light
;
border-radius
:
1em
;
font-family
:
$regular_font
;
font-size
:
9px
;
line-height
:
17px
;
text-align
:
center
;
}
app/assets/stylesheets/pages/diff.scss
View file @
9b156ad3
...
...
@@ -557,14 +557,7 @@
.diff-comments-more-count
,
.diff-notes-collapse
{
background-color
:
$gray-darkest
;
color
:
$white-light
;
border
:
1px
solid
$white-light
;
border-radius
:
1em
;
font-family
:
$regular_font
;
font-size
:
9px
;
line-height
:
17px
;
text-align
:
center
;
@extend
.avatar-counter
;
}
.diff-notes-collapse
{
...
...
app/assets/stylesheets/pages/issuable.scss
View file @
9b156ad3
...
...
@@ -324,6 +324,22 @@
color
:
$gl-text-color
;
}
}
&
.multiple-users
{
display
:
flex
;
}
}
.sidebar-avatar-counter
{
width
:
25px
;
height
:
25px
;
border-radius
:
12px
;
line-height
:
2
.5em
;
z-index
:
1
;
position
:
relative
;
left
:
inherit
;
margin-left
:
-2px
;
margin-top
:
-1px
;
}
.sidebar-collapsed-user
{
...
...
@@ -334,6 +350,23 @@
.issuable-header-btn
{
display
:
none
;
}
.multiple-users
{
.author_link
:first-child
{
z-index
:
2
;
.avatar
{
margin-left
:
6px
;
margin-right
:
0
;
transform
:
translateX
(
2px
);
}
}
.author_link
.avatar
{
margin-left
:
0
;
transform
:
translateX
(
-2px
);
}
}
}
a
{
...
...
app/views/shared/issuable/_sidebar.html.haml
View file @
9b156ad3
...
...
@@ -24,7 +24,7 @@
=
form_for
[
@project
.
namespace
.
becomes
(
Namespace
),
@project
,
issuable
],
remote:
true
,
format: :json
,
html:
{
class:
'issuable-context-form inline-update js-issuable-update'
}
do
|
f
|
.block.assignee
-
if
issuable
.
instance_of?
(
Issue
)
#js-vue-sidebar-assignees
{
data:
{
path:
issuable_json_path
(
issuable
),
field:
"#{issuable.to_ability_name}[assignee_id]"
,
user:
{
id:
current_user
.
id
}
}
}
#js-vue-sidebar-assignees
{
data:
{
path:
issuable_json_path
(
issuable
),
field:
"#{issuable.to_ability_name}[assignee_id]"
,
'editable'
=>
can_edit_issuable
?
true
:
false
,
user:
{
id:
current_user
.
id
}
}
}
.title.hide-collapsed
Assignee
=
icon
(
'spinner spin'
,
class:
'block-loading'
,
'aria-hidden'
:
'true'
)
...
...
@@ -212,11 +212,13 @@
=
project_ref
=
clipboard_button
(
clipboard_text:
project_ref
,
title:
"Copy reference to clipboard"
,
placement:
"left"
)
-
issuable
.
assignees
.
each
do
|
assignee
|
:javascript
document
.
addEventListener
(
'
DOMContentLoaded
'
,
()
=>
{
gl
.
sidebarAssigneesOptions
.
assignees
.
addUser
(
parseInt
(
"
#{
assignee
.
id
}
"
,
10
),
"
#{
assignee
.
name
}
"
,
"
#{
assignee
.
username
}
"
,
"
#{
assignee
.
avatar_url
}
"
,
true
);
});
-
if
issuable
.
instance_of?
(
Issue
)
-
issuable
.
assignees
.
each
do
|
assignee
|
:javascript
document
.
addEventListener
(
'
DOMContentLoaded
'
,
()
=>
{
gl
.
sidebarAssigneesOptions
.
assignees
.
addUser
(
parseInt
(
"
#{
assignee
.
id
}
"
,
10
),
"
#{
assignee
.
name
}
"
,
"
#{
assignee
.
username
}
"
,
"
#{
assignee
.
avatar_url
}
"
,
true
);
});
:javascript
gl
.
IssuableResource
=
new
gl
.
SubbableResource
(
'
#{
issuable_json_path
(
issuable
)
}
'
);
...
...
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