diff options
Diffstat (limited to 'app/assets/javascripts/notes')
21 files changed, 161 insertions, 75 deletions
diff --git a/app/assets/javascripts/notes/components/comment_form.vue b/app/assets/javascripts/notes/components/comment_form.vue index ac93d3df654..7cfff98e9f7 100644 --- a/app/assets/javascripts/notes/components/comment_form.vue +++ b/app/assets/javascripts/notes/components/comment_form.vue @@ -6,7 +6,7 @@ import Autosize from 'autosize'; import { GlAlert, GlIntersperse, GlLink, GlSprintf } from '@gitlab/ui'; import { __, sprintf } from '~/locale'; import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue'; -import Flash from '../../flash'; +import { deprecatedCreateFlash as Flash } from '../../flash'; import Autosave from '../../autosave'; import { capitalizeFirstCharacter, diff --git a/app/assets/javascripts/notes/components/discussion_actions.vue b/app/assets/javascripts/notes/components/discussion_actions.vue index 251199f1778..878a748e99a 100644 --- a/app/assets/javascripts/notes/components/discussion_actions.vue +++ b/app/assets/javascripts/notes/components/discussion_actions.vue @@ -3,6 +3,7 @@ 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 { name: 'DiscussionActions', @@ -12,6 +13,7 @@ export default { ResolveWithIssueButton, JumpToNextDiscussionButton, }, + mixins: [glFeatureFlagsMixin()], props: { discussion: { type: Object, @@ -36,6 +38,9 @@ export default { }, }, computed: { + hideJumpToNextUnresolvedInThreads() { + return this.glFeatures.hideJumpToNextUnresolvedInThreads; + }, resolvableNotes() { return this.discussion.notes.filter(x => x.resolvable); }, @@ -70,7 +75,11 @@ export default { /> </div> <div - v-if="discussion.resolvable && shouldShowJumpToNextDiscussion" + v-if=" + !hideJumpToNextUnresolvedInThreads && + discussion.resolvable && + shouldShowJumpToNextDiscussion + " class="btn-group discussion-actions ml-sm-2" > <jump-to-next-discussion-button :from-discussion-id="discussion.id" /> diff --git a/app/assets/javascripts/notes/components/discussion_filter_note.vue b/app/assets/javascripts/notes/components/discussion_filter_note.vue index 25ff49fbd0f..8dc4b43d69a 100644 --- a/app/assets/javascripts/notes/components/discussion_filter_note.vue +++ b/app/assets/javascripts/notes/components/discussion_filter_note.vue @@ -1,5 +1,5 @@ <script> -import { GlDeprecatedButton } from '@gitlab/ui'; +import { GlButton } from '@gitlab/ui'; import Icon from '~/vue_shared/components/icon.vue'; import { __, sprintf } from '~/locale'; @@ -7,7 +7,7 @@ import notesEventHub from '../event_hub'; export default { components: { - GlDeprecatedButton, + GlButton, Icon, }, computed: { @@ -40,12 +40,12 @@ export default { <div class="timeline-content"> <div ref="timelineContent" v-html="timelineContent"></div> <div class="discussion-filter-actions mt-2"> - <gl-deprecated-button ref="showAllActivity" variant="default" @click="selectFilter(0)"> + <gl-button ref="showAllActivity" variant="default" @click="selectFilter(0)"> {{ __('Show all activity') }} - </gl-deprecated-button> - <gl-deprecated-button ref="showComments" variant="default" @click="selectFilter(1)"> + </gl-button> + <gl-button ref="showComments" variant="default" @click="selectFilter(1)"> {{ __('Show comments only') }} - </gl-deprecated-button> + </gl-button> </div> </div> </li> diff --git a/app/assets/javascripts/notes/components/discussion_keyboard_navigator.vue b/app/assets/javascripts/notes/components/discussion_navigator.vue index 2dc222d08f9..facc53e27a6 100644 --- a/app/assets/javascripts/notes/components/discussion_keyboard_navigator.vue +++ b/app/assets/javascripts/notes/components/discussion_navigator.vue @@ -2,9 +2,13 @@ /* global Mousetrap */ import 'mousetrap'; import discussionNavigation from '~/notes/mixins/discussion_navigation'; +import eventHub from '~/notes/event_hub'; export default { mixins: [discussionNavigation], + created() { + eventHub.$on('jumpToFirstUnresolvedDiscussion', this.jumpToFirstUnresolvedDiscussion); + }, mounted() { Mousetrap.bind('n', this.jumpToNextDiscussion); Mousetrap.bind('p', this.jumpToPreviousDiscussion); @@ -12,6 +16,8 @@ export default { beforeDestroy() { Mousetrap.unbind('n'); Mousetrap.unbind('p'); + + eventHub.$off('jumpToFirstUnresolvedDiscussion', this.jumpToFirstUnresolvedDiscussion); }, render() { return this.$slots.default; diff --git a/app/assets/javascripts/notes/components/discussion_notes.vue b/app/assets/javascripts/notes/components/discussion_notes.vue index 458da5cf67f..a1e887c47d0 100644 --- a/app/assets/javascripts/notes/components/discussion_notes.vue +++ b/app/assets/javascripts/notes/components/discussion_notes.vue @@ -9,6 +9,7 @@ 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'; +import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; export default { name: 'DiscussionNotes', @@ -17,6 +18,7 @@ export default { NoteEditedText, DiscussionNotesRepliesWrapper, }, + mixins: [glFeatureFlagsMixin()], props: { discussion: { type: Object, @@ -93,6 +95,18 @@ export default { componentData(note) { return note.isPlaceholderNote ? note.notes[0] : note; }, + handleMouseEnter(discussion) { + if (this.glFeatures.multilineComments && discussion.position) { + this.setSelectedCommentPositionHover(discussion.position.line_range); + } + }, + handleMouseLeave(discussion) { + // Even though position isn't used here we still don't want to unecessarily call a mutation + // The lack of position tells us that highlighting is irrelevant in this context + if (this.glFeatures.multilineComments && discussion.position) { + this.setSelectedCommentPositionHover(); + } + }, }, }; </script> @@ -101,8 +115,8 @@ export default { <div class="discussion-notes"> <ul class="notes" - @mouseenter="setSelectedCommentPositionHover(discussion.position.line_range)" - @mouseleave="setSelectedCommentPositionHover()" + @mouseenter="handleMouseEnter(discussion)" + @mouseleave="handleMouseLeave(discussion)" > <template v-if="shouldGroupReplies"> <component 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 e5f78b1c7de..cace382ccd6 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 @@ -1,12 +1,10 @@ <script> -import { GlTooltipDirective, GlDeprecatedButton } from '@gitlab/ui'; -import Icon from '~/vue_shared/components/icon.vue'; +import { GlTooltipDirective, GlButton } from '@gitlab/ui'; export default { name: 'ResolveWithIssueButton', components: { - Icon, - GlDeprecatedButton, + GlButton, }, directives: { GlTooltip: GlTooltipDirective, @@ -22,13 +20,12 @@ export default { <template> <div class="btn-group" role="group"> - <gl-deprecated-button + <gl-button v-gl-tooltip :href="url" :title="s__('MergeRequests|Resolve this thread in a new issue')" class="new-issue-for-discussion discussion-create-issue-btn" - > - <icon name="issue-new" /> - </gl-deprecated-button> + icon="issue-new" + /> </div> </template> diff --git a/app/assets/javascripts/notes/components/note_actions.vue b/app/assets/javascripts/notes/components/note_actions.vue index 7615b0518b7..a8ae7fb48f0 100644 --- a/app/assets/javascripts/notes/components/note_actions.vue +++ b/app/assets/javascripts/notes/components/note_actions.vue @@ -1,13 +1,13 @@ <script> -import { __ } from '~/locale'; import { mapGetters } from 'vuex'; import { GlLoadingIcon, GlTooltipDirective } from '@gitlab/ui'; +import { __ } from '~/locale'; import resolvedStatusMixin from '~/batch_comments/mixins/resolved_status'; import Icon from '~/vue_shared/components/icon.vue'; import ReplyButton from './note_actions/reply_button.vue'; import eventHub from '~/sidebar/event_hub'; import Api from '~/api'; -import flash from '~/flash'; +import { deprecatedCreateFlash as flash } from '~/flash'; export default { name: 'NoteActions', diff --git a/app/assets/javascripts/notes/components/note_awards_list.vue b/app/assets/javascripts/notes/components/note_awards_list.vue index 5181b5f26ee..cf3e991986c 100644 --- a/app/assets/javascripts/notes/components/note_awards_list.vue +++ b/app/assets/javascripts/notes/components/note_awards_list.vue @@ -1,7 +1,7 @@ <script> import { mapActions, mapGetters } from 'vuex'; import AwardsList from '~/vue_shared/components/awards_list.vue'; -import Flash from '../../flash'; +import { deprecatedCreateFlash as Flash } from '../../flash'; import { __ } from '~/locale'; export default { diff --git a/app/assets/javascripts/notes/components/note_header.vue b/app/assets/javascripts/notes/components/note_header.vue index 81812ee2279..9ded5ab648e 100644 --- a/app/assets/javascripts/notes/components/note_header.vue +++ b/app/assets/javascripts/notes/components/note_header.vue @@ -191,7 +191,7 @@ export default { name="eye-slash" :size="14" :title="s__('Notes|Private comments are accessible by internal staff only')" - class="gl-ml-1 gl-text-gray-800 align-middle" + class="gl-ml-1 gl-text-gray-700 align-middle" /> <slot name="extra-controls"></slot> <i diff --git a/app/assets/javascripts/notes/components/noteable_discussion.vue b/app/assets/javascripts/notes/components/noteable_discussion.vue index 7fe50d36c0c..b4176c6063b 100644 --- a/app/assets/javascripts/notes/components/noteable_discussion.vue +++ b/app/assets/javascripts/notes/components/noteable_discussion.vue @@ -7,7 +7,7 @@ import { clearDraft, getDiscussionReplyKey } from '~/lib/utils/autosave'; import icon from '~/vue_shared/components/icon.vue'; import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue'; import DraftNote from '~/batch_comments/components/draft_note.vue'; -import Flash from '../../flash'; +import { deprecatedCreateFlash as Flash } from '../../flash'; import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue'; import diffDiscussionHeader from './diff_discussion_header.vue'; import noteSignedOutWidget from './note_signed_out_widget.vue'; @@ -149,9 +149,14 @@ export default { 'removePlaceholderNotes', 'toggleResolveNote', 'removeConvertedDiscussion', + 'expandDiscussion', ]), showReplyForm() { this.isReplying = true; + + if (!this.discussion.expanded) { + this.expandDiscussion({ discussionId: this.discussion.id }); + } }, cancelReplyForm(shouldConfirm, isDirty) { if (shouldConfirm && isDirty) { diff --git a/app/assets/javascripts/notes/components/noteable_note.vue b/app/assets/javascripts/notes/components/noteable_note.vue index 9bf8cffe940..ce771e67cbb 100644 --- a/app/assets/javascripts/notes/components/noteable_note.vue +++ b/app/assets/javascripts/notes/components/noteable_note.vue @@ -7,7 +7,7 @@ import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import { truncateSha } from '~/lib/utils/text_utility'; import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue'; import { __, s__, sprintf } from '../../locale'; -import Flash from '../../flash'; +import { deprecatedCreateFlash as Flash } from '../../flash'; import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue'; import noteHeader from './note_header.vue'; import noteActions from './note_actions.vue'; @@ -23,7 +23,6 @@ import { commentLineOptions, formatLineRange, } from './multiline_comment_utils'; -import MultilineCommentForm from './multiline_comment_form.vue'; export default { name: 'NoteableNote', @@ -34,7 +33,6 @@ export default { noteActions, NoteBody, TimelineEntryItem, - MultilineCommentForm, }, mixins: [noteable, resolvable, glFeatureFlagsMixin()], props: { @@ -147,14 +145,17 @@ export default { return getEndLineNumber(this.lineRange); }, showMultiLineComment() { - if (!this.glFeatures.multilineComments || !this.discussionRoot) return false; - if (this.isEditing) return true; + if ( + !this.glFeatures.multilineComments || + !this.discussionRoot || + this.startLineNumber.length === 0 || + this.endLineNumber.length === 0 + ) + return false; return this.line && this.startLineNumber !== this.endLineNumber; }, commentLineOptions() { - if (!this.diffFile || !this.line) return []; - const sideA = this.line.type === 'new' ? 'right' : 'left'; const sideB = sideA === 'left' ? 'right' : 'left'; const lines = this.diffFile.highlighted_diff_lines.length @@ -207,6 +208,7 @@ export default { 'scrollToNoteIfNeeded', 'updateAssignees', 'setSelectedCommentPositionHover', + 'updateDiscussionPosition', ]), editHandler() { this.isEditing = true; @@ -249,8 +251,13 @@ export default { ...this.note.position, }; - if (this.commentLineStart && this.line) + if (this.discussionRoot && this.commentLineStart && this.line) { position.line_range = formatLineRange(this.commentLineStart, this.line); + this.updateDiscussionPosition({ + discussionId: this.note.discussion_id, + position, + }); + } this.$emit('handleUpdateNote', { note: this.note, @@ -337,28 +344,19 @@ export default { :data-note-id="note.id" class="note note-wrapper qa-noteable-note-item" > - <div v-if="showMultiLineComment" data-testid="multiline-comment"> - <multiline-comment-form - v-if="isEditing && note.position" - v-model="commentLineStart" - :line="line" - :comment-line-options="commentLineOptions" - :line-range="note.position.line_range" - class="gl-mb-3 gl-text-gray-700 gl-pb-3" - /> - <div - v-else - class="gl-mb-3 gl-text-gray-700 gl-border-gray-200 gl-border-b-solid gl-border-b-1 gl-pb-3" - > - <gl-sprintf :message="__('Comment on lines %{startLine} to %{endLine}')"> - <template #startLine> - <span :class="getLineClasses(startLineNumber)">{{ startLineNumber }}</span> - </template> - <template #endLine> - <span :class="getLineClasses(endLineNumber)">{{ endLineNumber }}</span> - </template> - </gl-sprintf> - </div> + <div + v-if="showMultiLineComment" + data-testid="multiline-comment" + class="gl-mb-3 gl-text-gray-500 gl-border-gray-200 gl-border-b-solid gl-border-b-1 gl-pb-3" + > + <gl-sprintf :message="__('Comment on lines %{startLine} to %{endLine}')"> + <template #startLine> + <span :class="getLineClasses(startLineNumber)">{{ startLineNumber }}</span> + </template> + <template #endLine> + <span :class="getLineClasses(endLineNumber)">{{ endLineNumber }}</span> + </template> + </gl-sprintf> </div> <div v-once class="timeline-icon"> <user-avatar-link diff --git a/app/assets/javascripts/notes/components/notes_app.vue b/app/assets/javascripts/notes/components/notes_app.vue index faa6006945d..fb18be9386e 100644 --- a/app/assets/javascripts/notes/components/notes_app.vue +++ b/app/assets/javascripts/notes/components/notes_app.vue @@ -1,7 +1,7 @@ <script> import { mapGetters, mapActions } from 'vuex'; import { getLocationHash, doesHashExistInUrl } from '../../lib/utils/url_utility'; -import Flash from '../../flash'; +import { deprecatedCreateFlash as Flash } from '../../flash'; import * as constants from '../constants'; import eventHub from '../event_hub'; import noteableNote from './noteable_note.vue'; @@ -136,6 +136,8 @@ export default { } window.addEventListener('hashchange', this.handleHashChanged); + + eventHub.$on('notesApp.updateIssuableConfidentiality', this.setConfidentiality); }, updated() { this.$nextTick(() => { @@ -146,6 +148,7 @@ export default { beforeDestroy() { this.stopPolling(); window.removeEventListener('hashchange', this.handleHashChanged); + eventHub.$off('notesApp.updateIssuableConfidentiality', this.setConfidentiality); }, methods: { ...mapActions([ @@ -164,6 +167,7 @@ export default { 'startTaskList', 'convertToDiscussion', 'stopPolling', + 'setConfidentiality', ]), discussionIsIndividualNoteAndNotConverted(discussion) { return discussion.individual_note && !this.convertedDisscussionIds.includes(discussion.id); diff --git a/app/assets/javascripts/notes/event_hub.js b/app/assets/javascripts/notes/event_hub.js index 0948c2e5352..e31806ad199 100644 --- a/app/assets/javascripts/notes/event_hub.js +++ b/app/assets/javascripts/notes/event_hub.js @@ -1,3 +1,3 @@ -import Vue from 'vue'; +import createEventHub from '~/helpers/event_hub_factory'; -export default new Vue(); +export default createEventHub(); diff --git a/app/assets/javascripts/notes/index.js b/app/assets/javascripts/notes/index.js index ba814649078..7bf465482b3 100644 --- a/app/assets/javascripts/notes/index.js +++ b/app/assets/javascripts/notes/index.js @@ -20,6 +20,11 @@ document.addEventListener('DOMContentLoaded', () => { noteableData.noteableType = notesDataset.noteableType; noteableData.targetType = notesDataset.targetType; + if (noteableData.discussion_locked === null) { + // discussion_locked has never been set for this issuable. + // set to `false` for safety. + noteableData.discussion_locked = false; + } if (parsedUserData) { currentUserData = { diff --git a/app/assets/javascripts/notes/mixins/diff_line_note_form.js b/app/assets/javascripts/notes/mixins/diff_line_note_form.js index 9a2e86aeed2..c4a42eb1a98 100644 --- a/app/assets/javascripts/notes/mixins/diff_line_note_form.js +++ b/app/assets/javascripts/notes/mixins/diff_line_note_form.js @@ -1,7 +1,7 @@ import { mapActions, mapGetters, mapState } from 'vuex'; import { getDraftReplyFormData, getDraftFormData } from '~/batch_comments/utils'; import { TEXT_DIFF_POSITION_TYPE, IMAGE_DIFF_POSITION_TYPE } from '~/diffs/constants'; -import createFlash from '~/flash'; +import { deprecatedCreateFlash as createFlash } from '~/flash'; import { s__ } from '~/locale'; import { clearDraft } from '~/lib/utils/autosave'; import { formatLineRange } from '~/notes/components/multiline_comment_utils'; diff --git a/app/assets/javascripts/notes/mixins/discussion_navigation.js b/app/assets/javascripts/notes/mixins/discussion_navigation.js index 889883a23d0..61298a15c5d 100644 --- a/app/assets/javascripts/notes/mixins/discussion_navigation.js +++ b/app/assets/javascripts/notes/mixins/discussion_navigation.js @@ -78,7 +78,7 @@ function handleDiscussionJump(self, fn, discussionId = self.currentDiscussionId) const isDiffView = window.mrTabs.currentAction === 'diffs'; const targetId = fn(discussionId, isDiffView); const discussion = self.getDiscussion(targetId); - const discussionFilePath = discussion.diff_file?.file_path; + const discussionFilePath = discussion?.diff_file?.file_path; if (discussionFilePath) { self.scrollToFile(discussionFilePath); @@ -113,6 +113,14 @@ export default { handleDiscussionJump(this, this.previousUnresolvedDiscussionId); }, + jumpToFirstUnresolvedDiscussion() { + this.setCurrentDiscussionId(null) + .then(() => { + this.jumpToNextDiscussion(); + }) + .catch(() => {}); + }, + /** * Go to the next discussion from the given discussionId * @param {String} discussionId The id we are jumping from diff --git a/app/assets/javascripts/notes/mixins/resolvable.js b/app/assets/javascripts/notes/mixins/resolvable.js index 16b7598ee09..087b5828cce 100644 --- a/app/assets/javascripts/notes/mixins/resolvable.js +++ b/app/assets/javascripts/notes/mixins/resolvable.js @@ -1,4 +1,4 @@ -import Flash from '~/flash'; +import { deprecatedCreateFlash as Flash } from '~/flash'; import { __ } from '~/locale'; export default { diff --git a/app/assets/javascripts/notes/stores/actions.js b/app/assets/javascripts/notes/stores/actions.js index 5b2ab255557..f6069b509e8 100644 --- a/app/assets/javascripts/notes/stores/actions.js +++ b/app/assets/javascripts/notes/stores/actions.js @@ -3,7 +3,7 @@ import $ from 'jquery'; import Visibility from 'visibilityjs'; import axios from '~/lib/utils/axios_utils'; import TaskList from '../../task_list'; -import Flash from '../../flash'; +import { deprecatedCreateFlash as Flash } from '../../flash'; import Poll from '../../lib/utils/poll'; import * as types from './mutation_types'; import * as utils from './utils'; @@ -13,32 +13,35 @@ import sidebarTimeTrackingEventHub from '../../sidebar/event_hub'; import { isInViewport, scrollToElement, isInMRPage } from '../../lib/utils/common_utils'; import { mergeUrlParams } from '../../lib/utils/url_utility'; import mrWidgetEventHub from '../../vue_merge_request_widget/event_hub'; -import updateIssueConfidentialMutation from '~/sidebar/components/confidential/queries/update_issue_confidential.mutation.graphql'; +import updateIssueConfidentialMutation from '~/sidebar/components/confidential/mutations/update_issue_confidential.mutation.graphql'; +import updateMergeRequestLockMutation from '~/sidebar/components/lock/mutations/update_merge_request_lock.mutation.graphql'; +import updateIssueLockMutation from '~/sidebar/components/lock/mutations/update_issue_lock.mutation.graphql'; import { __, sprintf } from '~/locale'; import Api from '~/api'; let eTagPoll; -export const updateConfidentialityOnIssue = ({ commit, getters }, { confidential, fullPath }) => { - const { iid } = getters.getNoteableData; +export const updateLockedAttribute = ({ commit, getters }, { locked, fullPath }) => { + const { iid, targetType } = getters.getNoteableData; return utils.gqClient .mutate({ - mutation: updateIssueConfidentialMutation, + mutation: targetType === 'issue' ? updateIssueLockMutation : updateMergeRequestLockMutation, variables: { input: { projectPath: fullPath, iid: String(iid), - confidential, + locked, }, }, }) .then(({ data }) => { - const { - issueSetConfidential: { issue }, - } = data; + const discussionLocked = + targetType === 'issue' + ? data.issueSetLocked.issue.discussionLocked + : data.mergeRequestSetLocked.mergeRequest.discussionLocked; - commit(types.SET_ISSUE_CONFIDENTIAL, issue.confidential); + commit(types.SET_ISSUABLE_LOCK, discussionLocked); }); }; @@ -683,5 +686,32 @@ export const updateAssignees = ({ commit }, assignees) => { commit(types.UPDATE_ASSIGNEES, assignees); }; -// prevent babel-plugin-rewire from generating an invalid default during karma tests -export default () => {}; +export const updateDiscussionPosition = ({ commit }, updatedPosition) => { + commit(types.UPDATE_DISCUSSION_POSITION, updatedPosition); +}; + +export const updateConfidentialityOnIssuable = ( + { getters, commit }, + { confidential, fullPath }, +) => { + const { iid } = getters.getNoteableData; + + return utils.gqClient + .mutate({ + mutation: updateIssueConfidentialMutation, + variables: { + input: { + projectPath: fullPath, + iid: String(iid), + confidential, + }, + }, + }) + .then(({ data }) => { + const { + issueSetConfidential: { issue }, + } = data; + + setConfidentiality({ commit }, issue.confidential); + }); +}; diff --git a/app/assets/javascripts/notes/stores/getters.js b/app/assets/javascripts/notes/stores/getters.js index 85997b44bcc..7d60fbffb10 100644 --- a/app/assets/javascripts/notes/stores/getters.js +++ b/app/assets/javascripts/notes/stores/getters.js @@ -194,7 +194,9 @@ export const findUnresolvedDiscussionIdNeighbor = (state, getters) => ({ diffOrder, step, }) => { - const ids = getters.unresolvedDiscussionsIdsOrdered(diffOrder); + const diffIds = getters.unresolvedDiscussionsIdsOrdered(diffOrder); + const dateIds = getters.unresolvedDiscussionsIdsOrdered(false); + const ids = diffIds.length ? diffIds : dateIds; const index = ids.indexOf(discussionId) + step; if (index < 0 && step < 0) { @@ -229,6 +231,3 @@ export const getDiscussion = state => discussionId => state.discussions.find(discussion => discussion.id === discussionId); export const commentsDisabled = state => state.commentsDisabled; - -// prevent babel-plugin-rewire from generating an invalid default during karma tests -export default () => {}; diff --git a/app/assets/javascripts/notes/stores/mutation_types.js b/app/assets/javascripts/notes/stores/mutation_types.js index f2236b18beb..eb3447291bc 100644 --- a/app/assets/javascripts/notes/stores/mutation_types.js +++ b/app/assets/javascripts/notes/stores/mutation_types.js @@ -12,6 +12,7 @@ export const SHOW_PLACEHOLDER_NOTE = 'SHOW_PLACEHOLDER_NOTE'; export const TOGGLE_AWARD = 'TOGGLE_AWARD'; export const UPDATE_NOTE = 'UPDATE_NOTE'; export const UPDATE_DISCUSSION = 'UPDATE_DISCUSSION'; +export const UPDATE_DISCUSSION_POSITION = 'UPDATE_DISCUSSION_POSITION'; export const SET_DISCUSSION_DIFF_LINES = 'SET_DISCUSSION_DIFF_LINES'; export const SET_NOTES_FETCHED_STATE = 'SET_NOTES_FETCHED_STATE'; export const SET_NOTES_LOADING_STATE = 'SET_NOTES_LOADING_STATE'; @@ -42,6 +43,7 @@ export const REOPEN_ISSUE = 'REOPEN_ISSUE'; export const TOGGLE_STATE_BUTTON_LOADING = 'TOGGLE_STATE_BUTTON_LOADING'; export const TOGGLE_BLOCKED_ISSUE_WARNING = 'TOGGLE_BLOCKED_ISSUE_WARNING'; export const SET_ISSUE_CONFIDENTIAL = 'SET_ISSUE_CONFIDENTIAL'; +export const SET_ISSUABLE_LOCK = 'SET_ISSUABLE_LOCK'; // Description version export const REQUEST_DESCRIPTION_VERSION = 'REQUEST_DESCRIPTION_VERSION'; diff --git a/app/assets/javascripts/notes/stores/mutations.js b/app/assets/javascripts/notes/stores/mutations.js index e5f1c11fb35..aa078f00569 100644 --- a/app/assets/javascripts/notes/stores/mutations.js +++ b/app/assets/javascripts/notes/stores/mutations.js @@ -99,6 +99,10 @@ export default { state.noteableData.confidential = data; }, + [types.SET_ISSUABLE_LOCK](state, locked) { + state.noteableData.discussion_locked = locked; + }, + [types.SET_USER_DATA](state, data) { Object.assign(state, { userData: data }); }, @@ -274,6 +278,11 @@ export default { Object.assign(selectedDiscussion, { ...note }); }, + [types.UPDATE_DISCUSSION_POSITION](state, { discussionId, position }) { + const selectedDiscussion = state.discussions.find(disc => disc.id === discussionId); + if (selectedDiscussion) Object.assign(selectedDiscussion.position, { ...position }); + }, + [types.CLOSE_ISSUE](state) { Object.assign(state.noteableData, { state: constants.CLOSED }); }, |