diff options
Diffstat (limited to 'app/assets/javascripts/notes/components')
15 files changed, 202 insertions, 114 deletions
diff --git a/app/assets/javascripts/notes/components/comment_form.vue b/app/assets/javascripts/notes/components/comment_form.vue index 075c28e8d07..fda494fec07 100644 --- a/app/assets/javascripts/notes/components/comment_form.vue +++ b/app/assets/javascripts/notes/components/comment_form.vue @@ -13,6 +13,7 @@ import { splitCamelCase, slugifyWithUnderscore, } from '../../lib/utils/text_utility'; +import { refreshUserMergeRequestCounts } from '~/commons/nav/user_merge_requests'; import * as constants from '../constants'; import eventHub from '../event_hub'; import issueWarning from '../../vue_shared/components/issue/issue_warning.vue'; @@ -65,14 +66,12 @@ export default { return this.getUserData.id; }, commentButtonTitle() { - return this.noteType === constants.COMMENT ? 'Comment' : 'Start discussion'; + return this.noteType === constants.COMMENT ? __('Comment') : __('Start thread'); }, startDiscussionDescription() { - let text = 'Discuss a specific suggestion or question'; - if (this.getNoteableData.noteableType === constants.MERGE_REQUEST_NOTEABLE_TYPE) { - text += ' that needs to be resolved'; - } - return `${text}.`; + return this.getNoteableData.noteableType === constants.MERGE_REQUEST_NOTEABLE_TYPE + ? __('Discuss a specific suggestion or question that needs to be resolved.') + : __('Discuss a specific suggestion or question.'); }, isOpen() { return this.openState === constants.OPENED || this.openState === constants.REOPENED; @@ -127,8 +126,8 @@ export default { }, issuableTypeTitle() { return this.noteableType === constants.MERGE_REQUEST_NOTEABLE_TYPE - ? 'merge request' - : 'issue'; + ? __('merge request') + : __('issue'); }, trackingLabel() { return slugifyWithUnderscore(`${this.commentButtonTitle} button`); @@ -203,7 +202,7 @@ export default { this.discard(); } else { Flash( - 'Something went wrong while adding your comment. Please try again.', + __('Something went wrong while adding your comment. Please try again.'), 'alert', this.$refs.commentForm, ); @@ -219,8 +218,9 @@ export default { .catch(() => { this.enableButton(); this.discard(false); - const msg = `Your comment could not be submitted! -Please check your network connection and try again.`; + const msg = __( + 'Your comment could not be submitted! Please check your network connection and try again.', + ); Flash(msg, 'alert', this.$el); this.note = noteData.data.note.note; // Restore textarea content. this.removePlaceholderNotes(); @@ -235,7 +235,10 @@ Please check your network connection and try again.`; toggleIssueState() { if (this.isOpen) { this.closeIssue() - .then(() => this.enableButton()) + .then(() => { + this.enableButton(); + refreshUserMergeRequestCounts(); + }) .catch(() => { this.enableButton(); this.toggleStateButtonLoading(false); @@ -248,7 +251,10 @@ Please check your network connection and try again.`; }); } else { this.reopenIssue() - .then(() => this.enableButton()) + .then(() => { + this.enableButton(); + refreshUserMergeRequestCounts(); + }) .catch(({ data }) => { this.enableButton(); this.toggleStateButtonLoading(false); @@ -298,7 +304,7 @@ Please check your network connection and try again.`; const noteableType = capitalizeFirstCharacter(convertToCamelCase(this.noteableType)); this.autosave = new Autosave($(this.$refs.textarea), [ - 'Note', + __('Note'), noteableType, this.getNoteableData.id, ]); @@ -359,8 +365,8 @@ Please check your network connection and try again.`; class="note-textarea js-vue-comment-form js-note-text js-gfm-input js-autosize markdown-area js-vue-textarea qa-comment-input" data-supports-quick-actions="true" - aria-label="Description" - placeholder="Write a comment or drag your files here…" + :aria-label="__('Description')" + :placeholder="__('Write a comment or drag your files here…')" @keydown.up="editCurrentUserLastNote()" @keydown.meta.enter="handleSave()" @keydown.ctrl.enter="handleSave()" @@ -381,7 +387,7 @@ append-right-10 comment-type-dropdown js-comment-type-dropdown droplab-dropdown" data-track-event="click_button" @click.prevent="handleSave()" > - {{ __(commentButtonTitle) }} + {{ commentButtonTitle }} </button> <button :disabled="isSubmitButtonDisabled" @@ -390,7 +396,7 @@ append-right-10 comment-type-dropdown js-comment-type-dropdown droplab-dropdown" class="btn btn-success note-type-toggle js-note-new-discussion dropdown-toggle qa-note-dropdown" data-display="static" data-toggle="dropdown" - aria-label="Open comment type dropdown" + :aria-label="__('Open comment type dropdown')" > <i aria-hidden="true" class="fa fa-caret-down toggle-icon"> </i> </button> @@ -404,8 +410,14 @@ append-right-10 comment-type-dropdown js-comment-type-dropdown droplab-dropdown" > <i aria-hidden="true" class="fa fa-check icon"> </i> <div class="description"> - <strong>Comment</strong> - <p>Add a general comment to this {{ noteableDisplayName }}.</p> + <strong>{{ __('Comment') }}</strong> + <p> + {{ + sprintf(__('Add a general comment to this %{noteableDisplayName}.'), { + noteableDisplayName, + }) + }} + </p> </div> </button> </li> @@ -418,7 +430,7 @@ append-right-10 comment-type-dropdown js-comment-type-dropdown droplab-dropdown" > <i aria-hidden="true" class="fa fa-check icon"> </i> <div class="description"> - <strong>Start discussion</strong> + <strong>{{ __('Start thread') }}</strong> <p>{{ startDiscussionDescription }}</p> </div> </button> diff --git a/app/assets/javascripts/notes/components/diff_with_note.vue b/app/assets/javascripts/notes/components/diff_with_note.vue index 54c242b2fda..164e79c6294 100644 --- a/app/assets/javascripts/notes/components/diff_with_note.vue +++ b/app/assets/javascripts/notes/components/diff_with_note.vue @@ -100,7 +100,7 @@ export default { class="btn-link btn-link-retry btn-no-padding js-toggle-lazy-diff-retry-button" @click="fetchDiff" > - Try again + {{ __('Try again') }} </button> </td> <td v-else class="line_content js-success-lazy-load"> diff --git a/app/assets/javascripts/notes/components/discussion_actions.vue b/app/assets/javascripts/notes/components/discussion_actions.vue index 1357a5268d6..f4570c1292c 100644 --- a/app/assets/javascripts/notes/components/discussion_actions.vue +++ b/app/assets/javascripts/notes/components/discussion_actions.vue @@ -39,15 +39,23 @@ export default { </script> <template> - <div class="discussion-with-resolve-btn clearfix"> - <reply-placeholder class="qa-discussion-reply" @onClick="$emit('showReplyForm')" /> - - <div class="btn-group discussion-actions" role="group"> - <resolve-discussion-button - v-if="discussion.resolvable" - :is-resolving="isResolving" - :button-title="resolveButtonTitle" - @onClick="$emit('resolve')" + <div class="discussion-with-resolve-btn"> + <reply-placeholder + :button-text="s__('MergeRequests|Reply...')" + class="qa-discussion-reply" + @onClick="$emit('showReplyForm')" + /> + <resolve-discussion-button + v-if="discussion.resolvable" + :is-resolving="isResolving" + :button-title="resolveButtonTitle" + @onClick="$emit('resolve')" + /> + <div v-if="discussion.resolvable" class="btn-group discussion-actions ml-sm-2" role="group"> + <resolve-with-issue-button v-if="resolveWithIssuePath" :url="resolveWithIssuePath" /> + <jump-to-next-discussion-button + v-if="shouldShowJumpToNextDiscussion" + @onClick="$emit('jumpToNextDiscussion')" /> <resolve-with-issue-button v-if="discussion.resolvable && resolveWithIssuePath" diff --git a/app/assets/javascripts/notes/components/discussion_counter.vue b/app/assets/javascripts/notes/components/discussion_counter.vue index efd84f5722c..d7ffa0abb79 100644 --- a/app/assets/javascripts/notes/components/discussion_counter.vue +++ b/app/assets/javascripts/notes/components/discussion_counter.vue @@ -61,7 +61,7 @@ export default { </span> <span class="line-resolve-text"> {{ resolvedDiscussionsCount }}/{{ resolvableDiscussionsCount }} - {{ n__('discussion resolved', 'discussions resolved', resolvableDiscussionsCount) }} + {{ n__('thread resolved', 'threads resolved', resolvableDiscussionsCount) }} </span> </div> <div @@ -72,7 +72,7 @@ export default { <a v-gl-tooltip :href="resolveAllDiscussionsIssuePath" - :title="s__('Resolve all discussions in new issue')" + :title="s__('Resolve all threads in new issue')" class="new-issue-for-discussion btn btn-default discussion-create-issue-btn" > <icon name="issue-new" /> @@ -81,7 +81,7 @@ export default { <div v-if="isLoggedIn && !allResolved" class="btn-group btn-group-sm" role="group"> <button v-gl-tooltip - title="Jump to first unresolved discussion" + title="Jump to first unresolved thread" class="btn btn-default discussion-next-btn" @click="jumpToFirstUnresolvedDiscussion" > diff --git a/app/assets/javascripts/notes/components/discussion_notes.vue b/app/assets/javascripts/notes/components/discussion_notes.vue index 30971ad5227..0b136549c14 100644 --- a/app/assets/javascripts/notes/components/discussion_notes.vue +++ b/app/assets/javascripts/notes/components/discussion_notes.vue @@ -1,19 +1,21 @@ <script> -import { mapGetters } from 'vuex'; +import { mapGetters, mapActions } from 'vuex'; import { SYSTEM_NOTE } from '../constants'; import { __ } from '~/locale'; -import NoteableNote from './noteable_note.vue'; -import PlaceholderNote from '../../vue_shared/components/notes/placeholder_note.vue'; -import PlaceholderSystemNote from '../../vue_shared/components/notes/placeholder_system_note.vue'; +import PlaceholderNote from '~/vue_shared/components/notes/placeholder_note.vue'; +import PlaceholderSystemNote from '~/vue_shared/components/notes/placeholder_system_note.vue'; import SystemNote from '~/vue_shared/components/notes/system_note.vue'; +import NoteableNote from './noteable_note.vue'; import ToggleRepliesWidget from './toggle_replies_widget.vue'; import NoteEditedText from './note_edited_text.vue'; +import DiscussionNotesRepliesWrapper from './discussion_notes_replies_wrapper.vue'; export default { name: 'DiscussionNotes', components: { ToggleRepliesWidget, NoteEditedText, + DiscussionNotesRepliesWrapper, }, props: { discussion: { @@ -72,6 +74,7 @@ export default { }, }, methods: { + ...mapActions(['toggleDiscussion']), componentName(note) { if (note.isPlaceholderNote) { if (note.placeholderType === SYSTEM_NOTE) { @@ -101,7 +104,7 @@ export default { <component :is="componentName(firstNote)" :note="componentData(firstNote)" - :line="line" + :line="line || diffLine" :commit="commit" :help-page-path="helpPagePath" :show-reply-button="userCanReply" @@ -118,23 +121,27 @@ export default { /> <slot slot="avatar-badge" name="avatar-badge"></slot> </component> - <toggle-replies-widget - v-if="hasReplies" - :collapsed="!isExpanded" - :replies="replies" - @toggle="$emit('toggleDiscussion')" - /> - <template v-if="isExpanded"> - <component - :is="componentName(note)" - v-for="note in replies" - :key="note.id" - :note="componentData(note)" - :help-page-path="helpPagePath" - :line="line" - @handleDeleteNote="$emit('deleteNote')" + <discussion-notes-replies-wrapper :is-diff-discussion="discussion.diff_discussion"> + <toggle-replies-widget + v-if="hasReplies" + :collapsed="!isExpanded" + :replies="replies" + :class="{ 'discussion-toggle-replies': discussion.diff_discussion }" + @toggle="toggleDiscussion({ discussionId: discussion.id })" /> - </template> + <template v-if="isExpanded"> + <component + :is="componentName(note)" + v-for="note in replies" + :key="note.id" + :note="componentData(note)" + :help-page-path="helpPagePath" + :line="line" + @handleDeleteNote="$emit('deleteNote')" + /> + </template> + <slot :show-replies="isExpanded || !hasReplies" name="footer"></slot> + </discussion-notes-replies-wrapper> </template> <template v-else> <component @@ -148,8 +155,8 @@ export default { > <slot v-if="index === 0" slot="avatar-badge" name="avatar-badge"></slot> </component> + <slot :show-replies="isExpanded || !hasReplies" name="footer"></slot> </template> </ul> - <slot :show-replies="isExpanded || !hasReplies" name="footer"></slot> </div> </template> diff --git a/app/assets/javascripts/notes/components/discussion_notes_replies_wrapper.vue b/app/assets/javascripts/notes/components/discussion_notes_replies_wrapper.vue new file mode 100644 index 00000000000..2ddca56ddd5 --- /dev/null +++ b/app/assets/javascripts/notes/components/discussion_notes_replies_wrapper.vue @@ -0,0 +1,27 @@ +<script> +/** + * Wrapper for discussion notes replies section. + * + * This is a functional component using the render method because in some cases + * the wrapper is not needed and we want to simply render along the children. + */ +export default { + functional: true, + props: { + isDiffDiscussion: { + type: Boolean, + required: false, + default: false, + }, + }, + render(h, { props, children }) { + if (props.isDiffDiscussion) { + return h('li', { class: 'discussion-collapsible bordered-box clearfix' }, [ + h('ul', { class: 'notes' }, children), + ]); + } + + return children; + }, +}; +</script> diff --git a/app/assets/javascripts/notes/components/discussion_reply_placeholder.vue b/app/assets/javascripts/notes/components/discussion_reply_placeholder.vue index ea590905e3c..0204169214b 100644 --- a/app/assets/javascripts/notes/components/discussion_reply_placeholder.vue +++ b/app/assets/javascripts/notes/components/discussion_reply_placeholder.vue @@ -1,6 +1,12 @@ <script> export default { name: 'ReplyPlaceholder', + props: { + buttonText: { + type: String, + required: true, + }, + }, }; </script> @@ -12,6 +18,6 @@ export default { :title="s__('MergeRequests|Add a reply')" @click="$emit('onClick')" > - {{ s__('MergeRequests|Reply...') }} + {{ buttonText }} </button> </template> diff --git a/app/assets/javascripts/notes/components/discussion_resolve_with_issue_button.vue b/app/assets/javascripts/notes/components/discussion_resolve_with_issue_button.vue index e413398696a..f03e6fd73d7 100644 --- a/app/assets/javascripts/notes/components/discussion_resolve_with_issue_button.vue +++ b/app/assets/javascripts/notes/components/discussion_resolve_with_issue_button.vue @@ -25,7 +25,7 @@ export default { <gl-button v-gl-tooltip :href="url" - :title="s__('MergeRequests|Resolve this discussion in a new issue')" + :title="s__('MergeRequests|Resolve this thread in a new issue')" class="new-issue-for-discussion discussion-create-issue-btn" > <icon name="issue-new" /> diff --git a/app/assets/javascripts/notes/components/note_awards_list.vue b/app/assets/javascripts/notes/components/note_awards_list.vue index 941b6d5cab3..d4a57d5d58d 100644 --- a/app/assets/javascripts/notes/components/note_awards_list.vue +++ b/app/assets/javascripts/notes/components/note_awards_list.vue @@ -4,6 +4,7 @@ import tooltip from '~/vue_shared/directives/tooltip'; import Icon from '~/vue_shared/components/icon.vue'; import Flash from '../../flash'; import { glEmojiTag } from '../../emoji'; +import { __, sprintf } from '~/locale'; export default { components: { @@ -108,23 +109,26 @@ export default { // Add myself to the beginning of the list so title will start with You. if (hasReactionByCurrentUser) { - namesToShow.unshift('You'); + namesToShow.unshift(__('You')); } let title = ''; // We have 10+ awarded user, join them with comma and add `and x more`. if (remainingAwardList.length) { - title = `${namesToShow.join(', ')}, and ${remainingAwardList.length} more.`; + title = sprintf(__(`%{listToShow}, and %{awardsListLength} more.`), { + listToShow: namesToShow.join(', '), + awardsListLength: remainingAwardList.length, + }); } else if (namesToShow.length > 1) { // Join all names with comma but not the last one, it will be added with and text. title = namesToShow.slice(0, namesToShow.length - 1).join(', '); // If we have more than 2 users we need an extra comma before and text. title += namesToShow.length > 2 ? ',' : ''; - title += ` and ${namesToShow.slice(-1)}`; // Append and text + title += sprintf(__(` and %{sliced}`), { sliced: namesToShow.slice(-1) }); // Append and text } else { // We have only 2 users so join them with and. - title = namesToShow.join(' and '); + title = namesToShow.join(__(' and ')); } return title; @@ -155,7 +159,7 @@ export default { awardName: parsedName, }; - this.toggleAwardRequest(data).catch(() => Flash('Something went wrong on our end.')); + this.toggleAwardRequest(data).catch(() => Flash(__('Something went wrong on our end.'))); }, }, }; @@ -184,7 +188,7 @@ export default { :class="{ 'js-user-authored': isAuthoredByMe }" class="award-control btn js-add-award" title="Add reaction" - aria-label="Add reaction" + :aria-label="__('Add reaction')" data-boundary="viewport" type="button" > diff --git a/app/assets/javascripts/notes/components/note_form.vue b/app/assets/javascripts/notes/components/note_form.vue index 042ed196933..3823861c0b9 100644 --- a/app/assets/javascripts/notes/components/note_form.vue +++ b/app/assets/javascripts/notes/components/note_form.vue @@ -1,14 +1,14 @@ <script> import { mergeUrlParams } from '~/lib/utils/url_utility'; import { mapGetters, mapActions } from 'vuex'; +import noteFormMixin from 'ee_else_ce/notes/mixins/note_form'; import eventHub from '../event_hub'; import issueWarning from '../../vue_shared/components/issue/issue_warning.vue'; import markdownField from '../../vue_shared/components/markdown/field.vue'; import issuableStateMixin from '../mixins/issuable_state'; import resolvable from '../mixins/resolvable'; -import { __ } from '~/locale'; +import { __, sprintf } from '~/locale'; import { getDraft, updateDraft } from '~/lib/utils/autosave'; -import noteFormMixin from 'ee_else_ce/notes/mixins/note_form'; export default { name: 'NoteForm', @@ -174,6 +174,18 @@ export default { (this.line && this.line.can_receive_suggestion) ); }, + changedCommentText() { + return sprintf( + __( + 'This comment has changed since you started editing, please review the %{startTag}updated comment%{endTag} to ensure information is not lost.', + ), + { + startTag: `<a href="${this.noteHash}" target="_blank" rel="noopener noreferrer">`, + endTag: '</a>', + }, + false, + ); + }, }, watch: { noteBody() { @@ -228,11 +240,11 @@ export default { <template> <div ref="editNoteForm" class="note-edit-form current-note-edit-form js-discussion-note-form"> - <div v-if="conflictWhileEditing" class="js-conflict-edit-warning alert alert-danger"> - This comment has changed since you started editing, please review the - <a :href="noteHash" target="_blank" rel="noopener noreferrer">updated comment</a> to ensure - information is not lost. - </div> + <div + v-if="conflictWhileEditing" + class="js-conflict-edit-warning alert alert-danger" + v-html="changedCommentText" + ></div> <div class="flash-container timeline-content"></div> <form :data-line-code="lineCode" class="edit-note common-note-form js-quick-submit gfm-form"> <issue-warning @@ -264,8 +276,8 @@ export default { name="note[note]" class="note-textarea js-gfm-input js-note-text js-autosize markdown-area js-vue-issue-note-form js-vue-textarea qa-reply-input" dir="auto" - aria-label="Description" - placeholder="Write a comment or drag your files here…" + :aria-label="__('Description')" + :placeholder="__('Write a comment or drag your files here…')" @keydown.meta.enter="handleKeySubmit()" @keydown.ctrl.enter="handleKeySubmit()" @keydown.exact.up="editMyLastNote()" @@ -283,11 +295,11 @@ export default { type="checkbox" class="qa-unresolve-review-discussion" /> - {{ __('Unresolve discussion') }} + {{ __('Unresolve thread') }} </template> <template v-else> <input v-model="isResolving" type="checkbox" class="qa-resolve-review-discussion" /> - {{ __('Resolve discussion') }} + {{ __('Resolve thread') }} </template> </label> </p> @@ -339,7 +351,7 @@ export default { type="button" @click="cancelHandler()" > - Cancel + {{ __('Cancel') }} </button> </template> </div> diff --git a/app/assets/javascripts/notes/components/note_header.vue b/app/assets/javascripts/notes/components/note_header.vue index fbf82fab9e9..3158e086f6c 100644 --- a/app/assets/javascripts/notes/components/note_header.vue +++ b/app/assets/javascripts/notes/components/note_header.vue @@ -70,7 +70,7 @@ export default { @click="handleToggle" > <i :class="toggleChevronClass" class="fa" aria-hidden="true"></i> - {{ __('Toggle discussion') }} + {{ __('Toggle thread') }} </button> </div> <a @@ -103,7 +103,7 @@ export default { </template> <i class="fa fa-spinner fa-spin editing-spinner" - aria-label="Comment is being updated" + :aria-label="__('Comment is being updated')" aria-hidden="true" ></i> </span> diff --git a/app/assets/javascripts/notes/components/note_signed_out_widget.vue b/app/assets/javascripts/notes/components/note_signed_out_widget.vue index e3eb92956b1..ccfe84ab098 100644 --- a/app/assets/javascripts/notes/components/note_signed_out_widget.vue +++ b/app/assets/javascripts/notes/components/note_signed_out_widget.vue @@ -1,5 +1,6 @@ <script> import { mapGetters } from 'vuex'; +import { __, sprintf } from '~/locale'; export default { computed: { @@ -10,12 +11,24 @@ export default { signInLink() { return this.getNotesDataByProp('newSessionPath'); }, + signedOutText() { + return sprintf( + __( + 'Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply', + ), + { + startTagRegister: `<a href="${this.registerLink}">`, + startTagSignIn: `<a href="${this.signInLink}">`, + endRegisterTag: '</a>', + endSignInTag: '</a>', + }, + false, + ); + }, }, }; </script> <template> - <div class="disabled-comment text-center"> - Please <a :href="registerLink">register</a> or <a :href="signInLink">sign in</a> to reply - </div> + <div class="disabled-comment text-center" v-html="signedOutText"></div> </template> diff --git a/app/assets/javascripts/notes/components/noteable_discussion.vue b/app/assets/javascripts/notes/components/noteable_discussion.vue index b8eaff32cce..ac743d9f4b8 100644 --- a/app/assets/javascripts/notes/components/noteable_discussion.vue +++ b/app/assets/javascripts/notes/components/noteable_discussion.vue @@ -132,7 +132,7 @@ export default { return this.discussion.diff_discussion && this.renderDiffFile; }, shouldGroupReplies() { - return !this.shouldRenderDiffs && !this.discussion.diff_discussion; + return !this.shouldRenderDiffs; }, wrapperComponent() { return this.shouldRenderDiffs ? diffWithNote : 'div'; @@ -144,15 +144,6 @@ export default { return {}; }, - componentClassName() { - if (this.shouldRenderDiffs) { - if (!this.lastUpdatedAt && !this.discussion.resolved) { - return 'unresolved'; - } - } - - return ''; - }, isExpanded() { return this.discussion.expanded || this.alwaysExpanded; }, @@ -174,22 +165,20 @@ export default { active: isActive, } = this.discussion; - let text = s__('MergeRequests|started a discussion'); + let text = s__('MergeRequests|started a thread'); if (isForCommit) { - text = s__( - 'MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}', - ); + text = s__('MergeRequests|started a thread on commit %{linkStart}%{commitId}%{linkEnd}'); } else if (isDiffDiscussion && commitId) { text = isActive - ? s__('MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}') + ? s__('MergeRequests|started a thread on commit %{linkStart}%{commitId}%{linkEnd}') : s__( - 'MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}', + 'MergeRequests|started a thread on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}', ); } else if (isDiffDiscussion) { text = isActive - ? s__('MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}') + ? s__('MergeRequests|started a thread on %{linkStart}the diff%{linkEnd}') : s__( - 'MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}', + 'MergeRequests|started a thread on %{linkStart}an old version of the diff%{linkEnd}', ); } @@ -250,6 +239,11 @@ export default { clearDraft(this.autosaveKey); }, saveReply(noteText, form, callback) { + if (!noteText) { + this.cancelReplyForm(); + callback(); + return; + } const postData = { in_reply_to_discussion_id: this.discussion.reply_id, target_type: this.getNoteableData.targetType, @@ -280,8 +274,9 @@ export default { this.removePlaceholderNotes(); this.isReplying = true; this.$nextTick(() => { - const msg = `Your comment could not be submitted! -Please check your network connection and try again.`; + const msg = __( + 'Your comment could not be submitted! Please check your network connection and try again.', + ); Flash(msg, 'alert', this.$el); this.$refs.noteForm.note = noteText; callback(err); @@ -309,11 +304,11 @@ Please check your network connection and try again.`; </script> <template> - <timeline-entry-item class="note note-discussion" :class="componentClassName"> + <timeline-entry-item class="note note-discussion"> <div class="timeline-content"> <div :data-discussion-id="discussion.id" class="discussion js-discussion-container"> <div v-if="shouldRenderDiffs" class="discussion-header note-wrapper"> - <div v-once class="timeline-icon"> + <div v-once class="timeline-icon align-self-start flex-shrink-0"> <user-avatar-link v-if="author" :link-href="author.path" @@ -322,7 +317,7 @@ Please check your network connection and try again.`; :img-size="40" /> </div> - <div class="timeline-content"> + <div class="timeline-content w-100"> <note-header :author="author" :created-at="firstNote.created_at" @@ -363,7 +358,6 @@ Please check your network connection and try again.`; :line="line" :should-group-replies="shouldGroupReplies" @startReplying="showReplyForm" - @toggleDiscussion="toggleDiscussionHandler" @deleteNote="deleteNoteHandler" > <slot slot="avatar-badge" name="avatar-badge"></slot> @@ -376,7 +370,7 @@ Please check your network connection and try again.`; <div v-else-if="showReplies" :class="{ 'is-replying': isReplying }" - class="discussion-reply-holder" + class="discussion-reply-holder clearfix" > <user-avatar-link v-if="!isReplying && userCanReply" diff --git a/app/assets/javascripts/notes/components/noteable_note.vue b/app/assets/javascripts/notes/components/noteable_note.vue index aa80e25a3e0..2f201839d45 100644 --- a/app/assets/javascripts/notes/components/noteable_note.vue +++ b/app/assets/javascripts/notes/components/noteable_note.vue @@ -5,7 +5,7 @@ import { escape } from 'underscore'; import { truncateSha } from '~/lib/utils/text_utility'; import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue'; import draftMixin from 'ee_else_ce/notes/mixins/draft'; -import { s__, sprintf } from '../../locale'; +import { __, s__, sprintf } from '../../locale'; import Flash from '../../flash'; import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue'; import noteHeader from './note_header.vue'; @@ -128,9 +128,13 @@ export default { this.$emit('handleEdit'); }, deleteHandler() { - const typeOfComment = this.note.isDraft ? 'pending comment' : 'comment'; - // eslint-disable-next-line no-alert - if (window.confirm(`Are you sure you want to delete this ${typeOfComment}?`)) { + const typeOfComment = this.note.isDraft ? __('pending comment') : __('comment'); + if ( + // eslint-disable-next-line no-alert + window.confirm( + sprintf(__('Are you sure you want to delete this %{typeOfComment}?'), { typeOfComment }), + ) + ) { this.isDeleting = true; this.$emit('handleDeleteNote', this.note); @@ -141,7 +145,7 @@ export default { this.isDeleting = false; }) .catch(() => { - Flash('Something went wrong while deleting your note. Please try again.'); + Flash(__('Something went wrong while deleting your note. Please try again.')); this.isDeleting = false; }); } @@ -185,7 +189,7 @@ export default { this.isRequesting = false; this.isEditing = true; this.$nextTick(() => { - const msg = 'Something went wrong while editing your comment. Please try again.'; + const msg = __('Something went wrong while editing your comment. Please try again.'); Flash(msg, 'alert', this.$el); this.recoverNoteContent(noteText); callback(); @@ -195,7 +199,7 @@ export default { formCancelHandler(shouldConfirm, isDirty) { if (shouldConfirm && isDirty) { // eslint-disable-next-line no-alert - if (!window.confirm('Are you sure you want to cancel editing this comment?')) return; + if (!window.confirm(__('Are you sure you want to cancel editing this comment?'))) return; } this.$refs.noteBody.resetAutoSave(); if (this.oldContent) { diff --git a/app/assets/javascripts/notes/components/notes_app.vue b/app/assets/javascripts/notes/components/notes_app.vue index 4d00e957973..a0695f9e191 100644 --- a/app/assets/javascripts/notes/components/notes_app.vue +++ b/app/assets/javascripts/notes/components/notes_app.vue @@ -1,4 +1,5 @@ <script> +import { __ } from '~/locale'; import { mapGetters, mapActions } from 'vuex'; import { getLocationHash } from '../../lib/utils/url_utility'; import Flash from '../../flash'; @@ -170,7 +171,7 @@ export default { .catch(() => { this.setLoadingState(false); this.setNotesFetchedState(true); - Flash('Something went wrong while fetching comments. Please try again.'); + Flash(__('Something went wrong while fetching comments. Please try again.')); }); }, initPolling() { |