diff options
Diffstat (limited to 'app/assets/javascripts/notes')
29 files changed, 113 insertions, 63 deletions
diff --git a/app/assets/javascripts/notes/components/attachments_warning.vue b/app/assets/javascripts/notes/components/attachments_warning.vue index aaa4b0d92b9..aa19dd58c0f 100644 --- a/app/assets/javascripts/notes/components/attachments_warning.vue +++ b/app/assets/javascripts/notes/components/attachments_warning.vue @@ -12,7 +12,7 @@ export default { </script> <template> - <div class="issuable-note-warning" data-testid="attachment-warning"> + <div class="issuable-note-warning"> {{ message }} </div> </template> diff --git a/app/assets/javascripts/notes/components/comment_form.vue b/app/assets/javascripts/notes/components/comment_form.vue index c6d94a3b7b7..a009f2975bb 100644 --- a/app/assets/javascripts/notes/components/comment_form.vue +++ b/app/assets/javascripts/notes/components/comment_form.vue @@ -1,6 +1,7 @@ <script> import { GlAlert, GlButton, GlIcon, GlFormCheckbox, GlTooltipDirective } from '@gitlab/ui'; import $ from 'jquery'; +// eslint-disable-next-line no-restricted-imports import { mapActions, mapGetters, mapState } from 'vuex'; import { refreshUserMergeRequestCounts } from '~/commons/nav/user_merge_requests'; import { createAlert } from '~/alert'; diff --git a/app/assets/javascripts/notes/components/diff_discussion_header.vue b/app/assets/javascripts/notes/components/diff_discussion_header.vue index e7b7ba7743e..75cacd9ace0 100644 --- a/app/assets/javascripts/notes/components/diff_discussion_header.vue +++ b/app/assets/javascripts/notes/components/diff_discussion_header.vue @@ -1,6 +1,7 @@ <script> import { GlAvatar, GlAvatarLink } from '@gitlab/ui'; import { escape } from 'lodash'; +// eslint-disable-next-line no-restricted-imports import { mapActions } from 'vuex'; import SafeHtml from '~/vue_shared/directives/safe_html'; import { truncateSha } from '~/lib/utils/text_utility'; diff --git a/app/assets/javascripts/notes/components/diff_with_note.vue b/app/assets/javascripts/notes/components/diff_with_note.vue index b1a2ab77fa8..f08c005259c 100644 --- a/app/assets/javascripts/notes/components/diff_with_note.vue +++ b/app/assets/javascripts/notes/components/diff_with_note.vue @@ -1,5 +1,6 @@ <script> import { GlSkeletonLoader } from '@gitlab/ui'; +// eslint-disable-next-line no-restricted-imports import { mapState, mapActions } from 'vuex'; import SafeHtml from '~/vue_shared/directives/safe_html'; import DiffFileHeader from '~/diffs/components/diff_file_header.vue'; diff --git a/app/assets/javascripts/notes/components/discussion_counter.vue b/app/assets/javascripts/notes/components/discussion_counter.vue index cff1043c258..d8883f90eda 100644 --- a/app/assets/javascripts/notes/components/discussion_counter.vue +++ b/app/assets/javascripts/notes/components/discussion_counter.vue @@ -1,5 +1,6 @@ <script> import { GlButton, GlButtonGroup, GlDisclosureDropdown, GlTooltipDirective } from '@gitlab/ui'; +// eslint-disable-next-line no-restricted-imports import { mapActions, mapGetters } from 'vuex'; import { throttle } from 'lodash'; import { __ } from '~/locale'; diff --git a/app/assets/javascripts/notes/components/discussion_filter.vue b/app/assets/javascripts/notes/components/discussion_filter.vue index 692fd6cc500..7266cdb6405 100644 --- a/app/assets/javascripts/notes/components/discussion_filter.vue +++ b/app/assets/javascripts/notes/components/discussion_filter.vue @@ -5,6 +5,7 @@ import { GlDisclosureDropdownGroup, GlDisclosureDropdownItem, } from '@gitlab/ui'; +// eslint-disable-next-line no-restricted-imports import { mapGetters, mapActions } from 'vuex'; import { getLocationHash, doesHashExistInUrl } from '~/lib/utils/url_utility'; import { __ } from '~/locale'; diff --git a/app/assets/javascripts/notes/components/discussion_notes.vue b/app/assets/javascripts/notes/components/discussion_notes.vue index 080787884c8..79157c3f99c 100644 --- a/app/assets/javascripts/notes/components/discussion_notes.vue +++ b/app/assets/javascripts/notes/components/discussion_notes.vue @@ -1,4 +1,5 @@ <script> +// eslint-disable-next-line no-restricted-imports import { mapGetters, mapActions } from 'vuex'; import { __ } from '~/locale'; import PlaceholderNote from '~/vue_shared/components/notes/placeholder_note.vue'; diff --git a/app/assets/javascripts/notes/components/email_participants_warning.vue b/app/assets/javascripts/notes/components/email_participants_warning.vue index 1875d48e7b2..cf9108992be 100644 --- a/app/assets/javascripts/notes/components/email_participants_warning.vue +++ b/app/assets/javascripts/notes/components/email_participants_warning.vue @@ -55,7 +55,7 @@ export default { </script> <template> - <div class="issuable-note-warning" data-testid="email-participants-warning"> + <div class="issuable-note-warning"> <gl-sprintf :message="message"> <template #andMore> <button type="button" class="gl-button btn-link" @click="showMoreParticipants"> diff --git a/app/assets/javascripts/notes/components/mr_discussion_filter.vue b/app/assets/javascripts/notes/components/mr_discussion_filter.vue index 7ca0c4730a9..08d3670ae6a 100644 --- a/app/assets/javascripts/notes/components/mr_discussion_filter.vue +++ b/app/assets/javascripts/notes/components/mr_discussion_filter.vue @@ -1,5 +1,6 @@ <script> import { GlCollapsibleListbox, GlButton, GlIcon, GlSprintf, GlButtonGroup } from '@gitlab/ui'; +// eslint-disable-next-line no-restricted-imports import { mapActions, mapState } from 'vuex'; import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue'; import { __ } from '~/locale'; diff --git a/app/assets/javascripts/notes/components/multiline_comment_form.vue b/app/assets/javascripts/notes/components/multiline_comment_form.vue index 1633b79c3be..2c2264c36f3 100644 --- a/app/assets/javascripts/notes/components/multiline_comment_form.vue +++ b/app/assets/javascripts/notes/components/multiline_comment_form.vue @@ -1,5 +1,6 @@ <script> import { GlFormSelect, GlSprintf } from '@gitlab/ui'; +// eslint-disable-next-line no-restricted-imports import { mapActions } from 'vuex'; import { getSymbol, getLineClasses } from './multiline_comment_utils'; diff --git a/app/assets/javascripts/notes/components/note_actions.vue b/app/assets/javascripts/notes/components/note_actions.vue index 8d2d8095a44..7f23ee70086 100644 --- a/app/assets/javascripts/notes/components/note_actions.vue +++ b/app/assets/javascripts/notes/components/note_actions.vue @@ -5,6 +5,7 @@ import { GlDisclosureDropdown, GlDisclosureDropdownItem, } from '@gitlab/ui'; +// eslint-disable-next-line no-restricted-imports import { mapActions, mapGetters, mapState } from 'vuex'; import Api from '~/api'; import resolvedStatusMixin from '~/batch_comments/mixins/resolved_status'; diff --git a/app/assets/javascripts/notes/components/note_awards_list.vue b/app/assets/javascripts/notes/components/note_awards_list.vue index 9c04a72375b..21f226cd207 100644 --- a/app/assets/javascripts/notes/components/note_awards_list.vue +++ b/app/assets/javascripts/notes/components/note_awards_list.vue @@ -1,4 +1,5 @@ <script> +// eslint-disable-next-line no-restricted-imports import { mapActions, mapGetters } from 'vuex'; import { createAlert } from '~/alert'; import { __ } from '~/locale'; diff --git a/app/assets/javascripts/notes/components/note_body.vue b/app/assets/javascripts/notes/components/note_body.vue index 1c6be0cfd77..fcb9dc43e8e 100644 --- a/app/assets/javascripts/notes/components/note_body.vue +++ b/app/assets/javascripts/notes/components/note_body.vue @@ -1,5 +1,6 @@ <script> import { escape } from 'lodash'; +// eslint-disable-next-line no-restricted-imports import { mapActions, mapGetters, mapState } from 'vuex'; import SafeHtml from '~/vue_shared/directives/safe_html'; import { __ } from '~/locale'; diff --git a/app/assets/javascripts/notes/components/note_form.vue b/app/assets/javascripts/notes/components/note_form.vue index 4e816038539..8b43f068f11 100644 --- a/app/assets/javascripts/notes/components/note_form.vue +++ b/app/assets/javascripts/notes/components/note_form.vue @@ -1,5 +1,6 @@ <script> import { GlButton, GlSprintf, GlLink, GlFormCheckbox } from '@gitlab/ui'; +// eslint-disable-next-line no-restricted-imports import { mapGetters, mapActions, mapState } from 'vuex'; import { mergeUrlParams } from '~/lib/utils/url_utility'; import { __ } from '~/locale'; @@ -245,15 +246,16 @@ export default { }, methods: { ...mapActions(['toggleResolveNote']), - shouldToggleResolved(shouldResolve, beforeSubmitDiscussionState) { - const newResolvedStateAfterUpdate = - this.shouldBeResolved && this.shouldBeResolved(shouldResolve); - - const shouldToggleState = - newResolvedStateAfterUpdate !== undefined && - beforeSubmitDiscussionState !== newResolvedStateAfterUpdate; - - return shouldResolve || shouldToggleState; + shouldToggleResolved(beforeSubmitDiscussionState) { + return ( + this.showResolveDiscussionToggle && beforeSubmitDiscussionState !== this.newResolvedState() + ); + }, + newResolvedState() { + return ( + (this.discussionResolved && !this.isUnresolving) || + (!this.discussionResolved && this.isResolving) + ); }, editMyLastNote() { if (this.updatedNoteBody === '') { @@ -293,7 +295,7 @@ export default { } this.updatedNoteBody = ''; }, - handleUpdate(shouldResolve) { + handleUpdate() { const beforeSubmitDiscussionState = this.discussionResolved; this.isSubmitting = true; @@ -309,23 +311,13 @@ export default { () => { this.isSubmitting = false; - if (this.shouldToggleResolved(shouldResolve, beforeSubmitDiscussionState)) { + if (this.shouldToggleResolved(beforeSubmitDiscussionState)) { this.resolveHandler(beforeSubmitDiscussionState); } }, this.discussionResolved ? !this.isUnresolving : this.isResolving, ); }, - shouldBeResolved(resolveStatus) { - if (this.withBatchComments) { - return ( - (this.discussionResolved && !this.isUnresolving) || - (!this.discussionResolved && this.isResolving) - ); - } - - return resolveStatus; - }, handleAddToReview() { // check if draft should resolve thread const shouldResolve = @@ -390,21 +382,22 @@ export default { /> </comment-field-layout> <div class="note-form-actions"> + <p v-if="showResolveDiscussionToggle"> + <label> + <template v-if="discussionResolved"> + <gl-form-checkbox v-model="isUnresolving" class="js-unresolve-checkbox"> + {{ __('Unresolve thread') }} + </gl-form-checkbox> + </template> + <template v-else> + <gl-form-checkbox v-model="isResolving" class="js-resolve-checkbox"> + {{ __('Resolve thread') }} + </gl-form-checkbox> + </template> + </label> + </p> + <template v-if="showBatchCommentsActions"> - <p v-if="showResolveDiscussionToggle"> - <label> - <template v-if="discussionResolved"> - <gl-form-checkbox v-model="isUnresolving" class="js-unresolve-checkbox"> - {{ __('Unresolve thread') }} - </gl-form-checkbox> - </template> - <template v-else> - <gl-form-checkbox v-model="isResolving" class="js-resolve-checkbox"> - {{ __('Resolve thread') }} - </gl-form-checkbox> - </template> - </label> - </p> <div class="gl-display-flex gl-flex-wrap gl-mb-n3"> <gl-button :disabled="isDisabled" @@ -451,15 +444,6 @@ export default { {{ saveButtonTitle }} </gl-button> <gl-button - v-if="discussion.resolvable" - category="secondary" - variant="default" - class="gl-sm-mr-3 gl-xs-mb-3 js-comment-resolve-button" - @click.prevent="handleUpdate(true)" - > - {{ resolveButtonTitle }} - </gl-button> - <gl-button class="note-edit-cancel js-close-discussion-note-form" category="secondary" variant="default" diff --git a/app/assets/javascripts/notes/components/note_header.vue b/app/assets/javascripts/notes/components/note_header.vue index 83cebb9a0e0..bdf9ea2057c 100644 --- a/app/assets/javascripts/notes/components/note_header.vue +++ b/app/assets/javascripts/notes/components/note_header.vue @@ -1,5 +1,6 @@ <script> import { GlIcon, GlBadge, GlLoadingIcon, GlTooltipDirective } from '@gitlab/ui'; +// eslint-disable-next-line no-restricted-imports import { mapActions } from 'vuex'; import { getIdFromGraphQLId } from '~/graphql_shared/utils'; import { __, s__ } from '~/locale'; 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 94636b3e47b..30d3bfcb989 100644 --- a/app/assets/javascripts/notes/components/note_signed_out_widget.vue +++ b/app/assets/javascripts/notes/components/note_signed_out_widget.vue @@ -1,4 +1,5 @@ <script> +// eslint-disable-next-line no-restricted-imports import { mapGetters } from 'vuex'; import SafeHtml from '~/vue_shared/directives/safe_html'; import { __, sprintf } from '~/locale'; diff --git a/app/assets/javascripts/notes/components/noteable_discussion.vue b/app/assets/javascripts/notes/components/noteable_discussion.vue index 7e79edfea15..94d5dc25b9e 100644 --- a/app/assets/javascripts/notes/components/noteable_discussion.vue +++ b/app/assets/javascripts/notes/components/noteable_discussion.vue @@ -1,5 +1,6 @@ <script> import { GlTooltipDirective, GlIcon } from '@gitlab/ui'; +// eslint-disable-next-line no-restricted-imports import { mapActions, mapGetters } from 'vuex'; import DraftNote from '~/batch_comments/components/draft_note.vue'; import { createAlert } from '~/alert'; diff --git a/app/assets/javascripts/notes/components/noteable_note.vue b/app/assets/javascripts/notes/components/noteable_note.vue index 69c41af97ab..9a7cc1a4d37 100644 --- a/app/assets/javascripts/notes/components/noteable_note.vue +++ b/app/assets/javascripts/notes/components/noteable_note.vue @@ -2,6 +2,7 @@ import { GlSprintf, GlAvatarLink, GlAvatar } from '@gitlab/ui'; import $ from 'jquery'; import { escape, isEmpty } from 'lodash'; +// eslint-disable-next-line no-restricted-imports import { mapGetters, mapActions } from 'vuex'; import SafeHtml from '~/vue_shared/directives/safe_html'; import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal'; diff --git a/app/assets/javascripts/notes/components/notes_app.vue b/app/assets/javascripts/notes/components/notes_app.vue index 06c925002b6..6fb958e810b 100644 --- a/app/assets/javascripts/notes/components/notes_app.vue +++ b/app/assets/javascripts/notes/components/notes_app.vue @@ -1,4 +1,5 @@ <script> +// eslint-disable-next-line no-restricted-imports import { mapGetters, mapActions } from 'vuex'; import highlightCurrentUser from '~/behaviors/markdown/highlight_current_user'; import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue'; @@ -231,7 +232,7 @@ export default { :ai-loading="aiLoading" @set-ai-loading="setAiLoading" /> - <ai-summary v-if="aiLoading !== null" @set-ai-loading="setAiLoading" /> + <ai-summary v-if="aiLoading !== null" :ai-loading="aiLoading" @set-ai-loading="setAiLoading" /> <ordered-layout :slot-keys="slotKeys"> <template #form> <comment-form diff --git a/app/assets/javascripts/notes/components/sidebar_subscription.vue b/app/assets/javascripts/notes/components/sidebar_subscription.vue index 2a0a3d5414f..f60a17eb36b 100644 --- a/app/assets/javascripts/notes/components/sidebar_subscription.vue +++ b/app/assets/javascripts/notes/components/sidebar_subscription.vue @@ -1,4 +1,5 @@ <script> +// eslint-disable-next-line no-restricted-imports import { mapActions } from 'vuex'; import { TYPE_EPIC, TYPE_ISSUE } from '~/issues/constants'; import { fetchPolicies } from '~/lib/graphql'; diff --git a/app/assets/javascripts/notes/components/timeline_toggle.vue b/app/assets/javascripts/notes/components/timeline_toggle.vue index 59a3cc2d306..a627047faf9 100644 --- a/app/assets/javascripts/notes/components/timeline_toggle.vue +++ b/app/assets/javascripts/notes/components/timeline_toggle.vue @@ -1,5 +1,6 @@ <script> import { GlButton, GlTooltipDirective } from '@gitlab/ui'; +// eslint-disable-next-line no-restricted-imports import { mapActions, mapGetters } from 'vuex'; import { s__ } from '~/locale'; import TrackEventDirective from '~/vue_shared/directives/track_event'; diff --git a/app/assets/javascripts/notes/constants.js b/app/assets/javascripts/notes/constants.js index 419b427682e..999ef8ff905 100644 --- a/app/assets/javascripts/notes/constants.js +++ b/app/assets/javascripts/notes/constants.js @@ -10,6 +10,9 @@ export const COMMENT = 'comment'; export const ISSUE_NOTEABLE_TYPE = 'Issue'; export const EPIC_NOTEABLE_TYPE = 'Epic'; export const MERGE_REQUEST_NOTEABLE_TYPE = 'MergeRequest'; +export const SNIPPET_NOTEABLE_TYPE = 'Snippet'; +export const DESIGN_NOTEABLE_TYPE = 'DesignManagement::Design'; +export const COMMIT_NOTEABLE_TYPE = 'Commit'; export const INCIDENT_NOTEABLE_TYPE = 'INCIDENT'; // TODO: check if value can be converted to `Incident` export const UNRESOLVE_NOTE_METHOD_NAME = 'delete'; export const RESOLVE_NOTE_METHOD_NAME = 'post'; 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 cb6f72538b9..34090d22cec 100644 --- a/app/assets/javascripts/notes/mixins/diff_line_note_form.js +++ b/app/assets/javascripts/notes/mixins/diff_line_note_form.js @@ -1,3 +1,4 @@ +// eslint-disable-next-line no-restricted-imports import { mapActions, mapGetters, mapState } from 'vuex'; import { getDraftReplyFormData, getDraftFormData } from '~/batch_comments/utils'; import { diff --git a/app/assets/javascripts/notes/mixins/discussion_navigation.js b/app/assets/javascripts/notes/mixins/discussion_navigation.js index 8e69f1ddc88..212ca6851f6 100644 --- a/app/assets/javascripts/notes/mixins/discussion_navigation.js +++ b/app/assets/javascripts/notes/mixins/discussion_navigation.js @@ -1,3 +1,4 @@ +// eslint-disable-next-line no-restricted-imports import { mapGetters, mapActions, mapState } from 'vuex'; import { scrollToElement, contentTop } from '~/lib/utils/common_utils'; diff --git a/app/assets/javascripts/notes/mixins/issuable_state.js b/app/assets/javascripts/notes/mixins/issuable_state.js index 52b67764b70..54f1a1a0cb3 100644 --- a/app/assets/javascripts/notes/mixins/issuable_state.js +++ b/app/assets/javascripts/notes/mixins/issuable_state.js @@ -1,3 +1,4 @@ +// eslint-disable-next-line no-restricted-imports import { mapGetters } from 'vuex'; export default { diff --git a/app/assets/javascripts/notes/mixins/resolvable.js b/app/assets/javascripts/notes/mixins/resolvable.js index 63822a31cd1..814702b724d 100644 --- a/app/assets/javascripts/notes/mixins/resolvable.js +++ b/app/assets/javascripts/notes/mixins/resolvable.js @@ -11,14 +11,6 @@ export default { return this.note.resolved; }, resolveButtonTitle() { - if (this.updatedNoteBody) { - if (this.discussionResolved) { - return __('Comment & unresolve thread'); - } - - return __('Comment & resolve thread'); - } - return this.discussionResolved ? __('Unresolve thread') : __('Resolve thread'); }, }, diff --git a/app/assets/javascripts/notes/stores/actions.js b/app/assets/javascripts/notes/stores/actions.js index 1bb44988c4d..0444eca9aa7 100644 --- a/app/assets/javascripts/notes/stores/actions.js +++ b/app/assets/javascripts/notes/stores/actions.js @@ -1,6 +1,7 @@ import $ from 'jquery'; import Visibility from 'visibilityjs'; import Vue from 'vue'; +import actionCable from '~/actioncable_consumer'; import Api from '~/api'; import { createAlert, VARIANT_INFO } from '~/alert'; import { EVENT_ISSUABLE_VUE_APP_CHANGE } from '~/issuable/constants'; @@ -151,7 +152,30 @@ export const initPolling = ({ state, dispatch, getters, commit }) => { dispatch('setLastFetchedAt', getters.getNotesDataByProp('lastFetchedAt')); - dispatch('poll'); + if (gon.features?.actionCableNotes) { + actionCable.subscriptions.create( + { + channel: 'Noteable::NotesChannel', + project_id: state.notesData.projectId, + group_id: state.notesData.groupId, + noteable_type: state.notesData.noteableType, + noteable_id: state.notesData.noteableId, + }, + { + connected() { + dispatch('fetchUpdatedNotes'); + }, + received(data) { + if (data.event === 'updated') { + dispatch('fetchUpdatedNotes'); + } + }, + }, + ); + } else { + dispatch('poll'); + } + commit(types.SET_IS_POLLING_INITIALIZED, true); }; @@ -491,7 +515,7 @@ export const saveNote = ({ commit, dispatch }, noteData) => { {"commands_changes":{},"valid":false,"errors":{"commands_only":["Commands applied"]}} */ if (hasQuickActions && message) { - eTagPoll.makeRequest(); + if (eTagPoll) eTagPoll.makeRequest(); // synchronizing the quick action with the sidebar widget // this is a temporary solution until we have confidentiality real-time updates @@ -592,6 +616,21 @@ const getFetchDataParams = (state) => { return { endpoint, options }; }; +export const fetchUpdatedNotes = ({ commit, state, getters, dispatch }) => { + const { endpoint, options } = getFetchDataParams(state); + + return axios + .get(endpoint, options) + .then(({ data }) => { + pollSuccessCallBack(data, commit, state, getters, dispatch); + }) + .catch(() => { + createAlert({ + message: __('Something went wrong while fetching latest comments.'), + }); + }); +}; + export const poll = ({ commit, state, getters, dispatch }) => { const notePollOccurrenceTracking = create(); let alert; diff --git a/app/assets/javascripts/notes/stores/index.js b/app/assets/javascripts/notes/stores/index.js index c4895f58656..483e21b340e 100644 --- a/app/assets/javascripts/notes/stores/index.js +++ b/app/assets/javascripts/notes/stores/index.js @@ -1,4 +1,5 @@ import Vue from 'vue'; +// eslint-disable-next-line no-restricted-imports import Vuex from 'vuex'; import notesModule from './modules'; diff --git a/app/assets/javascripts/notes/stores/mutations.js b/app/assets/javascripts/notes/stores/mutations.js index a67928c387b..966f4184780 100644 --- a/app/assets/javascripts/notes/stores/mutations.js +++ b/app/assets/javascripts/notes/stores/mutations.js @@ -238,26 +238,36 @@ export default { }, [types.UPDATE_NOTE](state, note) { - const noteObj = utils.findNoteObjectById(state.discussions, note.discussion_id); + const discussion = utils.findNoteObjectById(state.discussions, note.discussion_id); // Disable eslint here so we can delete the property that we no longer need // in the note object // eslint-disable-next-line no-param-reassign delete note.base_discussion; - if (noteObj.individual_note) { + if (discussion.individual_note) { if (note.type === constants.DISCUSSION_NOTE) { - noteObj.individual_note = false; + discussion.individual_note = false; } - noteObj.notes.splice(0, 1, note); + discussion.notes.splice(0, 1, note); } else { - const comment = utils.findNoteObjectById(noteObj.notes, note.id); + const comment = utils.findNoteObjectById(discussion.notes, note.id); if (!isEqual(comment, note)) { - noteObj.notes.splice(noteObj.notes.indexOf(comment), 1, note); + discussion.notes.splice(discussion.notes.indexOf(comment), 1, note); } } + + if (note.resolvable && note.id === discussion.notes[0].id) { + Object.assign(discussion, { + resolvable: note.resolvable, + resolved: note.resolved, + resolved_at: note.resolved_at, + resolved_by: note.resolved_by, + resolved_by_push: note.resolved_by_push, + }); + } }, [types.APPLY_SUGGESTION](state, { noteId, discussionId, suggestionId }) { |