From 5307d05c6dd70f537793872a9f056ac190754810 Mon Sep 17 00:00:00 2001 From: Tim Zallmann Date: Wed, 18 Jul 2018 11:49:13 +0000 Subject: Merge branch '_acet-fix-outdated-discussions' into 'master' Fix showing outdated discussions on Changes tab. Closes #48167 See merge request gitlab-org/gitlab-ce!20445 --- .../diffs/components/diff_line_gutter_content.vue | 3 +- .../diffs/components/inline_diff_comment_row.vue | 7 ++-- .../diffs/components/inline_diff_view.vue | 3 +- .../diffs/components/parallel_diff_comment_row.vue | 2 +- .../diffs/components/parallel_diff_view.vue | 3 +- app/assets/javascripts/diffs/store/getters.js | 40 ++++++++++++++++++++++ app/assets/javascripts/diffs/store/utils.js | 21 ++++++++++++ app/assets/javascripts/notes/stores/getters.js | 12 ------- app/serializers/discussion_entity.rb | 1 + .../unreleased/_acet-fix-outdated-discussions.yml | 5 +++ .../components/diff_line_gutter_content_spec.js | 2 ++ .../diffs/components/inline_diff_view_spec.js | 1 + .../diffs/mock_data/diff_discussions.js | 11 ++++++ spec/javascripts/diffs/store/getters_spec.js | 35 +++++++++++++++++++ spec/javascripts/diffs/store/utils_spec.js | 20 +++++++++++ 15 files changed, 146 insertions(+), 20 deletions(-) create mode 100644 changelogs/unreleased/_acet-fix-outdated-discussions.yml diff --git a/app/assets/javascripts/diffs/components/diff_line_gutter_content.vue b/app/assets/javascripts/diffs/components/diff_line_gutter_content.vue index ad838a32518..3b36bab206b 100644 --- a/app/assets/javascripts/diffs/components/diff_line_gutter_content.vue +++ b/app/assets/javascripts/diffs/components/diff_line_gutter_content.vue @@ -77,7 +77,8 @@ export default { diffViewType: state => state.diffs.diffViewType, diffFiles: state => state.diffs.diffFiles, }), - ...mapGetters(['isLoggedIn', 'discussionsByLineCode']), + ...mapGetters(['isLoggedIn']), + ...mapGetters('diffs', ['discussionsByLineCode']), lineHref() { return this.lineCode ? `#${this.lineCode}` : '#'; }, diff --git a/app/assets/javascripts/diffs/components/inline_diff_comment_row.vue b/app/assets/javascripts/diffs/components/inline_diff_comment_row.vue index ca265dd892c..a6f011ff31e 100644 --- a/app/assets/javascripts/diffs/components/inline_diff_comment_row.vue +++ b/app/assets/javascripts/diffs/components/inline_diff_comment_row.vue @@ -26,13 +26,16 @@ export default { ...mapState({ diffLineCommentForms: state => state.diffs.diffLineCommentForms, }), - ...mapGetters(['discussionsByLineCode']), + ...mapGetters('diffs', ['discussionsByLineCode']), discussions() { return this.discussionsByLineCode[this.line.lineCode] || []; }, className() { return this.discussions.length ? '' : 'js-temp-notes-holder'; }, + hasCommentForm() { + return this.diffLineCommentForms[this.line.lineCode]; + }, }, }; @@ -53,7 +56,7 @@ export default { :discussions="discussions" /> state.diffs.diffLineCommentForms, }), diff --git a/app/assets/javascripts/diffs/components/parallel_diff_comment_row.vue b/app/assets/javascripts/diffs/components/parallel_diff_comment_row.vue index cc5248c25d9..05e5cafc717 100644 --- a/app/assets/javascripts/diffs/components/parallel_diff_comment_row.vue +++ b/app/assets/javascripts/diffs/components/parallel_diff_comment_row.vue @@ -26,7 +26,7 @@ export default { ...mapState({ diffLineCommentForms: state => state.diffs.diffLineCommentForms, }), - ...mapGetters(['discussionsByLineCode']), + ...mapGetters('diffs', ['discussionsByLineCode']), leftLineCode() { return this.line.left.lineCode; }, diff --git a/app/assets/javascripts/diffs/components/parallel_diff_view.vue b/app/assets/javascripts/diffs/components/parallel_diff_view.vue index 32528c9e7ab..8f8d6bbc818 100644 --- a/app/assets/javascripts/diffs/components/parallel_diff_view.vue +++ b/app/assets/javascripts/diffs/components/parallel_diff_view.vue @@ -21,8 +21,7 @@ export default { }, }, computed: { - ...mapGetters('diffs', ['commitId']), - ...mapGetters(['discussionsByLineCode']), + ...mapGetters('diffs', ['commitId', 'discussionsByLineCode']), ...mapState({ diffLineCommentForms: state => state.diffs.diffLineCommentForms, }), diff --git a/app/assets/javascripts/diffs/store/getters.js b/app/assets/javascripts/diffs/store/getters.js index 855de79adf8..d3881fa1a0a 100644 --- a/app/assets/javascripts/diffs/store/getters.js +++ b/app/assets/javascripts/diffs/store/getters.js @@ -1,5 +1,7 @@ import _ from 'underscore'; +import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; import { PARALLEL_DIFF_VIEW_TYPE, INLINE_DIFF_VIEW_TYPE } from '../constants'; +import { getDiffRefsByLineCode } from './utils'; export const isParallelView = state => state.diffViewType === PARALLEL_DIFF_VIEW_TYPE; @@ -56,6 +58,44 @@ export const getDiffFileDiscussions = (state, getters, rootState, rootGetters) = discussion.diff_discussion && _.isEqual(discussion.diff_file.file_hash, diff.fileHash), ) || []; +/** + * Returns an Object with discussions by their diff line code + * To avoid rendering outdated discussions on the Changes tab we should do a bunch of SHA + * comparisions. `note.position.formatter` have the current version diff refs but + * `note.original_position.formatter` will have the first version's diff refs. + * If line diff refs matches with one of them, we should render it as a discussion on Changes tab. + * + * @param {Object} diff + * @returns {Array} + */ +export const discussionsByLineCode = (state, getters, rootState, rootGetters) => { + const diffRefsByLineCode = getDiffRefsByLineCode(state.diffFiles); + + return rootGetters.discussions.reduce((acc, note) => { + const isDiffDiscussion = note.diff_discussion; + const hasLineCode = note.line_code; + const isResolvable = note.resolvable; + const diffRefs = diffRefsByLineCode[note.line_code]; + + if (isDiffDiscussion && hasLineCode && isResolvable && diffRefs) { + const refs = convertObjectPropsToCamelCase(note.position.formatter); + const originalRefs = convertObjectPropsToCamelCase(note.original_position.formatter); + + if (_.isEqual(refs, diffRefs) || _.isEqual(originalRefs, diffRefs)) { + const lineCode = note.line_code; + + if (acc[lineCode]) { + acc[lineCode].push(note); + } else { + acc[lineCode] = [note]; + } + } + } + + return acc; + }, {}); +}; + // prevent babel-plugin-rewire from generating an invalid default during karma∂ tests export const getDiffFileByHash = state => fileHash => state.diffFiles.find(file => file.fileHash === fileHash); diff --git a/app/assets/javascripts/diffs/store/utils.js b/app/assets/javascripts/diffs/store/utils.js index d9589baa76e..82082ac508a 100644 --- a/app/assets/javascripts/diffs/store/utils.js +++ b/app/assets/javascripts/diffs/store/utils.js @@ -173,3 +173,24 @@ export function trimFirstCharOfLineContent(line = {}) { return parsedLine; } + +export function getDiffRefsByLineCode(diffFiles) { + return diffFiles.reduce((acc, diffFile) => { + const { baseSha, headSha, startSha } = diffFile.diffRefs; + const { newPath, oldPath } = diffFile; + + // We can only use highlightedDiffLines to create the map of diff lines because + // highlightedDiffLines will also include every parallel diff line in it. + if (diffFile.highlightedDiffLines) { + diffFile.highlightedDiffLines.forEach(line => { + const { lineCode, oldLine, newLine } = line; + + if (lineCode) { + acc[lineCode] = { baseSha, headSha, startSha, newPath, oldPath, oldLine, newLine }; + } + }); + } + + return acc; + }, {}); +} diff --git a/app/assets/javascripts/notes/stores/getters.js b/app/assets/javascripts/notes/stores/getters.js index 5c65e1c3bb5..e9e95dd4219 100644 --- a/app/assets/javascripts/notes/stores/getters.js +++ b/app/assets/javascripts/notes/stores/getters.js @@ -28,18 +28,6 @@ export const notesById = state => return acc; }, {}); -export const discussionsByLineCode = state => - state.discussions.reduce((acc, note) => { - if (note.diff_discussion && note.line_code && note.resolvable) { - // For context about line notes: there might be multiple notes with the same line code - const items = acc[note.line_code] || []; - items.push(note); - - Object.assign(acc, { [note.line_code]: items }); - } - return acc; - }, {}); - export const noteableType = state => { const { ISSUE_NOTEABLE_TYPE, MERGE_REQUEST_NOTEABLE_TYPE, EPIC_NOTEABLE_TYPE } = constants; diff --git a/app/serializers/discussion_entity.rb b/app/serializers/discussion_entity.rb index 8a39a4950f5..7505bbdeb3d 100644 --- a/app/serializers/discussion_entity.rb +++ b/app/serializers/discussion_entity.rb @@ -4,6 +4,7 @@ class DiscussionEntity < Grape::Entity expose :id, :reply_id expose :position, if: -> (d, _) { d.diff_discussion? && !d.legacy_diff_discussion? } + expose :original_position, if: -> (d, _) { d.diff_discussion? && !d.legacy_diff_discussion? } expose :line_code, if: -> (d, _) { d.diff_discussion? } expose :expanded?, as: :expanded expose :active?, as: :active, if: -> (d, _) { d.diff_discussion? } diff --git a/changelogs/unreleased/_acet-fix-outdated-discussions.yml b/changelogs/unreleased/_acet-fix-outdated-discussions.yml new file mode 100644 index 00000000000..d31483b4765 --- /dev/null +++ b/changelogs/unreleased/_acet-fix-outdated-discussions.yml @@ -0,0 +1,5 @@ +--- +title: Fix showing outdated discussions on Changes tab +merge_request: 20445 +author: +type: fixed diff --git a/spec/javascripts/diffs/components/diff_line_gutter_content_spec.js b/spec/javascripts/diffs/components/diff_line_gutter_content_spec.js index 2d136a63c52..cb85d12daf2 100644 --- a/spec/javascripts/diffs/components/diff_line_gutter_content_spec.js +++ b/spec/javascripts/diffs/components/diff_line_gutter_content_spec.js @@ -18,10 +18,12 @@ describe('DiffLineGutterContent', () => { }; const setDiscussions = component => { component.$store.dispatch('setInitialNotes', getDiscussionsMockData()); + component.$store.commit('diffs/SET_DIFF_DATA', { diffFiles: [getDiffFileMock()] }); }; const resetDiscussions = component => { component.$store.dispatch('setInitialNotes', []); + component.$store.commit('diffs/SET_DIFF_DATA', {}); }; describe('computed', () => { diff --git a/spec/javascripts/diffs/components/inline_diff_view_spec.js b/spec/javascripts/diffs/components/inline_diff_view_spec.js index b02328dd359..90dfa5c5a58 100644 --- a/spec/javascripts/diffs/components/inline_diff_view_spec.js +++ b/spec/javascripts/diffs/components/inline_diff_view_spec.js @@ -33,6 +33,7 @@ describe('InlineDiffView', () => { it('should render discussions', done => { const el = component.$el; component.$store.dispatch('setInitialNotes', getDiscussionsMockData()); + component.$store.commit('diffs/SET_DIFF_DATA', { diffFiles: [getDiffFileMock()] }); Vue.nextTick(() => { expect(el.querySelectorAll('.notes_holder').length).toEqual(1); diff --git a/spec/javascripts/diffs/mock_data/diff_discussions.js b/spec/javascripts/diffs/mock_data/diff_discussions.js index 41d0dfd8939..8cd57d2248b 100644 --- a/spec/javascripts/diffs/mock_data/diff_discussions.js +++ b/spec/javascripts/diffs/mock_data/diff_discussions.js @@ -12,6 +12,17 @@ export default { head_sha: 'c48ee0d1bf3b30453f5b32250ce03134beaa6d13', }, }, + original_position: { + formatter: { + old_line: null, + new_line: 2, + old_path: 'CHANGELOG', + new_path: 'CHANGELOG', + base_sha: 'e63f41fe459e62e1228fcef60d7189127aeba95a', + start_sha: 'd9eaefe5a676b820c57ff18cf5b68316025f7962', + head_sha: 'c48ee0d1bf3b30453f5b32250ce03134beaa6d13', + }, + }, line_code: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_1_2', expanded: true, notes: [ diff --git a/spec/javascripts/diffs/store/getters_spec.js b/spec/javascripts/diffs/store/getters_spec.js index 6210d4a7124..f5628a01a55 100644 --- a/spec/javascripts/diffs/store/getters_spec.js +++ b/spec/javascripts/diffs/store/getters_spec.js @@ -2,6 +2,7 @@ import * as getters from '~/diffs/store/getters'; import state from '~/diffs/store/modules/diff_state'; import { PARALLEL_DIFF_VIEW_TYPE, INLINE_DIFF_VIEW_TYPE } from '~/diffs/constants'; import discussion from '../mock_data/diff_discussions'; +import diffFile from '../mock_data/diff_file'; describe('Diffs Module Getters', () => { let localState; @@ -203,4 +204,38 @@ describe('Diffs Module Getters', () => { expect(getters.getDiffFileByHash(localState)('123')).toBeUndefined(); }); }); + + describe('discussionsByLineCode', () => { + let mockState; + + beforeEach(() => { + mockState = { diffFiles: [diffFile] }; + }); + + it('should return a map of diff lines with their line codes', () => { + const mockGetters = { discussions: [discussionMock] }; + + const map = getters.discussionsByLineCode(mockState, {}, {}, mockGetters); + expect(map['1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_1_2']).toBeDefined(); + expect(Object.keys(map).length).toEqual(1); + }); + + it('should have the diff discussion on the map if the original position matches', () => { + discussionMock.position.formatter.base_sha = 'ff9200'; + const mockGetters = { discussions: [discussionMock] }; + + const map = getters.discussionsByLineCode(mockState, {}, {}, mockGetters); + expect(map['1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_1_2']).toBeDefined(); + expect(Object.keys(map).length).toEqual(1); + }); + + it('should not add an outdated diff discussion to the returned map', () => { + discussionMock.position.formatter.base_sha = 'ff9200'; + discussionMock.original_position.formatter.base_sha = 'ff9200'; + const mockGetters = { discussions: [discussionMock] }; + + const map = getters.discussionsByLineCode(mockState, {}, {}, mockGetters); + expect(Object.keys(map).length).toEqual(0); + }); + }); }); diff --git a/spec/javascripts/diffs/store/utils_spec.js b/spec/javascripts/diffs/store/utils_spec.js index 32136d9ebff..8e7bd8afca4 100644 --- a/spec/javascripts/diffs/store/utils_spec.js +++ b/spec/javascripts/diffs/store/utils_spec.js @@ -207,4 +207,24 @@ describe('DiffsStoreUtils', () => { expect(utils.trimFirstCharOfLineContent()).toEqual({}); }); }); + + describe('getDiffRefsByLineCode', () => { + it('should return diffRefs for all highlightedDiffLines', () => { + const diffFile = getDiffFileMock(); + const map = utils.getDiffRefsByLineCode([diffFile]); + const { highlightedDiffLines } = diffFile; + const lineCodeCount = highlightedDiffLines.reduce( + (acc, line) => (line.lineCode ? acc + 1 : acc), + 0, + ); + + const { baseSha, headSha, startSha } = diffFile.diffRefs; + const targetLine = map[highlightedDiffLines[4].lineCode]; + + expect(Object.keys(map).length).toEqual(lineCodeCount); + expect(targetLine.baseSha).toEqual(baseSha); + expect(targetLine.headSha).toEqual(headSha); + expect(targetLine.startSha).toEqual(startSha); + }); + }); }); -- cgit v1.2.1 From 8d4f7f3982553f547633b0567a12ffcd9e5c2cb7 Mon Sep 17 00:00:00 2001 From: Tim Zallmann Date: Wed, 18 Jul 2018 16:08:09 +0000 Subject: Merge branch '_acet-fix-expanding-context-lines' into 'master' Fix rendering context lines on MR diffs Closes #49242 and #49343 See merge request gitlab-org/gitlab-ce!20642 --- app/assets/javascripts/diffs/components/diff_line_gutter_content.vue | 1 - app/assets/javascripts/diffs/components/inline_diff_table_row.vue | 1 - app/assets/javascripts/diffs/components/parallel_diff_table_row.vue | 2 -- changelogs/unreleased/_acet-fix-expanding-context-lines.yml | 5 +++++ 4 files changed, 5 insertions(+), 4 deletions(-) create mode 100644 changelogs/unreleased/_acet-fix-expanding-context-lines.yml diff --git a/app/assets/javascripts/diffs/components/diff_line_gutter_content.vue b/app/assets/javascripts/diffs/components/diff_line_gutter_content.vue index 3b36bab206b..0fe0007057b 100644 --- a/app/assets/javascripts/diffs/components/diff_line_gutter_content.vue +++ b/app/assets/javascripts/diffs/components/diff_line_gutter_content.vue @@ -190,7 +190,6 @@ export default { diff --git a/app/assets/javascripts/diffs/components/inline_diff_table_row.vue b/app/assets/javascripts/diffs/components/inline_diff_table_row.vue index 0197a510ef1..0e306f39a9f 100644 --- a/app/assets/javascripts/diffs/components/inline_diff_table_row.vue +++ b/app/assets/javascripts/diffs/components/inline_diff_table_row.vue @@ -101,7 +101,6 @@ export default { class="diff-line-num new_line" /> Date: Wed, 18 Jul 2018 15:12:31 +0000 Subject: Merge branch '_acet-fix-mr-autosave' into 'master' Fix autosave issues for MR discussions Closes #48876 and #48877 See merge request gitlab-org/gitlab-ce!20569 --- app/assets/javascripts/autosave.js | 4 +++ .../diffs/components/diff_line_note_form.vue | 31 +++++++++------- .../javascripts/notes/components/note_form.vue | 2 +- .../notes/components/noteable_discussion.vue | 34 +++++++++--------- app/assets/javascripts/notes/mixins/autosave.js | 17 ++++++--- changelogs/unreleased/_acet-fix-mr-autosave.yml | 5 +++ locale/gitlab.pot | 3 ++ spec/javascripts/autosave_spec.js | 10 ++---- .../diffs/components/diff_line_note_form_spec.js | 41 +++++++++++++++++----- .../notes/components/noteable_discussion_spec.js | 9 +++-- 10 files changed, 106 insertions(+), 50 deletions(-) create mode 100644 changelogs/unreleased/_acet-fix-mr-autosave.yml diff --git a/app/assets/javascripts/autosave.js b/app/assets/javascripts/autosave.js index fa00a3cf386..e8c59fab609 100644 --- a/app/assets/javascripts/autosave.js +++ b/app/assets/javascripts/autosave.js @@ -53,4 +53,8 @@ export default class Autosave { return window.localStorage.removeItem(this.key); } + + dispose() { + this.field.off('input'); + } } diff --git a/app/assets/javascripts/diffs/components/diff_line_note_form.vue b/app/assets/javascripts/diffs/components/diff_line_note_form.vue index 32f9516d332..cbe4551d06b 100644 --- a/app/assets/javascripts/diffs/components/diff_line_note_form.vue +++ b/app/assets/javascripts/diffs/components/diff_line_note_form.vue @@ -1,17 +1,17 @@ @@ -64,13 +57,15 @@ export default { :line="line" :is-bottom="index + 1 === diffLinesLength" :key="line.lineCode" + :discussions="singleDiscussionByLineCode(line.lineCode)" /> diff --git a/app/assets/javascripts/diffs/components/parallel_diff_comment_row.vue b/app/assets/javascripts/diffs/components/parallel_diff_comment_row.vue index 05e5cafc717..bb9a65c83fa 100644 --- a/app/assets/javascripts/diffs/components/parallel_diff_comment_row.vue +++ b/app/assets/javascripts/diffs/components/parallel_diff_comment_row.vue @@ -1,5 +1,5 @@ @@ -97,13 +75,17 @@ export default { :line="line" :is-bottom="index + 1 === diffLinesLength" :key="index" + :left-discussions="singleDiscussionByLineCode(line.left.lineCode)" + :right-discussions="singleDiscussionByLineCode(line.right.lineCode)" /> diff --git a/app/assets/javascripts/diffs/store/getters.js b/app/assets/javascripts/diffs/store/getters.js index d3881fa1a0a..c7b9b1a16e6 100644 --- a/app/assets/javascripts/diffs/store/getters.js +++ b/app/assets/javascripts/diffs/store/getters.js @@ -75,19 +75,21 @@ export const discussionsByLineCode = (state, getters, rootState, rootGetters) => const isDiffDiscussion = note.diff_discussion; const hasLineCode = note.line_code; const isResolvable = note.resolvable; - const diffRefs = diffRefsByLineCode[note.line_code]; - if (isDiffDiscussion && hasLineCode && isResolvable && diffRefs) { - const refs = convertObjectPropsToCamelCase(note.position.formatter); - const originalRefs = convertObjectPropsToCamelCase(note.original_position.formatter); + if (isDiffDiscussion && hasLineCode && isResolvable) { + const diffRefs = diffRefsByLineCode[note.line_code]; + if (diffRefs) { + const refs = convertObjectPropsToCamelCase(note.position.formatter); + const originalRefs = convertObjectPropsToCamelCase(note.original_position.formatter); - if (_.isEqual(refs, diffRefs) || _.isEqual(originalRefs, diffRefs)) { - const lineCode = note.line_code; + if (_.isEqual(refs, diffRefs) || _.isEqual(originalRefs, diffRefs)) { + const lineCode = note.line_code; - if (acc[lineCode]) { - acc[lineCode].push(note); - } else { - acc[lineCode] = [note]; + if (acc[lineCode]) { + acc[lineCode].push(note); + } else { + acc[lineCode] = [note]; + } } } } @@ -96,6 +98,47 @@ export const discussionsByLineCode = (state, getters, rootState, rootGetters) => }, {}); }; +export const singleDiscussionByLineCode = (state, getters) => lineCode => { + if (!lineCode) return []; + const discussions = getters.discussionsByLineCode; + return discussions[lineCode] || []; +}; + +export const shouldRenderParallelCommentRow = (state, getters) => line => { + const leftLineCode = line.left.lineCode; + const rightLineCode = line.right.lineCode; + const leftDiscussions = getters.singleDiscussionByLineCode(leftLineCode); + const rightDiscussions = getters.singleDiscussionByLineCode(rightLineCode); + const hasDiscussion = leftDiscussions.length || rightDiscussions.length; + + const hasExpandedDiscussionOnLeft = leftDiscussions.length + ? leftDiscussions.every(discussion => discussion.expanded) + : false; + const hasExpandedDiscussionOnRight = rightDiscussions.length + ? rightDiscussions.every(discussion => discussion.expanded) + : false; + + if (hasDiscussion && (hasExpandedDiscussionOnLeft || hasExpandedDiscussionOnRight)) { + return true; + } + + const hasCommentFormOnLeft = state.diffLineCommentForms[leftLineCode]; + const hasCommentFormOnRight = state.diffLineCommentForms[rightLineCode]; + + return hasCommentFormOnLeft || hasCommentFormOnRight; +}; + +export const shouldRenderInlineCommentRow = (state, getters) => line => { + if (state.diffLineCommentForms[line.lineCode]) return true; + + const lineDiscussions = getters.singleDiscussionByLineCode(line.lineCode); + if (lineDiscussions.length === 0) { + return false; + } + + return lineDiscussions.every(discussion => discussion.expanded); +}; + // prevent babel-plugin-rewire from generating an invalid default during karma∂ tests export const getDiffFileByHash = state => fileHash => state.diffFiles.find(file => file.fileHash === fileHash); diff --git a/changelogs/unreleased/tz-mr-refactor-memory-reduction.yml b/changelogs/unreleased/tz-mr-refactor-memory-reduction.yml new file mode 100644 index 00000000000..20b72c98bc1 --- /dev/null +++ b/changelogs/unreleased/tz-mr-refactor-memory-reduction.yml @@ -0,0 +1,5 @@ +--- +title: Reduces the client side memory footprint on merge requests +merge_request: 20744 +author: +type: performance diff --git a/spec/javascripts/diffs/components/diff_line_gutter_content_spec.js b/spec/javascripts/diffs/components/diff_line_gutter_content_spec.js index cb85d12daf2..bdc94131fc2 100644 --- a/spec/javascripts/diffs/components/diff_line_gutter_content_spec.js +++ b/spec/javascripts/diffs/components/diff_line_gutter_content_spec.js @@ -50,7 +50,11 @@ describe('DiffLineGutterContent', () => { it('should return discussions for the given lineCode', () => { const { lineCode } = getDiffFileMock().highlightedDiffLines[1]; - const component = createComponent({ lineCode, showCommentButton: true }); + const component = createComponent({ + lineCode, + showCommentButton: true, + discussions: getDiscussionsMockData(), + }); setDiscussions(component); -- cgit v1.2.1 From d1f09ec7cdab3b6892b1006b8c382c08be4cd9e0 Mon Sep 17 00:00:00 2001 From: Fatih Acet Date: Mon, 23 Jul 2018 18:42:36 +0000 Subject: Merge branch 'tz-mr-refactor-mem-posting' into 'master' Improving performance of posting a comment by reducing memory + CPU See merge request gitlab-org/gitlab-ce!20779 --- app/assets/javascripts/lib/utils/poll.js | 11 ++++++----- app/assets/javascripts/notes/stores/mutations.js | 19 ++++--------------- app/assets/javascripts/notes/stores/utils.js | 9 +++------ .../unreleased/tz-mr-refactor-memory-reduction.yml | 10 +++++----- 4 files changed, 18 insertions(+), 31 deletions(-) diff --git a/app/assets/javascripts/lib/utils/poll.js b/app/assets/javascripts/lib/utils/poll.js index 7fca80c2fdb..91d8c30744f 100644 --- a/app/assets/javascripts/lib/utils/poll.js +++ b/app/assets/javascripts/lib/utils/poll.js @@ -38,7 +38,7 @@ import { normalizeHeaders } from './common_utils'; * } else { * poll.stop(); * } -* }); + * }); * * 1. Checks for response and headers before start polling * 2. Interval is provided by `Poll-Interval` header. @@ -51,8 +51,8 @@ export default class Poll { constructor(options = {}) { this.options = options; this.options.data = options.data || {}; - this.options.notificationCallback = options.notificationCallback || - function notificationCallback() {}; + this.options.notificationCallback = + options.notificationCallback || function notificationCallback() {}; this.intervalHeader = 'POLL-INTERVAL'; this.timeoutID = null; @@ -63,6 +63,7 @@ export default class Poll { const headers = normalizeHeaders(response.headers); const pollInterval = parseInt(headers[this.intervalHeader], 10); if (pollInterval > 0 && response.status === httpStatusCodes.OK && this.canPoll) { + clearTimeout(this.timeoutID); this.timeoutID = setTimeout(() => { this.makeRequest(); }, pollInterval); @@ -77,11 +78,11 @@ export default class Poll { notificationCallback(true); return resource[method](data) - .then((response) => { + .then(response => { this.checkConditions(response); notificationCallback(false); }) - .catch((error) => { + .catch(error => { notificationCallback(false); if (error.status === httpStatusCodes.ABORTED) { return; diff --git a/app/assets/javascripts/notes/stores/mutations.js b/app/assets/javascripts/notes/stores/mutations.js index ab6a95e2601..e1b159142c9 100644 --- a/app/assets/javascripts/notes/stores/mutations.js +++ b/app/assets/javascripts/notes/stores/mutations.js @@ -174,27 +174,19 @@ export default { [types.UPDATE_NOTE](state, note) { const noteObj = utils.findNoteObjectById(state.discussions, note.discussion_id); - if (noteObj.individual_note) { noteObj.notes.splice(0, 1, note); } else { const comment = utils.findNoteObjectById(noteObj.notes, note.id); - noteObj.notes.splice(noteObj.notes.indexOf(comment), 1, note); + Object.assign(comment, note); } }, [types.UPDATE_DISCUSSION](state, noteData) { const note = noteData; - let index = 0; - - state.discussions.forEach((n, i) => { - if (n.id === note.id) { - index = i; - } - }); - + const selectedDiscussion = state.discussions.find(n => n.id === note.id); note.expanded = true; // override expand flag to prevent collapse - state.discussions.splice(index, 1, note); + Object.assign(selectedDiscussion, note); }, [types.CLOSE_ISSUE](state) { @@ -215,12 +207,9 @@ export default { [types.SET_DISCUSSION_DIFF_LINES](state, { discussionId, diffLines }) { const discussion = utils.findNoteObjectById(state.discussions, discussionId); - const index = state.discussions.indexOf(discussion); - const discussionWithDiffLines = Object.assign({}, discussion, { + Object.assign(discussion, { truncated_diff_lines: diffLines, }); - - state.discussions.splice(index, 1, discussionWithDiffLines); }, }; diff --git a/app/assets/javascripts/notes/stores/utils.js b/app/assets/javascripts/notes/stores/utils.js index a0e096ebfaf..c4a812c5af4 100644 --- a/app/assets/javascripts/notes/stores/utils.js +++ b/app/assets/javascripts/notes/stores/utils.js @@ -2,13 +2,11 @@ import AjaxCache from '~/lib/utils/ajax_cache'; const REGEX_QUICK_ACTIONS = /^\/\w+.*$/gm; -export const findNoteObjectById = (notes, id) => - notes.filter(n => n.id === id)[0]; +export const findNoteObjectById = (notes, id) => notes.find(n => n.id === id); export const getQuickActionText = note => { let text = 'Applying command'; - const quickActions = - AjaxCache.get(gl.GfmAutoComplete.dataSources.commands) || []; + const quickActions = AjaxCache.get(gl.GfmAutoComplete.dataSources.commands) || []; const executedCommands = quickActions.filter(command => { const commandRegex = new RegExp(`/${command.name}`); @@ -29,5 +27,4 @@ export const getQuickActionText = note => { export const hasQuickActions = note => REGEX_QUICK_ACTIONS.test(note); -export const stripQuickActions = note => - note.replace(REGEX_QUICK_ACTIONS, '').trim(); +export const stripQuickActions = note => note.replace(REGEX_QUICK_ACTIONS, '').trim(); diff --git a/changelogs/unreleased/tz-mr-refactor-memory-reduction.yml b/changelogs/unreleased/tz-mr-refactor-memory-reduction.yml index 20b72c98bc1..16003fa9cad 100644 --- a/changelogs/unreleased/tz-mr-refactor-memory-reduction.yml +++ b/changelogs/unreleased/tz-mr-refactor-memory-reduction.yml @@ -1,5 +1,5 @@ ---- -title: Reduces the client side memory footprint on merge requests -merge_request: 20744 -author: -type: performance +--- +title: Reduces the client side memory footprint on merge requests +merge_request: 20744 +author: +type: performance -- cgit v1.2.1