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
0
Merge Requests
0
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
Boxiang Sun
gitlab-ce
Commits
cd5ddc4f
Commit
cd5ddc4f
authored
6 years ago
by
Fatih Acet
Committed by
Mike Greiling
6 years ago
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Discussions redesign
parent
b5a79f15
No related merge requests found
Changes
24
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
24 changed files
with
629 additions
and
276 deletions
+629
-276
app/assets/javascripts/diffs/components/diff_discussions.vue
app/assets/javascripts/diffs/components/diff_discussions.vue
+0
-1
app/assets/javascripts/diffs/components/parallel_diff_comment_row.vue
...avascripts/diffs/components/parallel_diff_comment_row.vue
+6
-4
app/assets/javascripts/notes/components/comment_form.vue
app/assets/javascripts/notes/components/comment_form.vue
+4
-4
app/assets/javascripts/notes/components/discussion_counter.vue
...ssets/javascripts/notes/components/discussion_counter.vue
+9
-21
app/assets/javascripts/notes/components/note_actions.vue
app/assets/javascripts/notes/components/note_actions.vue
+21
-42
app/assets/javascripts/notes/components/note_awards_list.vue
app/assets/javascripts/notes/components/note_awards_list.vue
+10
-17
app/assets/javascripts/notes/components/note_header.vue
app/assets/javascripts/notes/components/note_header.vue
+7
-5
app/assets/javascripts/notes/components/noteable_discussion.vue
...sets/javascripts/notes/components/noteable_discussion.vue
+113
-57
app/assets/javascripts/notes/components/noteable_note.vue
app/assets/javascripts/notes/components/noteable_note.vue
+2
-1
app/assets/javascripts/notes/components/toggle_replies_widget.vue
...ts/javascripts/notes/components/toggle_replies_widget.vue
+94
-0
app/assets/javascripts/vue_shared/components/notes/skeleton_note.vue
...javascripts/vue_shared/components/notes/skeleton_note.vue
+1
-1
app/assets/javascripts/vue_shared/components/notes/system_note.vue
...s/javascripts/vue_shared/components/notes/system_note.vue
+1
-1
app/assets/stylesheets/framework/awards.scss
app/assets/stylesheets/framework/awards.scss
+1
-4
app/assets/stylesheets/framework/buttons.scss
app/assets/stylesheets/framework/buttons.scss
+19
-19
app/assets/stylesheets/framework/files.scss
app/assets/stylesheets/framework/files.scss
+0
-1
app/assets/stylesheets/framework/timeline.scss
app/assets/stylesheets/framework/timeline.scss
+2
-4
app/assets/stylesheets/pages/diff.scss
app/assets/stylesheets/pages/diff.scss
+2
-1
app/assets/stylesheets/pages/note_form.scss
app/assets/stylesheets/pages/note_form.scss
+13
-1
app/assets/stylesheets/pages/notes.scss
app/assets/stylesheets/pages/notes.scss
+208
-85
app/views/shared/notes/_notes_with_form.html.haml
app/views/shared/notes/_notes_with_form.html.haml
+2
-2
locale/gitlab.pot
locale/gitlab.pot
+11
-0
spec/javascripts/notes/components/noteable_discussion_spec.js
.../javascripts/notes/components/noteable_discussion_spec.js
+14
-2
spec/javascripts/notes/components/toggle_replies_widget_spec.js
...avascripts/notes/components/toggle_replies_widget_spec.js
+78
-0
spec/support/features/discussion_comments_shared_example.rb
spec/support/features/discussion_comments_shared_example.rb
+11
-3
No files found.
app/assets/javascripts/diffs/components/diff_discussions.vue
View file @
cd5ddc4f
...
...
@@ -76,7 +76,6 @@ export default {
<noteable-discussion
v-show=
"isExpanded(discussion)"
:discussion=
"discussion"
:render-header=
"false"
:render-diff-file=
"false"
:always-expanded=
"true"
:discussions-by-diff-order=
"true"
...
...
This diff is collapsed.
Click to expand it.
app/assets/javascripts/diffs/components/parallel_diff_comment_row.vue
View file @
cd5ddc4f
...
...
@@ -76,8 +76,9 @@ export default {
:class=
"className"
class=
"notes_holder"
>
<td
class=
"notes_line old"
></td>
<td
class=
"notes_content parallel old"
>
<td
class=
"notes_content parallel old"
colspan=
"2"
>
<div
v-if=
"shouldRenderDiscussionsOnLeft"
class=
"content"
...
...
@@ -95,8 +96,9 @@ export default {
line-position=
"left"
/>
</td>
<td
class=
"notes_line new"
></td>
<td
class=
"notes_content parallel new"
>
<td
class=
"notes_content parallel new"
colspan=
"2"
>
<div
v-if=
"shouldRenderDiscussionsOnRight"
class=
"content"
...
...
This diff is collapsed.
Click to expand it.
app/assets/javascripts/notes/components/comment_form.vue
View file @
cd5ddc4f
...
...
@@ -321,10 +321,10 @@ Please check your network connection and try again.`;
v-else-if=
"!canCreateNote"
:issuable-type=
"issuableTypeTitle"
/>
<
ul
<
div
v-else-if=
"canCreateNote"
class=
"notes notes-form timeline"
>
<
li
class=
"timeline-entry
"
>
<
div
class=
"timeline-entry note-form
"
>
<div
class=
"timeline-entry-inner"
>
<div
class=
"flash-container error-alert timeline-content"
></div>
<div
class=
"timeline-icon d-none d-sm-none d-md-block"
>
...
...
@@ -462,7 +462,7 @@ append-right-10 comment-type-dropdown js-comment-type-dropdown droplab-dropdown"
</form>
</div>
</div>
</
li
>
</
ul
>
</
div
>
</
div
>
</div>
</
template
>
This diff is collapsed.
Click to expand it.
app/assets/javascripts/notes/components/discussion_counter.vue
View file @
cd5ddc4f
<
script
>
import
{
mapActions
,
mapGetters
}
from
'
vuex
'
;
import
resolveSvg
from
'
icons/_icon_resolve_discussion.svg
'
;
import
resolvedSvg
from
'
icons/_icon_status_success_solid.svg
'
;
import
mrIssueSvg
from
'
icons/_icon_mr_issue.svg
'
;
import
nextDiscussionSvg
from
'
icons/_next_discussion.svg
'
;
import
Icon
from
'
~/vue_shared/components/icon.vue
'
;
import
{
pluralize
}
from
'
../../lib/utils/text_utility
'
;
import
discussionNavigation
from
'
../mixins/discussion_navigation
'
;
import
tooltip
from
'
../../vue_shared/directives/tooltip
'
;
...
...
@@ -12,6 +9,9 @@ export default {
directives
:
{
tooltip
,
},
components
:
{
Icon
,
},
mixins
:
[
discussionNavigation
],
computed
:
{
...
mapGetters
([
...
...
@@ -37,12 +37,6 @@ export default {
return
this
.
getNoteableData
.
create_issue_to_resolve_discussions_path
;
},
},
created
()
{
this
.
resolveSvg
=
resolveSvg
;
this
.
resolvedSvg
=
resolvedSvg
;
this
.
mrIssueSvg
=
mrIssueSvg
;
this
.
nextDiscussionSvg
=
nextDiscussionSvg
;
},
methods
:
{
...
mapActions
([
'
expandDiscussion
'
]),
jumpToFirstUnresolvedDiscussion
()
{
...
...
@@ -66,15 +60,9 @@ export default {
<span
:class=
"
{ 'is-active': allResolved }"
class="line-resolve-btn is-disabled"
type="button">
<span
v-if=
"allResolved"
v-html=
"resolvedSvg"
></span>
<span
v-else
v-html=
"resolveSvg"
></span>
type="button"
>
<icon
name=
"check-circle"
/>
</span>
<span
class=
"line-resolve-text"
>
{{
resolvedDiscussionCount
}}
/
{{
discussionCount
}}
{{
countText
}}
resolved
...
...
@@ -90,7 +78,7 @@ export default {
:title=
"s__('Resolve all discussions in new issue')"
data-container=
"body"
class=
"new-issue-for-discussion btn btn-default discussion-create-issue-btn"
>
<
span
v-html=
"mrIssueSvg"
></span
>
<
icon
name=
"issue-new"
/
>
</a>
</div>
<div
...
...
@@ -103,7 +91,7 @@ export default {
data-container=
"body"
class=
"btn btn-default discussion-next-btn"
@
click=
"jumpToFirstUnresolvedDiscussion"
>
<
span
v-html=
"nextDiscussionSvg"
></span
>
<
icon
name=
"comment-next"
/
>
</button>
</div>
</div>
...
...
This diff is collapsed.
Click to expand it.
app/assets/javascripts/notes/components/note_actions.vue
View file @
cd5ddc4f
<
script
>
import
{
mapGetters
}
from
'
vuex
'
;
import
emojiSmiling
from
'
icons/_emoji_slightly_smiling_face.svg
'
;
import
emojiSmile
from
'
icons/_emoji_smile.svg
'
;
import
emojiSmiley
from
'
icons/_emoji_smiley.svg
'
;
import
editSvg
from
'
icons/_icon_pencil.svg
'
;
import
resolveDiscussionSvg
from
'
icons/_icon_resolve_discussion.svg
'
;
import
resolvedDiscussionSvg
from
'
icons/_icon_status_success_solid.svg
'
;
import
ellipsisSvg
from
'
icons/_ellipsis_v.svg
'
;
import
Icon
from
'
~/vue_shared/components/icon.vue
'
;
import
tooltip
from
'
~/vue_shared/directives/tooltip
'
;
import
{
GlLoadingIcon
}
from
'
@gitlab-org/gitlab-ui
'
;
...
...
@@ -110,15 +103,6 @@ export default {
return
title
;
},
},
created
()
{
this
.
emojiSmiling
=
emojiSmiling
;
this
.
emojiSmile
=
emojiSmile
;
this
.
emojiSmiley
=
emojiSmiley
;
this
.
editSvg
=
editSvg
;
this
.
ellipsisSvg
=
ellipsisSvg
;
this
.
resolveDiscussionSvg
=
resolveDiscussionSvg
;
this
.
resolvedDiscussionSvg
=
resolvedDiscussionSvg
;
},
methods
:
{
onEdit
()
{
this
.
$emit
(
'
handleEdit
'
);
...
...
@@ -152,12 +136,7 @@ export default {
class="line-resolve-btn note-action-button"
@click="onResolve">
<template
v-if=
"!isResolving"
>
<div
v-if=
"isResolved"
v-html=
"resolvedDiscussionSvg"
></div>
<div
v-else
v-html=
"resolveDiscussionSvg"
></div>
<icon
name=
"check-circle"
/>
</
template
>
<gl-loading-icon
v-else
...
...
@@ -179,18 +158,18 @@ export default {
title=
"Add reaction"
>
<gl-loading-icon
inline
/>
<
spa
n
c
las
s=
"link-highlight award-control-icon-neutral"
v-html=
"emojiSmiling"
>
</span
>
<
spa
n
c
las
s=
"link-highlight award-control-icon-positive"
v-html=
"emojiSmiley"
>
</span
>
<
spa
n
c
las
s=
"link-highlight award-control-icon-super-positive"
v-html=
"emojiSmile"
>
</span
>
<
ico
n
c
ss-classe
s=
"link-highlight award-control-icon-neutral"
name=
"emoji_slightly_smiling_face"
/
>
<
ico
n
c
ss-classe
s=
"link-highlight award-control-icon-positive"
name=
"emoji_smiley"
/
>
<
ico
n
c
ss-classe
s=
"link-highlight award-control-icon-super-positive"
name=
"emoji_smiley"
/
>
</a>
</div>
<div
...
...
@@ -204,10 +183,10 @@ export default {
data-container=
"body"
data-placement=
"bottom"
@
click=
"onEdit"
>
<
spa
n
class=
"link-highlight
"
v-html=
"editSvg"
>
</span
>
<
ico
n
name=
"pencil
"
css-classes=
"link-highlight"
/
>
</button>
</div>
<div
...
...
@@ -240,10 +219,10 @@ export default {
data-toggle=
"dropdown"
data-container=
"body"
data-placement=
"bottom"
>
<
spa
n
c
las
s=
"icon"
v-html=
"ellipsisSvg"
>
</span
>
<
ico
n
c
ss-classe
s=
"icon"
name=
"ellipsis_v"
/
>
</button>
<ul
class=
"dropdown-menu more-actions-dropdown dropdown-open-left"
>
<li
v-if=
"canReportAsAbuse"
>
...
...
This diff is collapsed.
Click to expand it.
app/assets/javascripts/notes/components/note_awards_list.vue
View file @
cd5ddc4f
<
script
>
import
{
mapActions
,
mapGetters
}
from
'
vuex
'
;
import
emojiSmiling
from
'
icons/_emoji_slightly_smiling_face.svg
'
;
import
emojiSmile
from
'
icons/_emoji_smile.svg
'
;
import
emojiSmiley
from
'
icons/_emoji_smiley.svg
'
;
import
Icon
from
'
~/vue_shared/components/icon.vue
'
;
import
Flash
from
'
../../flash
'
;
import
{
glEmojiTag
}
from
'
../../emoji
'
;
import
tooltip
from
'
../../vue_shared/directives/tooltip
'
;
export
default
{
components
:
{
Icon
,
},
directives
:
{
tooltip
,
},
...
...
@@ -72,11 +73,6 @@ export default {
return
this
.
noteAuthorId
===
this
.
getUserData
.
id
;
},
},
created
()
{
this
.
emojiSmiling
=
emojiSmiling
;
this
.
emojiSmile
=
emojiSmile
;
this
.
emojiSmiley
=
emojiSmiley
;
},
methods
:
{
...
mapActions
([
'
toggleAwardRequest
'
]),
getAwardHTML
(
name
)
{
...
...
@@ -196,17 +192,14 @@ export default {
data-boundary="viewport"
data-placement="bottom"
type="button">
<span
class=
"award-control-icon award-control-icon-neutral"
v-html=
"emojiSmiling"
>
<span
class=
"award-control-icon award-control-icon-neutral"
>
<icon
name=
"emoji_slightly_smiling_face"
/>
</span>
<span
class=
"award-control-icon award-control-icon-positive"
v-html=
"emojiSmiley"
>
<span
class=
"award-control-icon award-control-icon-positive"
>
<icon
name=
"emoji_smiley"
/>
</span>
<span
class=
"award-control-icon award-control-icon-super-positive"
v-html=
"emojiSmile"
>
<span
class=
"award-control-icon award-control-icon-super-positive"
>
<icon
name=
"emoji_smiley"
/>
</span>
<i
aria-hidden=
"true"
...
...
This diff is collapsed.
Click to expand it.
app/assets/javascripts/notes/components/note_header.vue
View file @
cd5ddc4f
...
...
@@ -45,6 +45,9 @@ export default {
noteTimestampLink
()
{
return
`#note_
${
this
.
noteId
}
`
;
},
hasAuthor
()
{
return
this
.
author
&&
Object
.
keys
(
this
.
author
).
length
;
},
},
methods
:
{
...
mapActions
([
'
setTargetNoteHash
'
]),
...
...
@@ -76,7 +79,7 @@ export default {
</button>
</div>
<a
v-if=
"
Object.keys(author).length
"
v-if=
"
hasAuthor
"
:href=
"author.path"
>
<span
class=
"note-header-author-name"
>
{{
author
.
name
}}
</span>
...
...
@@ -92,9 +95,6 @@ export default {
</span>
<span
class=
"note-headline-light"
>
<span
class=
"note-headline-meta"
>
<template
v-if=
"actionText"
>
{{
actionText
}}
</
template
>
<span
class=
"system-note-message"
>
<slot></slot>
</span>
...
...
@@ -102,7 +102,9 @@ export default {
v-if=
"createdAt"
>
<span
class=
"system-note-separator"
>
·
<template
v-if=
"actionText"
>
{{
actionText
}}
</
template
>
</span>
<a
:href=
"noteTimestampLink"
...
...
This diff is collapsed.
Click to expand it.
app/assets/javascripts/notes/components/noteable_discussion.vue
View file @
cd5ddc4f
This diff is collapsed.
Click to expand it.
app/assets/javascripts/notes/components/noteable_note.vue
View file @
cd5ddc4f
...
...
@@ -173,7 +173,7 @@ export default {
:class=
"classNameBindings"
:data-award-url=
"note.toggle_award_path"
:data-note-id=
"note.id"
class=
"note timeline-entry"
class=
"note timeline-entry
note-wrapper
"
>
<div
class=
"timeline-entry-inner"
>
<div
class=
"timeline-icon"
>
...
...
@@ -196,6 +196,7 @@ export default {
:author=
"author"
:created-at=
"note.created_at"
:note-id=
"note.id"
action-text=
"commented"
/>
<note-actions
:author-id=
"author.id"
...
...
This diff is collapsed.
Click to expand it.
app/assets/javascripts/notes/components/toggle_replies_widget.vue
0 → 100644
View file @
cd5ddc4f
<
script
>
import
_
from
'
underscore
'
;
import
Icon
from
'
~/vue_shared/components/icon.vue
'
;
import
UserAvatarLink
from
'
~/vue_shared/components/user_avatar/user_avatar_link.vue
'
;
import
TimeAgoTooltip
from
'
~/vue_shared/components/time_ago_tooltip.vue
'
;
export
default
{
components
:
{
Icon
,
UserAvatarLink
,
TimeAgoTooltip
,
},
props
:
{
collapsed
:
{
type
:
Boolean
,
required
:
true
,
},
replies
:
{
type
:
Array
,
required
:
true
,
},
},
computed
:
{
lastReply
()
{
return
this
.
replies
[
this
.
replies
.
length
-
1
];
},
uniqueAuthors
()
{
const
authors
=
this
.
replies
.
map
(
reply
=>
reply
.
author
||
{});
return
_
.
uniq
(
authors
,
author
=>
author
.
username
);
},
className
()
{
return
this
.
collapsed
?
'
collapsed
'
:
'
expanded
'
;
},
},
methods
:
{
toggle
()
{
this
.
$emit
(
'
toggle
'
);
},
},
};
</
script
>
<
template
>
<li
:class=
"className"
class=
"replies-toggle"
>
<template
v-if=
"collapsed"
>
<icon
name=
"chevron-right"
@
click.native=
"toggle"
/>
<div>
<user-avatar-link
v-for=
"author in uniqueAuthors"
:key=
"author.username"
:link-href=
"author.path"
:img-alt=
"author.name"
:img-src=
"author.avatar_url"
:img-size=
"26"
:tooltip-text=
"author.name"
tooltip-placement=
"bottom"
/>
</div>
<button
class=
"btn btn-link js-replies-text"
type=
"button"
@
click=
"toggle"
>
{{
replies
.
length
}}
{{
n__
(
'
reply
'
,
'
replies
'
,
replies
.
length
)
}}
</button>
{{
__
(
'
Last reply by
'
)
}}
<a
:href=
"lastReply.author.path"
class=
"btn btn-link author-link"
>
{{
lastReply
.
author
.
name
}}
</a>
<time-ago-tooltip
:time=
"lastReply.created_at"
tooltip-placement=
"bottom"
/>
</
template
>
<span
v-else
class=
"collapse-replies-btn js-collapse-replies"
@
click=
"toggle"
>
<icon
name=
"chevron-down"
/>
{{ s__('Notes|Collapse replies') }}
</span>
</li>
</template>
This diff is collapsed.
Click to expand it.
app/assets/javascripts/vue_shared/components/notes/skeleton_note.vue
View file @
cd5ddc4f
...
...
@@ -10,7 +10,7 @@ export default {
</
script
>
<
template
>
<li
class=
"timeline-entry note"
>
<li
class=
"timeline-entry note
note-wrapper
"
>
<div
class=
"timeline-entry-inner"
>
<div
class=
"timeline-icon"
>
</div>
...
...
This diff is collapsed.
Click to expand it.
app/assets/javascripts/vue_shared/components/notes/system_note.vue
View file @
cd5ddc4f
...
...
@@ -76,7 +76,7 @@ export default {
<li
:id=
"noteAnchorId"
:class=
"
{ target: isTargetNote }"
class="note system-note timeline-entry">
class="note system-note timeline-entry
note-wrapper
">
<div
class=
"timeline-entry-inner"
>
<div
class=
"timeline-icon"
...
...
This diff is collapsed.
Click to expand it.
app/assets/stylesheets/framework/awards.scss
View file @
cd5ddc4f
...
...
@@ -148,10 +148,7 @@
.award-control-icon
svg
{
background
:
$award-emoji-positive-add-bg
;
path
{
fill
:
$award-emoji-positive-add-lines
;
}
fill
:
$award-emoji-positive-add-lines
;
}
.award-control-icon-neutral
{
...
...
This diff is collapsed.
Click to expand it.
app/assets/stylesheets/framework/buttons.scss
View file @
cd5ddc4f
...
...
@@ -222,6 +222,25 @@
}
}
&
.btn-text-field
{
width
:
100%
;
text-align
:
left
;
padding
:
6px
16px
;
border-color
:
$border-color
;
color
:
$gray-darkest
;
background-color
:
$gray-light
;
&
:hover
,
&
:active
,
&
:focus
{
cursor
:
text
;
box-shadow
:
none
;
border-color
:
lighten
(
$blue-300
,
20%
);
color
:
$gray-darkest
;
background-color
:
$gray-light
;
}
}
&.
dot-highlight
:
:
after
{
content
:
''
;
background-color
:
$blue-500
;
...
...
@@ -339,25 +358,6 @@
}
}
.btn-text-field
{
width
:
100%
;
text-align
:
left
;
padding
:
6px
16px
;
border-color
:
$border-color
;
color
:
$gray-darkest
;
background-color
:
$gray-light
;
&
:hover
,
&
:active
,
&
:focus
{
cursor
:
text
;
box-shadow
:
none
;
border-color
:
lighten
(
$blue-300
,
20%
);
color
:
$gray-darkest
;
background-color
:
$gray-light
;
}
}
.btn-build
{
margin-left
:
10px
;
...
...
This diff is collapsed.
Click to expand it.
app/assets/stylesheets/framework/files.scss
View file @
cd5ddc4f
...
...
@@ -36,7 +36,6 @@
text-align
:
left
;
padding
:
10px
$gl-padding
;
word-wrap
:
break-word
;
border-radius
:
$border-radius-default
$border-radius-default
0
0
;
&
.file-title-clear
{
padding-left
:
0
;
...
...
This diff is collapsed.
Click to expand it.
app/assets/stylesheets/framework/timeline.scss
View file @
cd5ddc4f
.timeline
{
@include
basic-list
;
margin
:
0
;
padding
:
0
;
list-style
:
none
;
&
:
:
before
{
@include
notes-media
(
'max'
,
map-get
(
$grid-breakpoints
,
sm
))
{
...
...
@@ -26,10 +26,8 @@
}
.timeline-entry
{
border-color
:
$white-normal
;
color
:
$gl-text-color
;
border-bottom
:
1px
solid
$border-white-light
;
background
:
$white-light
;
background-color
:
$white-light
;
.timeline-entry-inner
{
position
:
relative
;
...
...
This diff is collapsed.
Click to expand it.
app/assets/stylesheets/pages/diff.scss
View file @
cd5ddc4f
...
...
@@ -59,6 +59,7 @@
margin
:
0
;
padding
:
0
;
table-layout
:
fixed
;
border-radius
:
0
0
$border-radius-default
$border-radius-default
;
.diff-line-num
{
width
:
50px
;
...
...
@@ -859,7 +860,7 @@
}
.diff-file
.note-container
>
.new-note
,
.note-container
.discussion-notes
{
.note-container
.discussion-notes
.diff-discussions
{
margin-left
:
100px
;
border-left
:
1px
solid
$white-normal
;
}
...
...
This diff is collapsed.
Click to expand it.
app/assets/stylesheets/pages/note_form.scss
View file @
cd5ddc4f
...
...
@@ -239,6 +239,7 @@
.discussion-reply-holder
{
background-color
:
$white-light
;
padding
:
10px
16px
;
border-radius
:
0
0
$border-radius-default
$border-radius-default
;
&
.is-replying
{
padding-bottom
:
$gl-padding
;
...
...
@@ -247,10 +248,15 @@
}
.discussion-with-resolve-btn
{
@include
media-breakpoint-up
(
sm
)
{
display
:
flex
;
}
.discussion-actions
{
display
:
table
;
.btn-default
path
{
svg
{
fill
:
$gray-darkest
;
}
...
...
@@ -270,6 +276,12 @@
.btn
{
width
:
100%
;
}
.btn-text-field
{
@include
media-breakpoint-down
(
xs
)
{
margin-bottom
:
$gl-padding-8
;
}
}
}
.discussion-notes-count
{
...
...
This diff is collapsed.
Click to expand it.
app/assets/stylesheets/pages/notes.scss
View file @
cd5ddc4f
/**
* Notes
*/
$system-note-icon-size
:
32px
;
$system-note-svg-size
:
16px
;
$note-form-margin-left
:
70px
;
@-webkit-keyframes
targe3-note
{
from
{
background
:
$note-targe3-outside
;
@mixin
vertical-line
(
$left
)
{
&
:
:
before
{
content
:
''
;
border-left
:
2px
solid
$theme-gray-100
;
position
:
absolute
;
top
:
0
;
bottom
:
0
;
left
:
$left
;
}
}
50
%
{
background
:
$note-targe3-inside
;
}
.note-wrapper
{
padding
:
$gl-padding
;
}
.issuable-discussion
{
.notes.timeline
>
.timeline-entry
{
border
:
1px
solid
$border-color
;
border-radius
:
$border-radius-default
;
margin
:
$gl-padding
0
;
&
.system-note
,
&
.note-form
{
border
:
0
;
}
&
.note-form
{
margin-left
:
0
;
to
{
background
:
$note-targe3-outside
;
@include
notes-media
(
'min'
,
map-get
(
$grid-breakpoints
,
md
))
{
margin-left
:
$note-form-margin-left
;
}
.timeline-icon
{
@include
notes-media
(
'min'
,
map-get
(
$grid-breakpoints
,
sm
))
{
margin-left
:
-
$note-icon-gutter-width
;
}
}
.timeline-content
{
margin-left
:
0
;
}
}
.notes_content
{
border
:
0
;
border-top
:
1px
solid
$border-color
;
}
}
}
ul
.notes
{
.main-notes-list
{
@include
vertical-line
(
39px
);
}
.notes
{
display
:
block
;
list-style
:
none
;
margin
:
0
;
padding
:
0
;
position
:
relative
;
>
.note-discussion
{
.card
{
border
:
0
;
}
li
.note
{
border-bottom
:
1px
solid
$border-color
;
&
:first-child
{
border-radius
:
$border-radius-default
$border-radius-default
0
0
;
}
}
}
.replies-toggle
{
background-color
:
$gray-light
;
padding
:
$gl-padding-8
$gl-padding
;
.collapse-replies-btn
:hover
{
color
:
$blue-600
;
}
&
.expanded
{
border-bottom
:
1px
solid
$border-color
;
span
{
cursor
:
pointer
;
}
svg
{
position
:
relative
;
top
:
3px
;
}
}
&
.collapsed
{
color
:
$gl-text-color-secondary
;
svg
{
float
:
left
;
position
:
relative
;
top
:
$gl-padding-4
;
margin-right
:
$gl-padding-8
;
cursor
:
pointer
;
}
img
{
margin
:
-2px
4px
0
0
;
}
.author-link
{
color
:
$gl-text-color
;
}
}
.user-avatar-link
{
&
:last-child
img
{
margin-right
:
$gl-padding-8
;
}
}
.btn-link
{
border
:
0
;
vertical-align
:
baseline
;
}
}
.note-created-ago
,
.note-updated-at
{
...
...
@@ -28,8 +137,6 @@ ul.notes {
}
.discussion-body
{
padding-top
:
8px
;
.card
{
margin-bottom
:
0
;
}
...
...
@@ -46,21 +153,10 @@ ul.notes {
}
>
li
{
// .timeline-entry
padding
:
0
;
display
:
block
;
position
:
relative
;
border-bottom
:
0
;
@include
notes-media
(
'min'
,
map-get
(
$grid-breakpoints
,
sm
))
{
padding-left
:
$note-icon-gutter-width
;
}
.timeline-entry-inner
{
padding
:
$gl-padding
$gl-btn-padding
;
border-bottom
:
1px
solid
$white-normal
;
}
&
:target
,
&
.target
{
border-bottom
:
1px
solid
$white-normal
;
...
...
@@ -75,23 +171,10 @@ ul.notes {
}
}
.timeline-icon
{
@include
notes-media
(
'min'
,
map-get
(
$grid-breakpoints
,
sm
))
{
margin-left
:
-
$note-icon-gutter-width
;
}
}
.timeline-content
{
margin-left
:
$note-icon-gutter-width
;
@include
notes-media
(
'min'
,
map-get
(
$grid-breakpoints
,
sm
))
{
margin-left
:
0
;
}
}
&
.being-posted
{
pointer-events
:
none
;
opacity
:
0
.5
;
padding
:
$gl-padding
;
.dummy-avatar
{
background-color
:
$gl-gray-200
;
...
...
@@ -104,12 +187,6 @@ ul.notes {
}
}
&
.note-discussion
{
.timeline-entry-inner
{
padding
:
$gl-padding
10px
;
}
}
.editing-spinner
{
display
:
none
;
}
...
...
@@ -191,8 +268,9 @@ ul.notes {
}
.system-note
{
font-size
:
14px
;
clear
:
both
;
padding
:
6px
$gl-padding-24
;
margin
:
$gl-padding-24
0
;
background-color
:
transparent
;
.note-header-info
{
padding-bottom
:
0
;
...
...
@@ -225,17 +303,21 @@ ul.notes {
.timeline-icon
{
float
:
left
;
@include
notes-media
(
'min'
,
map-get
(
$grid-breakpoints
,
sm
))
{
margin-left
:
0
;
width
:
auto
;
}
display
:
flex
;
align-items
:
center
;
background-color
:
$white-light
;
width
:
$system-note-icon-size
;
height
:
$system-note-icon-size
;
border
:
1px
solid
$border-color
;
border-radius
:
$system-note-icon-size
;
margin
:
-6px
$gl-padding
0
0
;
svg
{
width
:
16px
;
height
:
16px
;
width
:
$system-note-svg-size
;
height
:
$system-note-svg-size
;
fill
:
$gray-darkest
;
margin-top
:
2px
;
display
:
block
;
margin
:
0
auto
;
}
}
...
...
@@ -302,10 +384,17 @@ ul.notes {
.discussion-body
.diff-file
{
.file-title
{
cursor
:
default
;
line-height
:
42px
;
padding
:
0
$gl-padding
;
border-top
:
1px
solid
$border-color
;
&
:hover
{
background-color
:
$gray-light
;
}
.btn-clipboard
{
top
:
10px
;
}
}
.line_content
{
...
...
@@ -320,6 +409,23 @@ ul.notes {
}
}
.discussion-notes
{
&
:not
(
:first-child
)
{
border-top
:
1px
solid
$white-normal
;
margin-top
:
20px
;
}
&
:not
(
:last-child
)
{
border-bottom
:
1px
solid
$white-normal
;
margin-bottom
:
20px
;
}
.system-note
{
margin
:
0
;
padding
:
$gl-padding
;
}
}
// Merge request notes in diffs
// Diff is inline
.notes_content
.note-header
.note-headline-light
{
...
...
@@ -335,7 +441,6 @@ ul.notes {
border-left
:
0
;
&
.notes_content
{
background-color
:
$gray-light
;
border-width
:
1px
0
;
padding
:
0
;
vertical-align
:
top
;
...
...
@@ -349,18 +454,6 @@ ul.notes {
}
}
.discussion-notes
{
&
:not
(
:first-child
)
{
border-top
:
1px
solid
$white-normal
;
margin-top
:
20px
;
}
&
:not
(
:last-child
)
{
border-bottom
:
1px
solid
$white-normal
;
margin-bottom
:
20px
;
}
}
.notes
{
background-color
:
$white-light
;
}
...
...
@@ -374,6 +467,30 @@ ul.notes {
}
}
.diffs
{
.discussion-notes
{
margin-left
:
0
;
border-left
:
0
;
.notes
{
position
:
relative
;
@include
vertical-line
(
52px
);
}
}
.note-wrapper
{
margin
:
$gl-padding
;
border
:
1px
solid
$border-color
;
border-radius
:
$border-radius-default
;
}
.discussion-reply-holder
{
border-radius
:
0
0
$border-radius-default
$border-radius-default
;
border-top
:
1px
solid
$border-color
;
position
:
relative
;
}
}
.discussion-header
,
.note-header-info
{
a
{
...
...
@@ -399,7 +516,17 @@ ul.notes {
}
.discussion-header
{
font-size
:
14px
;
min-height
:
72px
;
.note-header-info
{
padding-bottom
:
0
;
}
}
.unresolved
{
.note-header-info
{
margin-top
:
$gl-padding-8
;
}
}
.note-header
{
...
...
@@ -409,7 +536,7 @@ ul.notes {
.note-header-info
{
min-width
:
0
;
padding-bottom
:
8px
;
padding-bottom
:
$gl-padding-8
;
&
.discussion
{
padding-bottom
:
0
;
...
...
@@ -471,9 +598,18 @@ ul.notes {
margin-left
:
10px
;
color
:
$gray-darkest
;
@include
media-breakpoint-down
(
xs
)
{
width
:
100%
;
margin
:
$gl-padding-8
0
;
}
.btn-group
>
.discussion-next-btn
{
margin-left
:
-1px
;
}
svg
{
height
:
15px
;
}
}
.note-actions
{
...
...
@@ -585,19 +721,6 @@ ul.notes {
z-index
:
10
;
}
.discussion-body
,
.diff-file
{
.notes
.note
{
border-bottom
:
1px
solid
$white-normal
;
.timeline-entry-inner
{
padding-left
:
$gl-padding
;
padding-right
:
$gl-padding
;
border-bottom
:
0
;
}
}
}
.disabled-comment
{
background-color
:
$gray-light
;
border-radius
:
$border-radius-base
;
...
...
@@ -634,7 +757,7 @@ ul.notes {
}
.btn
{
svg
path
{
svg
{
fill
:
$gray-darkest
;
}
...
...
@@ -659,7 +782,7 @@ ul.notes {
.line-resolve-all
{
vertical-align
:
middle
;
display
:
inline-block
;
padding
:
5px
10px
6
px
;
padding
:
6px
10
px
;
background-color
:
$gray-light
;
border
:
1px
solid
$border-color
;
border-radius
:
$border-radius-default
;
...
...
This diff is collapsed.
Click to expand it.
app/views/shared/notes/_notes_with_form.html.haml
View file @
cd5ddc4f
...
...
@@ -7,8 +7,8 @@
=
render
'shared/notes/edit_form'
,
project:
@project
-
if
can_create_note?
%ul
.notes.notes-form.timeline
%li
.timeline-entry
.notes.notes-form.timeline
.timeline-entry
.timeline-entry-inner
.flash-container.timeline-content
...
...
This diff is collapsed.
Click to expand it.
locale/gitlab.pot
View file @
cd5ddc4f
...
...
@@ -3591,6 +3591,9 @@ msgstr ""
msgid "Last edited by %{name}"
msgstr ""
msgid "Last reply by"
msgstr ""
msgid "Last update"
msgstr ""
...
...
@@ -4192,6 +4195,9 @@ msgstr ""
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "Notes|Collapse replies"
msgstr ""
msgid "Notes|Show all activity"
msgstr ""
...
...
@@ -7568,6 +7574,11 @@ msgstr ""
msgid "remove due date"
msgstr ""
msgid "reply"
msgid_plural "replies"
msgstr[0] ""
msgstr[1] ""
msgid "source"
msgstr ""
...
...
This diff is collapsed.
Click to expand it.
spec/javascripts/notes/components/noteable_discussion_spec.js
View file @
cd5ddc4f
...
...
@@ -3,6 +3,7 @@ import createStore from '~/notes/stores';
import
noteableDiscussion
from
'
~/notes/components/noteable_discussion.vue
'
;
import
'
~/behaviors/markdown/render_gfm
'
;
import
{
noteableDataMock
,
discussionMock
,
notesDataMock
}
from
'
../mock_data
'
;
import
mockDiffFile
from
'
../../diffs/mock_data/diff_file
'
;
const
discussionWithTwoUnresolvedNotes
=
'
merge_requests/resolved_diff_discussion.json
'
;
...
...
@@ -33,9 +34,20 @@ describe('noteable_discussion component', () => {
expect
(
vm
.
$el
.
querySelector
(
'
.user-avatar-link
'
)).
not
.
toBeNull
();
});
it
(
'
should not render discussion header for non diff discussions
'
,
()
=>
{
expect
(
vm
.
$el
.
querySelector
(
'
.discussion-header
'
)).
toBeNull
();
});
it
(
'
should render discussion header
'
,
()
=>
{
expect
(
vm
.
$el
.
querySelector
(
'
.discussion-header
'
)).
not
.
toBeNull
();
expect
(
vm
.
$el
.
querySelector
(
'
.notes
'
).
children
.
length
).
toEqual
(
discussionMock
.
notes
.
length
);
const
discussion
=
{
...
discussionMock
};
discussion
.
diff_file
=
mockDiffFile
;
discussion
.
diff_discussion
=
true
;
const
diffDiscussionVm
=
new
Component
({
store
,
propsData
:
{
discussion
},
}).
$mount
();
expect
(
diffDiscussionVm
.
$el
.
querySelector
(
'
.discussion-header
'
)).
not
.
toBeNull
();
});
describe
(
'
actions
'
,
()
=>
{
...
...
This diff is collapsed.
Click to expand it.
spec/javascripts/notes/components/toggle_replies_widget_spec.js
0 → 100644
View file @
cd5ddc4f
import
Vue
from
'
vue
'
;
import
toggleRepliesWidget
from
'
~/notes/components/toggle_replies_widget.vue
'
;
import
mountComponent
from
'
spec/helpers/vue_mount_component_helper
'
;
import
{
note
}
from
'
../mock_data
'
;
const
deepCloneObject
=
obj
=>
JSON
.
parse
(
JSON
.
stringify
(
obj
));
describe
(
'
toggle replies widget for notes
'
,
()
=>
{
let
vm
;
let
ToggleRepliesWidget
;
const
noteFromOtherUser
=
deepCloneObject
(
note
);
noteFromOtherUser
.
author
.
username
=
'
fatihacet
'
;
const
noteFromAnotherUser
=
deepCloneObject
(
note
);
noteFromAnotherUser
.
author
.
username
=
'
mgreiling
'
;
noteFromAnotherUser
.
author
.
name
=
'
Mike Greiling
'
;
const
replies
=
[
note
,
note
,
note
,
noteFromOtherUser
,
noteFromAnotherUser
];
beforeEach
(()
=>
{
ToggleRepliesWidget
=
Vue
.
extend
(
toggleRepliesWidget
);
});
afterEach
(()
=>
{
vm
.
$destroy
();
});
describe
(
'
collapsed state
'
,
()
=>
{
beforeEach
(()
=>
{
vm
=
mountComponent
(
ToggleRepliesWidget
,
{
replies
,
collapsed
:
true
,
});
});
it
(
'
should render the collapsed
'
,
()
=>
{
const
vmTextContent
=
vm
.
$el
.
textContent
.
replace
(
/
\s\s
+/g
,
'
'
);
expect
(
vm
.
$el
.
classList
.
contains
(
'
collapsed
'
)).
toEqual
(
true
);
expect
(
vm
.
$el
.
querySelectorAll
(
'
.user-avatar-link
'
).
length
).
toEqual
(
3
);
expect
(
vm
.
$el
.
querySelector
(
'
time
'
)).
not
.
toBeNull
();
expect
(
vmTextContent
).
toContain
(
'
5 replies
'
);
expect
(
vmTextContent
).
toContain
(
`Last reply by
${
noteFromAnotherUser
.
author
.
name
}
`
);
});
it
(
'
should emit toggle event when the replies text clicked
'
,
()
=>
{
const
spy
=
spyOn
(
vm
,
'
$emit
'
);
vm
.
$el
.
querySelector
(
'
.js-replies-text
'
).
click
();
expect
(
spy
).
toHaveBeenCalledWith
(
'
toggle
'
);
});
});
describe
(
'
expanded state
'
,
()
=>
{
beforeEach
(()
=>
{
vm
=
mountComponent
(
ToggleRepliesWidget
,
{
replies
,
collapsed
:
false
,
});
});
it
(
'
should render expanded state
'
,
()
=>
{
const
vmTextContent
=
vm
.
$el
.
textContent
.
replace
(
/
\s\s
+/g
,
'
'
);
expect
(
vm
.
$el
.
querySelector
(
'
.collapse-replies-btn
'
)).
not
.
toBeNull
();
expect
(
vmTextContent
).
toContain
(
'
Collapse replies
'
);
});
it
(
'
should emit toggle event when the collapse replies text called
'
,
()
=>
{
const
spy
=
spyOn
(
vm
,
'
$emit
'
);
vm
.
$el
.
querySelector
(
'
.js-collapse-replies
'
).
click
();
expect
(
spy
).
toHaveBeenCalledWith
(
'
toggle
'
);
});
});
});
This diff is collapsed.
Click to expand it.
spec/support/features/discussion_comments_shared_example.rb
View file @
cd5ddc4f
...
...
@@ -150,17 +150,25 @@ shared_examples 'discussion comments' do |resource_name|
end
if
resource_name
==
'merge request'
let
(
:note_id
)
{
find
(
"
#{
comments_selector
}
.note"
,
match: :first
)[
'data-note-id'
]
}
let
(
:note_id
)
{
find
(
"
#{
comments_selector
}
.note:first-child"
,
match: :first
)[
'data-note-id'
]
}
let
(
:reply_id
)
{
find
(
"
#{
comments_selector
}
.note:last-child"
,
match: :first
)[
'data-note-id'
]
}
it
'shows resolved discussion when toggled'
do
find
(
"
#{
comments_selector
}
.js-vue-discussion-reply"
).
click
find
(
"
#{
comments_selector
}
.note-textarea"
).
send_keys
(
'a'
)
click_button
"Comment"
wait_for_requests
click_button
"Resolve discussion"
wait_for_requests
expect
(
page
).
to
have_selector
(
".note-row-
#{
note_id
}
"
,
visible:
true
)
refresh
click_button
"
Toggle discussion
"
click_button
"
1 reply
"
expect
(
page
).
to
have_selector
(
".note-row-
#{
note
_id
}
"
,
visible:
true
)
expect
(
page
).
to
have_selector
(
".note-row-
#{
reply
_id
}
"
,
visible:
true
)
end
end
end
...
...
This diff is collapsed.
Click to expand it.
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