Skip to content
Snippets Groups Projects
Commit cd5ddc4f authored by Fatih Acet's avatar Fatih Acet Committed by Mike Greiling
Browse files

Discussions redesign

parent b5a79f15
No related branches found
No related tags found
No related merge requests found
Showing
with 515 additions and 271 deletions
Loading
Loading
@@ -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"
Loading
Loading
Loading
Loading
@@ -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"
Loading
Loading
@@ -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"
Loading
Loading
Loading
Loading
@@ -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">
Loading
Loading
@@ -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>
<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';
Loading
Loading
@@ -12,6 +9,9 @@ export default {
directives: {
tooltip,
},
components: {
Icon,
},
mixins: [discussionNavigation],
computed: {
...mapGetters([
Loading
Loading
@@ -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() {
Loading
Loading
@@ -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
Loading
Loading
@@ -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
Loading
Loading
@@ -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>
Loading
Loading
<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';
Loading
Loading
@@ -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');
Loading
Loading
@@ -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
Loading
Loading
@@ -179,18 +158,18 @@ export default {
title="Add reaction"
>
<gl-loading-icon inline/>
<span
class="link-highlight award-control-icon-neutral"
v-html="emojiSmiling">
</span>
<span
class="link-highlight award-control-icon-positive"
v-html="emojiSmiley">
</span>
<span
class="link-highlight award-control-icon-super-positive"
v-html="emojiSmile">
</span>
<icon
css-classes="link-highlight award-control-icon-neutral"
name="emoji_slightly_smiling_face"
/>
<icon
css-classes="link-highlight award-control-icon-positive"
name="emoji_smiley"
/>
<icon
css-classes="link-highlight award-control-icon-super-positive"
name="emoji_smiley"
/>
</a>
</div>
<div
Loading
Loading
@@ -204,10 +183,10 @@ export default {
data-container="body"
data-placement="bottom"
@click="onEdit">
<span
class="link-highlight"
v-html="editSvg">
</span>
<icon
name="pencil"
css-classes="link-highlight"
/>
</button>
</div>
<div
Loading
Loading
@@ -240,10 +219,10 @@ export default {
data-toggle="dropdown"
data-container="body"
data-placement="bottom">
<span
class="icon"
v-html="ellipsisSvg">
</span>
<icon
css-classes="icon"
name="ellipsis_v"
/>
</button>
<ul class="dropdown-menu more-actions-dropdown dropdown-open-left">
<li v-if="canReportAsAbuse">
Loading
Loading
<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,
},
Loading
Loading
@@ -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) {
Loading
Loading
@@ -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"
Loading
Loading
Loading
Loading
@@ -45,6 +45,9 @@ export default {
noteTimestampLink() {
return `#note_${this.noteId}`;
},
hasAuthor() {
return this.author && Object.keys(this.author).length;
},
},
methods: {
...mapActions(['setTargetNoteHash']),
Loading
Loading
@@ -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>
Loading
Loading
@@ -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>
Loading
Loading
@@ -102,7 +102,9 @@ export default {
v-if="createdAt"
>
<span class="system-note-separator">
&middot;
<template v-if="actionText">
{{ actionText }}
</template>
</span>
<a
:href="noteTimestampLink"
Loading
Loading
<script>
import { mapActions, mapGetters } from 'vuex';
import resolveDiscussionsSvg from 'icons/_icon_mr_issue.svg';
import nextDiscussionsSvg from 'icons/_next_discussion.svg';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import { truncateSha } from '~/lib/utils/text_utility';
import systemNote from '~/vue_shared/components/notes/system_note.vue';
import { s__ } from '~/locale';
import systemNote from '~/vue_shared/components/notes/system_note.vue';
import icon from '~/vue_shared/components/icon.vue';
import Flash from '../../flash';
import { SYSTEM_NOTE } from '../constants';
import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
import noteableNote from './noteable_note.vue';
import noteHeader from './note_header.vue';
import toggleRepliesWidget from './toggle_replies_widget.vue';
import noteSignedOutWidget from './note_signed_out_widget.vue';
import noteEditedText from './note_edited_text.vue';
import noteForm from './note_form.vue';
Loading
Loading
@@ -26,6 +26,7 @@ import tooltip from '../../vue_shared/directives/tooltip';
export default {
name: 'NoteableDiscussion',
components: {
icon,
noteableNote,
diffWithNote,
userAvatarLink,
Loading
Loading
@@ -33,6 +34,7 @@ export default {
noteSignedOutWidget,
noteEditedText,
noteForm,
toggleRepliesWidget,
placeholderNote,
placeholderSystemNote,
systemNote,
Loading
Loading
@@ -46,11 +48,6 @@ export default {
type: Object,
required: true,
},
renderHeader: {
type: Boolean,
required: false,
default: true,
},
renderDiffFile: {
type: Boolean,
required: false,
Loading
Loading
@@ -72,6 +69,7 @@ export default {
isReplying: false,
isResolving: false,
resolveAsThread: true,
isRepliesCollapsed: (!this.discussion.diff_discussion && this.discussion.resolved) || false,
};
},
computed: {
Loading
Loading
@@ -112,6 +110,15 @@ export default {
newNotePath() {
return this.getNoteableData.create_note_path;
},
hasReplies() {
return this.discussion.notes.length > 1;
},
initialDiscussion() {
return this.discussion.notes.slice(0, 1)[0];
},
replies() {
return this.discussion.notes.slice(1);
},
lastUpdatedBy() {
const { notes } = this.discussion;
 
Loading
Loading
@@ -147,6 +154,12 @@ export default {
 
return diffDiscussion && diffFile && this.renderDiffFile;
},
shouldGroupReplies() {
return !this.shouldRenderDiffs && !this.transformedDiscussion.diffDiscussion;
},
shouldRenderHeader() {
return this.shouldRenderDiffs;
},
wrapperComponent() {
return this.shouldRenderDiffs ? diffWithNote : 'div';
},
Loading
Loading
@@ -160,6 +173,22 @@ export default {
wrapperClass() {
return this.isDiffDiscussion ? '' : 'card discussion-wrapper';
},
componentClassName() {
if (this.shouldRenderDiffs) {
if (!this.lastUpdatedAt && !this.discussion.resolved) {
return 'unresolved';
}
}
return '';
},
shouldShowDiscussions() {
const isExpanded = this.discussion.expanded;
const { diffDiscussion, resolved } = this.transformedDiscussion;
const isResolvedNonDiffDiscussion = !diffDiscussion && resolved;
return isExpanded || this.alwaysExpanded || isResolvedNonDiffDiscussion;
},
},
watch: {
isReplying() {
Loading
Loading
@@ -173,10 +202,6 @@ export default {
}
},
},
created() {
this.resolveDiscussionsSvg = resolveDiscussionsSvg;
this.nextDiscussionsSvg = nextDiscussionsSvg;
},
methods: {
...mapActions([
'saveNote',
Loading
Loading
@@ -207,6 +232,9 @@ export default {
toggleDiscussionHandler() {
this.toggleDiscussion({ discussionId: this.discussion.id });
},
toggleReplies() {
this.isRepliesCollapsed = !this.isRepliesCollapsed;
},
showReplyForm() {
this.isReplying = true;
},
Loading
Loading
@@ -274,26 +302,29 @@ Please check your network connection and try again.`;
</script>
 
<template>
<li class="note note-discussion timeline-entry">
<li
class="note note-discussion timeline-entry"
:class="componentClassName"
>
<div class="timeline-entry-inner">
<div class="timeline-icon">
<user-avatar-link
v-if="author"
:link-href="author.path"
:img-src="author.avatar_url"
:img-alt="author.name"
:img-size="40"
/>
</div>
<div class="timeline-content">
<div
:data-discussion-id="transformedDiscussion.discussion_id"
class="discussion js-discussion-container"
>
<div
v-if="renderHeader"
class="discussion-header"
v-if="shouldRenderHeader"
class="discussion-header note-wrapper"
>
<div class="timeline-icon">
<user-avatar-link
v-if="author"
:link-href="author.path"
:img-src="author.avatar_url"
:img-alt="author.name"
:img-size="40"
/>
</div>
<note-header
:author="author"
:created-at="transformedDiscussion.created_at"
Loading
Loading
@@ -339,7 +370,7 @@ Please check your network connection and try again.`;
/>
</div>
<div
v-if="discussion.expanded || alwaysExpanded"
v-if="shouldShowDiscussions"
class="discussion-body">
<component
:is="wrapperComponent"
Loading
Loading
@@ -348,45 +379,70 @@ Please check your network connection and try again.`;
>
<div class="discussion-notes">
<ul class="notes">
<component
:is="componentName(note)"
v-for="(note, index) in discussion.notes"
:key="note.id"
:note="componentData(note)"
@handleDeleteNote="deleteNoteHandler"
>
<slot
v-if="index === 0"
slot="avatar-badge"
name="avatar-badge"
<template v-if="shouldGroupReplies">
<component
:is="componentName(initialDiscussion)"
:note="componentData(initialDiscussion)"
@handleDeleteNote="deleteNoteHandler"
>
</slot>
</component>
<slot
slot="avatar-badge"
name="avatar-badge"
>
</slot>
</component>
<toggle-replies-widget
v-if="hasReplies"
:collapsed="isRepliesCollapsed"
:replies="replies"
@toggle="toggleReplies"
/>
<template v-if="!isRepliesCollapsed">
<component
:is="componentName(note)"
v-for="note in replies"
:key="note.id"
:note="componentData(note)"
@handleDeleteNote="deleteNoteHandler"
/>
</template>
</template>
<template v-else>
<component
:is="componentName(note)"
v-for="(note, index) in discussion.notes"
:key="note.id"
:note="componentData(note)"
@handleDeleteNote="deleteNoteHandler"
>
<slot
v-if="index === 0"
slot="avatar-badge"
name="avatar-badge"
>
</slot>
</component>
</template>
</ul>
<div
v-if="!isRepliesCollapsed"
:class="{ 'is-replying': isReplying }"
class="discussion-reply-holder"
>
<template v-if="!isReplying && canReply">
<div
class="btn-group d-flex discussion-with-resolve-btn"
role="group">
<div
class="btn-group w-100"
role="group">
<button
type="button"
class="js-vue-discussion-reply btn btn-text-field mr-2 qa-discussion-reply"
title="Add a reply"
@click="showReplyForm">Reply...</button>
</div>
<div
v-if="discussion.resolvable"
class="btn-group"
role="group">
<div class="discussion-with-resolve-btn">
<button
type="button"
class="js-vue-discussion-reply btn btn-text-field mr-2 qa-discussion-reply"
title="Add a reply"
@click="showReplyForm"
>
Reply...
</button>
<div v-if="discussion.resolvable">
<button
type="button"
class="btn btn-default"
class="btn btn-default mx-sm-2"
@click="resolveHandler()"
>
<i
Loading
Loading
@@ -414,7 +470,7 @@ Please check your network connection and try again.`;
btn-default discussion-create-issue-btn"
data-container="body"
>
<span v-html="resolveDiscussionsSvg"></span>
<icon name="issue-new" />
</a>
</div>
<div
Loading
Loading
@@ -428,7 +484,7 @@ Please check your network connection and try again.`;
data-container="body"
@click="jumpToNextDiscussion"
>
<span v-html="nextDiscussionsSvg"></span>
<icon name="comment-next" />
</button>
</div>
</div>
Loading
Loading
Loading
Loading
@@ -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">
Loading
Loading
@@ -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"
Loading
Loading
<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>
Loading
Loading
@@ -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>
Loading
Loading
Loading
Loading
@@ -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"
Loading
Loading
Loading
Loading
@@ -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 {
Loading
Loading
Loading
Loading
@@ -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;
Loading
Loading
@@ -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;
 
Loading
Loading
Loading
Loading
@@ -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;
Loading
Loading
.timeline {
@include basic-list;
margin: 0;
padding: 0;
list-style: none;
 
&::before {
@include notes-media('max', map-get($grid-breakpoints, sm)) {
Loading
Loading
@@ -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;
Loading
Loading
Loading
Loading
@@ -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;
Loading
Loading
@@ -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;
}
Loading
Loading
Loading
Loading
@@ -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;
Loading
Loading
@@ -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;
}
 
Loading
Loading
@@ -270,6 +276,12 @@
.btn {
width: 100%;
}
.btn-text-field {
@include media-breakpoint-down(xs) {
margin-bottom: $gl-padding-8;
}
}
}
 
.discussion-notes-count {
Loading
Loading
/**
* 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 {
Loading
Loading
@@ -28,8 +137,6 @@ ul.notes {
}
 
.discussion-body {
padding-top: 8px;
.card {
margin-bottom: 0;
}
Loading
Loading
@@ -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;
Loading
Loading
@@ -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;
Loading
Loading
@@ -104,12 +187,6 @@ ul.notes {
}
}
 
&.note-discussion {
.timeline-entry-inner {
padding: $gl-padding 10px;
}
}
.editing-spinner {
display: none;
}
Loading
Loading
@@ -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;
Loading
Loading
@@ -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;
}
}
 
Loading
Loading
@@ -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 {
Loading
Loading
@@ -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 {
Loading
Loading
@@ -335,7 +441,6 @@ ul.notes {
border-left: 0;
 
&.notes_content {
background-color: $gray-light;
border-width: 1px 0;
padding: 0;
vertical-align: top;
Loading
Loading
@@ -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;
}
Loading
Loading
@@ -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 {
Loading
Loading
@@ -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 {
Loading
Loading
@@ -409,7 +536,7 @@ ul.notes {
 
.note-header-info {
min-width: 0;
padding-bottom: 8px;
padding-bottom: $gl-padding-8;
 
&.discussion {
padding-bottom: 0;
Loading
Loading
@@ -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 {
Loading
Loading
@@ -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;
Loading
Loading
@@ -634,7 +757,7 @@ ul.notes {
}
 
.btn {
svg path {
svg {
fill: $gray-darkest;
}
 
Loading
Loading
@@ -659,7 +782,7 @@ ul.notes {
.line-resolve-all {
vertical-align: middle;
display: inline-block;
padding: 5px 10px 6px;
padding: 6px 10px;
background-color: $gray-light;
border: 1px solid $border-color;
border-radius: $border-radius-default;
Loading
Loading
Loading
Loading
@@ -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
 
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment