diff options
Diffstat (limited to 'app/assets/javascripts/notes/components')
18 files changed, 263 insertions, 172 deletions
diff --git a/app/assets/javascripts/notes/components/comment_field_layout.vue b/app/assets/javascripts/notes/components/comment_field_layout.vue new file mode 100644 index 00000000000..aaf64702ffd --- /dev/null +++ b/app/assets/javascripts/notes/components/comment_field_layout.vue @@ -0,0 +1,69 @@ +<script> +import EmailParticipantsWarning from './email_participants_warning.vue'; +import NoteableWarning from '~/vue_shared/components/notes/noteable_warning.vue'; + +const DEFAULT_NOTEABLE_TYPE = 'Issue'; + +export default { + components: { + EmailParticipantsWarning, + NoteableWarning, + }, + props: { + noteableData: { + type: Object, + required: true, + }, + noteableType: { + type: String, + required: false, + default: DEFAULT_NOTEABLE_TYPE, + }, + withAlertContainer: { + type: Boolean, + required: false, + default: false, + }, + }, + computed: { + isLocked() { + return Boolean(this.noteableData.discussion_locked); + }, + isConfidential() { + return Boolean(this.noteableData.confidential); + }, + hasWarning() { + return this.isConfidential || this.isLocked; + }, + emailParticipants() { + return this.noteableData.issue_email_participants?.map(({ email }) => email) || []; + }, + }, +}; +</script> +<template> + <div + class="comment-warning-wrapper gl-border-solid gl-border-1 gl-rounded-base gl-border-gray-100" + > + <div + v-if="withAlertContainer" + class="error-alert" + data-testid="comment-field-alert-container" + ></div> + <noteable-warning + v-if="hasWarning" + class="gl-border-b-1 gl-border-b-solid gl-border-b-gray-100 gl-rounded-base gl-rounded-bottom-left-none gl-rounded-bottom-right-none" + :is-locked="isLocked" + :is-confidential="isConfidential" + :noteable-type="noteableType" + :locked-noteable-docs-path="noteableData.locked_discussion_docs_path" + :confidential-noteable-docs-path="noteableData.confidential_issues_docs_path" + /> + <slot></slot> + <email-participants-warning + v-if="emailParticipants.length" + class="gl-border-t-1 gl-border-t-solid gl-border-t-gray-100 gl-rounded-base gl-rounded-top-left-none! gl-rounded-top-right-none!" + :emails="emailParticipants" + /> + </div> +</template> diff --git a/app/assets/javascripts/notes/components/comment_form.vue b/app/assets/javascripts/notes/components/comment_form.vue index 0363173f912..111af977ec5 100644 --- a/app/assets/javascripts/notes/components/comment_form.vue +++ b/app/assets/javascripts/notes/components/comment_form.vue @@ -17,17 +17,17 @@ import { import { refreshUserMergeRequestCounts } from '~/commons/nav/user_merge_requests'; import * as constants from '../constants'; import eventHub from '../event_hub'; -import NoteableWarning from '~/vue_shared/components/notes/noteable_warning.vue'; import markdownField from '~/vue_shared/components/markdown/field.vue'; import userAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue'; +import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import noteSignedOutWidget from './note_signed_out_widget.vue'; import discussionLockedWidget from './discussion_locked_widget.vue'; import issuableStateMixin from '../mixins/issuable_state'; +import CommentFieldLayout from './comment_field_layout.vue'; export default { name: 'CommentForm', components: { - NoteableWarning, noteSignedOutWidget, discussionLockedWidget, markdownField, @@ -35,8 +35,9 @@ export default { GlButton, TimelineEntryItem, GlIcon, + CommentFieldLayout, }, - mixins: [issuableStateMixin], + mixins: [glFeatureFlagsMixin(), issuableStateMixin], props: { noteableType: { type: String, @@ -286,6 +287,9 @@ export default { Autosize.update(this.$refs.textarea); }); }, + hasEmailParticipants() { + return this.getNoteableData.issue_email_participants?.length; + }, }, }; </script> @@ -308,46 +312,41 @@ export default { </div> <div class="timeline-content timeline-content-form"> <form ref="commentForm" class="new-note common-note-form gfm-form js-main-target-form"> - <div class="error-alert"></div> - - <noteable-warning - v-if="hasWarning(getNoteableData)" - :is-locked="isLocked(getNoteableData)" - :is-confidential="isConfidential(getNoteableData)" + <comment-field-layout + :with-alert-container="true" + :noteable-data="getNoteableData" :noteable-type="noteableType" - :locked-noteable-docs-path="lockedIssueDocsPath" - :confidential-noteable-docs-path="confidentialIssueDocsPath" - /> - - <markdown-field - ref="markdownField" - :is-submitting="isSubmitting" - :markdown-preview-path="markdownPreviewPath" - :markdown-docs-path="markdownDocsPath" - :quick-actions-docs-path="quickActionsDocsPath" - :add-spacing-classes="false" - :textarea-value="note" > - <textarea - id="note-body" - ref="textarea" - slot="textarea" - v-model="note" - dir="auto" - :disabled="isSubmitting" - name="note[note]" - class="note-textarea js-vue-comment-form js-note-text js-gfm-input js-autosize markdown-area" - data-qa-selector="comment_field" - data-testid="comment-field" - data-supports-quick-actions="true" - :aria-label="__('Description')" - :placeholder="__('Write a comment or drag your files here…')" - @keydown.up="editCurrentUserLastNote()" - @keydown.meta.enter="handleSave()" - @keydown.ctrl.enter="handleSave()" - ></textarea> - </markdown-field> - + <markdown-field + ref="markdownField" + :is-submitting="isSubmitting" + :markdown-preview-path="markdownPreviewPath" + :markdown-docs-path="markdownDocsPath" + :quick-actions-docs-path="quickActionsDocsPath" + :add-spacing-classes="false" + :textarea-value="note" + > + <template #textarea> + <textarea + id="note-body" + ref="textarea" + v-model="note" + dir="auto" + :disabled="isSubmitting" + name="note[note]" + class="note-textarea js-vue-comment-form js-note-text js-gfm-input js-autosize markdown-area" + data-qa-selector="comment_field" + data-testid="comment-field" + :data-supports-quick-actions="!glFeatures.tributeAutocomplete" + :aria-label="__('Description')" + :placeholder="__('Write a comment or drag your files here…')" + @keydown.up="editCurrentUserLastNote()" + @keydown.meta.enter="handleSave()" + @keydown.ctrl.enter="handleSave()" + ></textarea> + </template> + </markdown-field> + </comment-field-layout> <div class="note-form-actions"> <div class="btn-group gl-mr-3 comment-type-dropdown js-comment-type-dropdown droplab-dropdown" diff --git a/app/assets/javascripts/notes/components/diff_with_note.vue b/app/assets/javascripts/notes/components/diff_with_note.vue index 1580c94658a..b7355d4d927 100644 --- a/app/assets/javascripts/notes/components/diff_with_note.vue +++ b/app/assets/javascripts/notes/components/diff_with_note.vue @@ -31,7 +31,7 @@ export default { }, computed: { ...mapState({ - projectPath: state => state.diffs.projectPath, + projectPath: (state) => state.diffs.projectPath, }), diffMode() { return getDiffMode(this.discussion.diff_file); diff --git a/app/assets/javascripts/notes/components/discussion_actions.vue b/app/assets/javascripts/notes/components/discussion_actions.vue index 0272790a75d..da4134ab2c4 100644 --- a/app/assets/javascripts/notes/components/discussion_actions.vue +++ b/app/assets/javascripts/notes/components/discussion_actions.vue @@ -2,7 +2,6 @@ import ReplyPlaceholder from './discussion_reply_placeholder.vue'; import ResolveDiscussionButton from './discussion_resolve_button.vue'; import ResolveWithIssueButton from './discussion_resolve_with_issue_button.vue'; -import JumpToNextDiscussionButton from './discussion_jump_to_next_button.vue'; import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; export default { @@ -11,7 +10,6 @@ export default { ReplyPlaceholder, ResolveDiscussionButton, ResolveWithIssueButton, - JumpToNextDiscussionButton, }, mixins: [glFeatureFlagsMixin()], props: { @@ -38,14 +36,11 @@ export default { }, }, computed: { - hideJumpToNextUnresolvedInThreads() { - return this.glFeatures.hideJumpToNextUnresolvedInThreads; - }, resolvableNotes() { - return this.discussion.notes.filter(x => x.resolvable); + return this.discussion.notes.filter((x) => x.resolvable); }, userCanResolveDiscussion() { - return this.resolvableNotes.every(note => note.current_user?.can_resolve_discussion); + return this.resolvableNotes.every((note) => note.current_user?.can_resolve_discussion); }, }, }; @@ -74,15 +69,5 @@ export default { :url="resolveWithIssuePath" /> </div> - <div - v-if=" - !hideJumpToNextUnresolvedInThreads && - discussion.resolvable && - shouldShowJumpToNextDiscussion - " - class="btn-group discussion-actions ml-sm-2" - > - <jump-to-next-discussion-button :from-discussion-id="discussion.id" /> - </div> </div> </template> diff --git a/app/assets/javascripts/notes/components/discussion_counter.vue b/app/assets/javascripts/notes/components/discussion_counter.vue index 2427a3f98ad..0a72627834d 100644 --- a/app/assets/javascripts/notes/components/discussion_counter.vue +++ b/app/assets/javascripts/notes/components/discussion_counter.vue @@ -32,10 +32,10 @@ export default { return this.getNoteableData.create_issue_to_resolve_discussions_path; }, toggeableDiscussions() { - return this.discussions.filter(discussion => !discussion.individual_note); + return this.discussions.filter((discussion) => !discussion.individual_note); }, allExpanded() { - return this.toggeableDiscussions.every(discussion => discussion.expanded); + return this.toggeableDiscussions.every((discussion) => discussion.expanded); }, lineResolveClass() { return this.allResolved ? 'line-resolve-btn is-active' : 'line-resolve-text'; @@ -48,7 +48,7 @@ export default { ...mapActions(['setExpandDiscussions']), handleExpandDiscussions() { this.setExpandDiscussions({ - discussionIds: this.toggeableDiscussions.map(discussion => discussion.id), + discussionIds: this.toggeableDiscussions.map((discussion) => discussion.id), expanded: !this.allExpanded, }); }, diff --git a/app/assets/javascripts/notes/components/discussion_filter.vue b/app/assets/javascripts/notes/components/discussion_filter.vue index 08c22f0b4c6..aa61aa9b3cb 100644 --- a/app/assets/javascripts/notes/components/discussion_filter.vue +++ b/app/assets/javascripts/notes/components/discussion_filter.vue @@ -42,7 +42,7 @@ export default { ...mapGetters(['getNotesDataByProp', 'timelineEnabled']), currentFilter() { if (!this.currentValue) return this.filters[0]; - return this.filters.find(filter => filter.value === this.currentValue); + return this.filters.find((filter) => filter.value === this.currentValue); }, }, created() { diff --git a/app/assets/javascripts/notes/components/discussion_jump_to_next_button.vue b/app/assets/javascripts/notes/components/discussion_jump_to_next_button.vue deleted file mode 100644 index f94d0060b41..00000000000 --- a/app/assets/javascripts/notes/components/discussion_jump_to_next_button.vue +++ /dev/null @@ -1,38 +0,0 @@ -<script> -import { GlTooltipDirective, GlIcon } from '@gitlab/ui'; -import discussionNavigation from '../mixins/discussion_navigation'; - -export default { - name: 'JumpToNextDiscussionButton', - components: { - GlIcon, - }, - directives: { - GlTooltip: GlTooltipDirective, - }, - mixins: [discussionNavigation], - props: { - fromDiscussionId: { - type: String, - required: true, - }, - }, -}; -</script> - -<template> - <div class="btn-group" role="group"> - <button - ref="button" - v-gl-tooltip - class="btn btn-default discussion-next-btn" - :title="s__('MergeRequests|Jump to next unresolved thread')" - data-track-event="click_button" - data-track-label="mr_next_unresolved_thread" - data-track-property="click_next_unresolved_thread" - @click="jumpToNextRelativeDiscussion(fromDiscussionId)" - > - <gl-icon name="comment-next" /> - </button> - </div> -</template> diff --git a/app/assets/javascripts/notes/components/email_participants_warning.vue b/app/assets/javascripts/notes/components/email_participants_warning.vue new file mode 100644 index 00000000000..bb1ff58120a --- /dev/null +++ b/app/assets/javascripts/notes/components/email_participants_warning.vue @@ -0,0 +1,70 @@ +<script> +import { GlSprintf } from '@gitlab/ui'; +import { s__, sprintf } from '~/locale'; +import { toNounSeriesText } from '~/lib/utils/grammar'; + +export default { + components: { + GlSprintf, + }, + props: { + emails: { + type: Array, + required: true, + }, + numberOfLessParticipants: { + type: Number, + required: false, + default: 3, + }, + }, + data() { + return { + isShowingMoreParticipants: false, + }; + }, + computed: { + title() { + return this.moreParticipantsAvailable + ? toNounSeriesText(this.lessParticipants, { onlyCommas: true }) + : toNounSeriesText(this.emails); + }, + lessParticipants() { + return this.emails.slice(0, this.numberOfLessParticipants); + }, + moreLabel() { + return sprintf(s__('EmailParticipantsWarning|and %{moreCount} more'), { + moreCount: this.emails.length - this.numberOfLessParticipants, + }); + }, + moreParticipantsAvailable() { + return !this.isShowingMoreParticipants && this.emails.length > this.numberOfLessParticipants; + }, + message() { + return this.moreParticipantsAvailable + ? s__('EmailParticipantsWarning|%{emails}, %{andMore} will be notified of your comment.') + : s__('EmailParticipantsWarning|%{emails} will be notified of your comment.'); + }, + }, + methods: { + showMoreParticipants() { + this.isShowingMoreParticipants = true; + }, + }, +}; +</script> + +<template> + <div class="issuable-note-warning" data-testid="email-participants-warning"> + <gl-sprintf :message="message"> + <template #andMore> + <button type="button" class="btn-transparent btn-link" @click="showMoreParticipants"> + {{ moreLabel }} + </button> + </template> + <template #emails> + <span>{{ title }}</span> + </template> + </gl-sprintf> + </div> +</template> diff --git a/app/assets/javascripts/notes/components/multiline_comment_form.vue b/app/assets/javascripts/notes/components/multiline_comment_form.vue index bb13eb87af7..9fbf2c9265c 100644 --- a/app/assets/javascripts/notes/components/multiline_comment_form.vue +++ b/app/assets/javascripts/notes/components/multiline_comment_form.vue @@ -1,5 +1,5 @@ <script> -import { mapActions } from 'vuex'; +import { mapActions, mapState } from 'vuex'; import { GlFormSelect, GlSprintf } from '@gitlab/ui'; import { getSymbol, getLineClasses } from './multiline_comment_utils'; @@ -27,12 +27,13 @@ export default { }; }, computed: { + ...mapState({ selectedCommentPosition: ({ notes }) => notes.selectedCommentPosition }), lineNumber() { return this.commentLineOptions[this.commentLineOptions.length - 1].text; }, }, created() { - const line = this.lineRange?.start || this.line; + const line = this.selectedCommentPosition?.start || this.lineRange?.start || this.line; this.commentLineStart = { line_code: line.line_code, @@ -40,6 +41,8 @@ export default { old_line: line.old_line, new_line: line.new_line, }; + + if (this.selectedCommentPosition) return; this.highlightSelection(); }, destroyed() { diff --git a/app/assets/javascripts/notes/components/multiline_comment_utils.js b/app/assets/javascripts/notes/components/multiline_comment_utils.js index 2451400e980..4991695b97e 100644 --- a/app/assets/javascripts/notes/components/multiline_comment_utils.js +++ b/app/assets/javascripts/notes/components/multiline_comment_utils.js @@ -48,11 +48,11 @@ export function getLineClasses(line) { export function commentLineOptions(diffLines, startingLine, lineCode, side = 'left') { const preferredSide = side === 'left' ? 'old_line' : 'new_line'; const fallbackSide = preferredSide === 'new_line' ? 'old_line' : 'new_line'; - const notMatchType = l => l.type !== 'match'; + const notMatchType = (l) => l.type !== 'match'; const linesCopy = [...diffLines]; // don't mutate the argument const startingLineCode = startingLine.line_code; - const currentIndex = linesCopy.findIndex(line => line.line_code === lineCode); + const currentIndex = linesCopy.findIndex((line) => line.line_code === lineCode); // We're limiting adding comments to only lines above the current line // to make rendering simpler. Future interations will use a more @@ -66,10 +66,10 @@ export function commentLineOptions(diffLines, startingLine, lineCode, side = 'le // If the selected line is "hidden" in an unchanged line block // or "above" the current group of lines add it to the array so // that the drop down is not defaulted to empty - const selectedIndex = lines.findIndex(line => line.line_code === startingLineCode); + const selectedIndex = lines.findIndex((line) => line.line_code === startingLineCode); if (selectedIndex < 0) lines.unshift(startingLine); - return lines.map(l => { + return lines.map((l) => { const { line_code, type, old_line, new_line } = l; return { value: { line_code, type, old_line, new_line }, @@ -103,7 +103,7 @@ export function getCommentedLines(selectedCommentPosition, diffLines) { }; } - const findLineCodeIndex = line => position => { + const findLineCodeIndex = (line) => (position) => { return [position.line_code, position.left?.line_code, position.right?.line_code].includes( line.line_code, ); diff --git a/app/assets/javascripts/notes/components/note_actions.vue b/app/assets/javascripts/notes/components/note_actions.vue index fc131f548b4..b85cfa83e09 100644 --- a/app/assets/javascripts/notes/components/note_actions.vue +++ b/app/assets/javascripts/notes/components/note_actions.vue @@ -206,14 +206,14 @@ export default { const { project_id, iid } = this.getNoteableData; if (this.isUserAssigned) { - assignees = assignees.filter(assignee => assignee.id !== this.author.id); + assignees = assignees.filter((assignee) => assignee.id !== this.author.id); } else { assignees.push({ id: this.author.id }); } if (this.targetType === 'issue') { Api.updateIssue(project_id, iid, { - assignee_ids: assignees.map(assignee => assignee.id), + assignee_ids: assignees.map((assignee) => assignee.id), }) .then(() => this.handleAssigneeUpdate(assignees)) .catch(() => flash(__('Something went wrong while updating assignees'))); diff --git a/app/assets/javascripts/notes/components/note_body.vue b/app/assets/javascripts/notes/components/note_body.vue index 65b89b94eaa..8855ceac3d5 100644 --- a/app/assets/javascripts/notes/components/note_body.vue +++ b/app/assets/javascripts/notes/components/note_body.vue @@ -52,8 +52,9 @@ export default { return this.getDiscussion(this.note.discussion_id); }, ...mapState({ - batchSuggestionsInfo: state => state.notes.batchSuggestionsInfo, + batchSuggestionsInfo: (state) => state.notes.batchSuggestionsInfo, }), + ...mapState('diffs', ['defaultSuggestionCommitMessage']), noteBody() { return this.note.note; }, @@ -98,12 +99,16 @@ export default { formCancelHandler(shouldConfirm, isDirty) { this.$emit('cancelForm', shouldConfirm, isDirty); }, - applySuggestion({ suggestionId, flashContainer, callback = () => {} }) { + applySuggestion({ suggestionId, flashContainer, callback = () => {}, message }) { const { discussion_id: discussionId, id: noteId } = this.note; - return this.submitSuggestion({ discussionId, noteId, suggestionId, flashContainer }).then( - callback, - ); + return this.submitSuggestion({ + discussionId, + noteId, + suggestionId, + flashContainer, + message, + }).then(callback); }, applySuggestionBatch({ flashContainer }) { return this.submitSuggestionBatch({ flashContainer }); @@ -130,6 +135,7 @@ export default { :note-html="note.note_html" :line-type="lineType" :help-page-path="helpPagePath" + :default-commit-message="defaultSuggestionCommitMessage" @apply="applySuggestion" @applyBatch="applySuggestionBatch" @addToBatch="addSuggestionToBatch" diff --git a/app/assets/javascripts/notes/components/note_form.vue b/app/assets/javascripts/notes/components/note_form.vue index 84769bfc7c8..9acb837c27f 100644 --- a/app/assets/javascripts/notes/components/note_form.vue +++ b/app/assets/javascripts/notes/components/note_form.vue @@ -3,20 +3,21 @@ import { mapGetters, mapActions, mapState } from 'vuex'; import { mergeUrlParams } from '~/lib/utils/url_utility'; import eventHub from '../event_hub'; -import NoteableWarning from '../../vue_shared/components/notes/noteable_warning.vue'; -import markdownField from '../../vue_shared/components/markdown/field.vue'; +import markdownField from '~/vue_shared/components/markdown/field.vue'; +import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import issuableStateMixin from '../mixins/issuable_state'; import resolvable from '../mixins/resolvable'; import { __, sprintf } from '~/locale'; import { getDraft, updateDraft } from '~/lib/utils/autosave'; +import CommentFieldLayout from './comment_field_layout.vue'; export default { name: 'NoteForm', components: { - NoteableWarning, markdownField, + CommentFieldLayout, }, - mixins: [issuableStateMixin, resolvable], + mixins: [glFeatureFlagsMixin(), issuableStateMixin, resolvable], props: { noteBody: { type: String, @@ -114,7 +115,7 @@ export default { 'getUserDataByProp', ]), ...mapState({ - withBatchComments: state => state.batchComments?.withBatchComments, + withBatchComments: (state) => state.batchComments?.withBatchComments, }), ...mapGetters('batchComments', ['hasDrafts']), showBatchCommentsActions() { @@ -125,8 +126,8 @@ export default { return ( this.discussion?.notes - .filter(n => n.resolvable) - .some(n => n.current_user?.can_resolve_discussion) || this.isDraft + .filter((n) => n.resolvable) + .some((n) => n.current_user?.can_resolve_discussion) || this.isDraft ); }, noteHash() { @@ -192,8 +193,7 @@ export default { }, canSuggest() { return ( - this.getNoteableData.can_receive_suggestion && - (this.line && this.line.can_receive_suggestion) + this.getNoteableData.can_receive_suggestion && this.line && this.line.can_receive_suggestion ); }, changedCommentText() { @@ -303,6 +303,9 @@ export default { this.$emit('handleFormUpdateAddToReview', this.updatedNoteBody, shouldResolve); }, + hasEmailParticipants() { + return this.getNoteableData.issue_email_participants?.length; + }, }, }; </script> @@ -316,46 +319,41 @@ export default { ></div> <div class="flash-container timeline-content"></div> <form :data-line-code="lineCode" class="edit-note common-note-form js-quick-submit gfm-form"> - <noteable-warning - v-if="hasWarning(getNoteableData)" - :is-locked="isLocked(getNoteableData)" - :is-confidential="isConfidential(getNoteableData)" - :locked-noteable-docs-path="lockedIssueDocsPath" - :confidential-noteable-docs-path="confidentialIssueDocsPath" - /> - - <markdown-field - :markdown-preview-path="markdownPreviewPath" - :markdown-docs-path="markdownDocsPath" - :quick-actions-docs-path="quickActionsDocsPath" - :line="line" - :note="discussionNote" - :can-suggest="canSuggest" - :add-spacing-classes="false" - :help-page-path="helpPagePath" - :show-suggest-popover="showSuggestPopover" - :textarea-value="updatedNoteBody" - @handleSuggestDismissed="() => $emit('handleSuggestDismissed')" - > - <textarea - id="note_note" - ref="textarea" - slot="textarea" - v-model="updatedNoteBody" - :data-supports-quick-actions="!isEditing" - name="note[note]" - class="note-textarea js-gfm-input js-note-text js-autosize markdown-area js-vue-issue-note-form" - data-qa-selector="reply_field" - dir="auto" - :aria-label="__('Description')" - :placeholder="__('Write a comment or drag your files here…')" - @keydown.meta.enter="handleKeySubmit()" - @keydown.ctrl.enter="handleKeySubmit()" - @keydown.exact.up="editMyLastNote()" - @keydown.exact.esc="cancelHandler(true)" - @input="onInput" - ></textarea> - </markdown-field> + <comment-field-layout :noteable-data="getNoteableData"> + <markdown-field + :markdown-preview-path="markdownPreviewPath" + :markdown-docs-path="markdownDocsPath" + :quick-actions-docs-path="quickActionsDocsPath" + :line="line" + :note="discussionNote" + :can-suggest="canSuggest" + :add-spacing-classes="false" + :help-page-path="helpPagePath" + :show-suggest-popover="showSuggestPopover" + :textarea-value="updatedNoteBody" + @handleSuggestDismissed="() => $emit('handleSuggestDismissed')" + > + <template #textarea> + <textarea + id="note_note" + ref="textarea" + v-model="updatedNoteBody" + :data-supports-quick-actions="!isEditing && !glFeatures.tributeAutocomplete" + name="note[note]" + class="note-textarea js-gfm-input js-note-text js-autosize markdown-area js-vue-issue-note-form" + data-qa-selector="reply_field" + dir="auto" + :aria-label="__('Description')" + :placeholder="__('Write a comment or drag your files here…')" + @keydown.meta.enter="handleKeySubmit()" + @keydown.ctrl.enter="handleKeySubmit()" + @keydown.exact.up="editMyLastNote()" + @keydown.exact.esc="cancelHandler(true)" + @input="onInput" + ></textarea> + </template> + </markdown-field> + </comment-field-layout> <div class="note-form-actions clearfix"> <template v-if="showBatchCommentsActions"> <p v-if="showResolveDiscussionToggle"> diff --git a/app/assets/javascripts/notes/components/noteable_discussion.vue b/app/assets/javascripts/notes/components/noteable_discussion.vue index 62ee7f30c57..0a9a3da6069 100644 --- a/app/assets/javascripts/notes/components/noteable_discussion.vue +++ b/app/assets/javascripts/notes/components/noteable_discussion.vue @@ -201,14 +201,14 @@ export default { }; this.saveNote(replyData) - .then(res => { + .then((res) => { if (res.hasFlash !== true) { this.isReplying = false; clearDraft(this.autosaveKey); } callback(); }) - .catch(err => { + .catch((err) => { this.removePlaceholderNotes(); const msg = __( 'Your comment could not be submitted! Please check your network connection and try again.', diff --git a/app/assets/javascripts/notes/components/noteable_note.vue b/app/assets/javascripts/notes/components/noteable_note.vue index 5073922e4a4..eaa64cf7c01 100644 --- a/app/assets/javascripts/notes/components/noteable_note.vue +++ b/app/assets/javascripts/notes/components/noteable_note.vue @@ -296,7 +296,7 @@ export default { this.updateSuccess(); callback(); }) - .catch(response => { + .catch((response) => { if (response.status === httpStatusCodes.GONE) { this.removeNote(this.note); this.updateSuccess(); diff --git a/app/assets/javascripts/notes/components/notes_app.vue b/app/assets/javascripts/notes/components/notes_app.vue index 9eaa4e422d5..e9e687a8743 100644 --- a/app/assets/javascripts/notes/components/notes_app.vue +++ b/app/assets/javascripts/notes/components/notes_app.vue @@ -130,7 +130,7 @@ export default { const { parentElement } = this.$el; if (parentElement && parentElement.classList.contains('js-vue-notes-event')) { - parentElement.addEventListener('toggleAward', event => { + parentElement.addEventListener('toggleAward', (event) => { const { awardName, noteId } = event.detail; this.toggleAward({ awardName, noteId }); }); @@ -217,7 +217,7 @@ export default { const noteId = hash && hash.replace(/^note_/, ''); if (noteId) { - const discussion = this.discussions.find(d => d.notes.some(({ id }) => id === noteId)); + const discussion = this.discussions.find((d) => d.notes.some(({ id }) => id === noteId)); if (discussion) { this.expandDiscussion({ discussionId: discussion.id }); diff --git a/app/assets/javascripts/notes/components/timeline_toggle.vue b/app/assets/javascripts/notes/components/timeline_toggle.vue index d1ffe0a3601..8162878f80d 100644 --- a/app/assets/javascripts/notes/components/timeline_toggle.vue +++ b/app/assets/javascripts/notes/components/timeline_toggle.vue @@ -50,7 +50,6 @@ export default { v-gl-tooltip v-track-event="trackToggleTimelineView(timelineEnabled)" icon="comments" - size="small" :selected="timelineEnabled" :title="tooltip" :aria-label="tooltip" diff --git a/app/assets/javascripts/notes/components/toggle_replies_widget.vue b/app/assets/javascripts/notes/components/toggle_replies_widget.vue index 0628e1d8647..ab7fa793bdc 100644 --- a/app/assets/javascripts/notes/components/toggle_replies_widget.vue +++ b/app/assets/javascripts/notes/components/toggle_replies_widget.vue @@ -26,9 +26,9 @@ export default { return this.replies[this.replies.length - 1]; }, uniqueAuthors() { - const authors = this.replies.map(reply => reply.author || {}); + const authors = this.replies.map((reply) => reply.author || {}); - return uniqBy(authors, author => author.username); + return uniqBy(authors, (author) => author.username); }, className() { return this.collapsed ? 'collapsed' : 'expanded'; |