From 3e66795ef1ff1228906239763910b051d8afcc37 Mon Sep 17 00:00:00 2001 From: Felipe Artur Date: Thu, 21 Jun 2018 12:22:40 +0000 Subject: Changes tab VUE refactoring --- app/assets/javascripts/autosave.js | 4 +- app/assets/javascripts/awards_handler.js | 191 ++++++++++------ .../diff_notes/components/resolve_btn.js | 61 +++-- .../javascripts/diff_notes/diff_notes_bundle.js | 30 +-- .../javascripts/diff_notes/services/resolve.js | 40 ++-- app/assets/javascripts/diffs/components/app.vue | 197 ++++++++++++++++ .../javascripts/diffs/components/changed_files.vue | 184 +++++++++++++++ .../diffs/components/changed_files_dropdown.vue | 124 ++++++++++ .../diffs/components/compare_versions.vue | 55 +++++ .../diffs/components/compare_versions_dropdown.vue | 165 +++++++++++++ .../javascripts/diffs/components/diff_content.vue | 38 +++ .../diffs/components/diff_discussions.vue | 39 ++++ .../javascripts/diffs/components/diff_file.vue | 191 ++++++++++++++++ .../diffs/components/diff_file_header.vue | 254 +++++++++++++++++++++ .../diffs/components/diff_gutter_avatars.vue | 105 +++++++++ .../diffs/components/diff_line_gutter_content.vue | 203 ++++++++++++++++ .../diffs/components/diff_line_note_form.vue | 93 ++++++++ .../javascripts/diffs/components/edit_button.vue | 42 ++++ .../diffs/components/hidden_files_warning.vue | 51 +++++ .../diffs/components/inline_diff_view.vue | 117 ++++++++++ .../javascripts/diffs/components/no_changes.vue | 49 ++++ .../diffs/components/parallel_diff_view.vue | 224 ++++++++++++++++++ app/assets/javascripts/diffs/constants.js | 24 ++ app/assets/javascripts/diffs/index.js | 39 ++++ .../javascripts/diffs/mixins/changed_files.js | 38 +++ .../javascripts/diffs/mixins/diff_content.js | 89 ++++++++ app/assets/javascripts/diffs/store/actions.js | 99 ++++++++ app/assets/javascripts/diffs/store/getters.js | 16 ++ app/assets/javascripts/diffs/store/index.js | 11 + .../javascripts/diffs/store/modules/index.js | 25 ++ .../javascripts/diffs/store/mutation_types.js | 11 + app/assets/javascripts/diffs/store/mutations.js | 85 +++++++ app/assets/javascripts/diffs/store/utils.js | 172 ++++++++++++++ app/assets/javascripts/lib/utils/common_utils.js | 139 ++++++----- app/assets/javascripts/lib/utils/dom_utils.js | 7 +- app/assets/javascripts/lib/utils/text_utility.js | 21 ++ app/assets/javascripts/merge_request.js | 1 + app/assets/javascripts/merge_request_tabs.js | 11 +- app/assets/javascripts/mr_notes/index.js | 51 ++++- app/assets/javascripts/mr_notes/stores/actions.js | 7 + app/assets/javascripts/mr_notes/stores/getters.js | 5 + app/assets/javascripts/mr_notes/stores/index.js | 15 ++ .../javascripts/mr_notes/stores/modules/index.js | 12 + .../javascripts/mr_notes/stores/mutation_types.js | 3 + .../javascripts/mr_notes/stores/mutations.js | 7 + app/assets/javascripts/notes.js | 253 +++++--------------- .../javascripts/notes/components/comment_form.vue | 51 ++--- .../notes/components/diff_with_note.vue | 125 +++++++--- .../notes/components/discussion_counter.vue | 19 +- .../javascripts/notes/components/note_actions.vue | 20 +- .../javascripts/notes/components/note_body.vue | 9 +- .../notes/components/note_edited_text.vue | 13 +- .../javascripts/notes/components/note_form.vue | 53 ++--- .../javascripts/notes/components/note_header.vue | 11 +- .../notes/components/noteable_discussion.vue | 207 ++++++++++++----- .../javascripts/notes/components/noteable_note.vue | 51 +++-- .../javascripts/notes/components/notes_app.vue | 82 ++++--- app/assets/javascripts/notes/constants.js | 2 +- app/assets/javascripts/notes/index.js | 81 +++---- app/assets/javascripts/notes/mixins/autosave.js | 6 +- app/assets/javascripts/notes/mixins/noteable.js | 9 +- app/assets/javascripts/notes/mixins/resolvable.js | 36 ++- .../javascripts/notes/services/notes_service.js | 6 +- app/assets/javascripts/notes/stores/actions.js | 41 +++- app/assets/javascripts/notes/stores/getters.js | 71 ++++-- app/assets/javascripts/notes/stores/index.js | 26 +-- .../javascripts/notes/stores/modules/index.js | 26 +++ .../javascripts/notes/stores/mutation_types.js | 4 +- app/assets/javascripts/notes/stores/mutations.js | 96 ++++---- .../merge_requests/init_merge_request_show.js | 17 +- .../pages/projects/merge_requests/show/index.js | 6 +- app/assets/javascripts/shortcuts_issuable.js | 24 +- .../states/mr_widget_squash_before_merge.js | 15 ++ .../vue_shared/components/markdown/field.vue | 2 +- .../vue_shared/components/markdown/header.vue | 2 +- .../vue_shared/components/notes/skeleton_note.vue | 13 +- .../vue_shared/components/notes/system_note.vue | 141 ++++++++---- app/assets/stylesheets/framework/animations.scss | 9 + app/assets/stylesheets/framework/blocks.scss | 1 + app/assets/stylesheets/highlight/dark.scss | 4 +- app/assets/stylesheets/highlight/monokai.scss | 4 +- .../stylesheets/highlight/solarized_dark.scss | 4 +- .../stylesheets/highlight/solarized_light.scss | 4 +- app/assets/stylesheets/pages/diff.scss | 20 +- app/assets/stylesheets/pages/merge_requests.scss | 4 +- app/assets/stylesheets/pages/note_form.scss | 16 -- app/assets/stylesheets/pages/notes.scss | 62 ++++- app/controllers/concerns/issuable_actions.rb | 2 +- app/controllers/concerns/notes_actions.rb | 6 +- app/controllers/projects/blob_controller.rb | 44 +++- app/controllers/projects/discussions_controller.rb | 9 +- .../projects/merge_requests/diffs_controller.rb | 25 +- .../projects/merge_requests_controller.rb | 3 + app/finders/notes_finder.rb | 2 +- app/helpers/merge_requests_helper.rb | 2 + app/helpers/notes_helper.rb | 6 +- app/models/concerns/issuable.rb | 4 + app/models/discussion.rb | 4 + app/models/issue.rb | 4 + app/models/merge_request.rb | 4 + app/models/note.rb | 1 + app/serializers/blob_entity.rb | 4 +- app/serializers/diff_file_entity.rb | 123 +++++++++- app/serializers/diffs_entity.rb | 65 ++++++ app/serializers/diffs_serializer.rb | 3 + app/serializers/discussion_entity.rb | 49 ++-- app/serializers/merge_request_diff_entity.rb | 46 ++++ app/serializers/merge_request_user_entity.rb | 24 ++ app/serializers/merge_request_widget_entity.rb | 12 +- app/serializers/note_entity.rb | 28 ++- app/views/projects/issues/_discussion.html.haml | 3 +- app/views/projects/merge_requests/show.html.haml | 35 +-- app/views/shared/notes/_note.html.haml | 2 +- app/views/shared/notes/_notes_with_form.html.haml | 7 +- app/views/shared/runners/show.html.haml | 14 +- 115 files changed, 4513 insertions(+), 1009 deletions(-) create mode 100644 app/assets/javascripts/diffs/components/app.vue create mode 100644 app/assets/javascripts/diffs/components/changed_files.vue create mode 100644 app/assets/javascripts/diffs/components/changed_files_dropdown.vue create mode 100644 app/assets/javascripts/diffs/components/compare_versions.vue create mode 100644 app/assets/javascripts/diffs/components/compare_versions_dropdown.vue create mode 100644 app/assets/javascripts/diffs/components/diff_content.vue create mode 100644 app/assets/javascripts/diffs/components/diff_discussions.vue create mode 100644 app/assets/javascripts/diffs/components/diff_file.vue create mode 100644 app/assets/javascripts/diffs/components/diff_file_header.vue create mode 100644 app/assets/javascripts/diffs/components/diff_gutter_avatars.vue create mode 100644 app/assets/javascripts/diffs/components/diff_line_gutter_content.vue create mode 100644 app/assets/javascripts/diffs/components/diff_line_note_form.vue create mode 100644 app/assets/javascripts/diffs/components/edit_button.vue create mode 100644 app/assets/javascripts/diffs/components/hidden_files_warning.vue create mode 100644 app/assets/javascripts/diffs/components/inline_diff_view.vue create mode 100644 app/assets/javascripts/diffs/components/no_changes.vue create mode 100644 app/assets/javascripts/diffs/components/parallel_diff_view.vue create mode 100644 app/assets/javascripts/diffs/constants.js create mode 100644 app/assets/javascripts/diffs/index.js create mode 100644 app/assets/javascripts/diffs/mixins/changed_files.js create mode 100644 app/assets/javascripts/diffs/mixins/diff_content.js create mode 100644 app/assets/javascripts/diffs/store/actions.js create mode 100644 app/assets/javascripts/diffs/store/getters.js create mode 100644 app/assets/javascripts/diffs/store/index.js create mode 100644 app/assets/javascripts/diffs/store/modules/index.js create mode 100644 app/assets/javascripts/diffs/store/mutation_types.js create mode 100644 app/assets/javascripts/diffs/store/mutations.js create mode 100644 app/assets/javascripts/diffs/store/utils.js create mode 100644 app/assets/javascripts/mr_notes/stores/actions.js create mode 100644 app/assets/javascripts/mr_notes/stores/getters.js create mode 100644 app/assets/javascripts/mr_notes/stores/index.js create mode 100644 app/assets/javascripts/mr_notes/stores/modules/index.js create mode 100644 app/assets/javascripts/mr_notes/stores/mutation_types.js create mode 100644 app/assets/javascripts/mr_notes/stores/mutations.js create mode 100644 app/assets/javascripts/notes/stores/modules/index.js create mode 100644 app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_squash_before_merge.js create mode 100644 app/serializers/diffs_entity.rb create mode 100644 app/serializers/diffs_serializer.rb create mode 100644 app/serializers/merge_request_diff_entity.rb create mode 100644 app/serializers/merge_request_user_entity.rb (limited to 'app') diff --git a/app/assets/javascripts/autosave.js b/app/assets/javascripts/autosave.js index 959e6289502..fa00a3cf386 100644 --- a/app/assets/javascripts/autosave.js +++ b/app/assets/javascripts/autosave.js @@ -31,7 +31,9 @@ export default class Autosave { // https://github.com/vuejs/vue/issues/2804#issuecomment-216968137 const event = new Event('change', { bubbles: true, cancelable: false }); const field = this.field.get(0); - field.dispatchEvent(event); + if (field) { + field.dispatchEvent(event); + } } save() { diff --git a/app/assets/javascripts/awards_handler.js b/app/assets/javascripts/awards_handler.js index eb0f06efab4..70f20c5c7cf 100644 --- a/app/assets/javascripts/awards_handler.js +++ b/app/assets/javascripts/awards_handler.js @@ -11,7 +11,8 @@ import axios from './lib/utils/axios_utils'; const animationEndEventString = 'animationend webkitAnimationEnd MSAnimationEnd oAnimationEnd'; const transitionEndEventString = 'transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd'; -const requestAnimationFrame = window.requestAnimationFrame || +const requestAnimationFrame = + window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.setTimeout; @@ -37,21 +38,28 @@ class AwardsHandler { this.emoji = emoji; this.eventListeners = []; // If the user shows intent let's pre-build the menu - this.registerEventListener('one', $(document), 'mouseenter focus', '.js-add-award', 'mouseenter focus', () => { - const $menu = $('.emoji-menu'); - if ($menu.length === 0) { - requestAnimationFrame(() => { - this.createEmojiMenu(); - }); - } - }); - this.registerEventListener('on', $(document), 'click', '.js-add-award', (e) => { + this.registerEventListener( + 'one', + $(document), + 'mouseenter focus', + '.js-add-award', + 'mouseenter focus', + () => { + const $menu = $('.emoji-menu'); + if ($menu.length === 0) { + requestAnimationFrame(() => { + this.createEmojiMenu(); + }); + } + }, + ); + this.registerEventListener('on', $(document), 'click', '.js-add-award', e => { e.stopPropagation(); e.preventDefault(); this.showEmojiMenu($(e.currentTarget)); }); - this.registerEventListener('on', $('html'), 'click', (e) => { + this.registerEventListener('on', $('html'), 'click', e => { const $target = $(e.target); if (!$target.closest('.emoji-menu').length) { $('.js-awards-block.current').removeClass('current'); @@ -61,12 +69,14 @@ class AwardsHandler { } } }); - this.registerEventListener('on', $(document), 'click', '.js-emoji-btn', (e) => { + this.registerEventListener('on', $(document), 'click', '.js-emoji-btn', e => { e.preventDefault(); const $target = $(e.currentTarget); const $glEmojiElement = $target.find('gl-emoji'); const $spriteIconElement = $target.find('.icon'); - const emojiName = ($glEmojiElement.length ? $glEmojiElement : $spriteIconElement).data('name'); + const emojiName = ($glEmojiElement.length ? $glEmojiElement : $spriteIconElement).data( + 'name', + ); $target.closest('.js-awards-block').addClass('current'); this.addAward(this.getVotesBlock(), this.getAwardUrl(), emojiName); @@ -83,7 +93,10 @@ class AwardsHandler { showEmojiMenu($addBtn) { if ($addBtn.hasClass('js-note-emoji')) { - $addBtn.closest('.note').find('.js-awards-block').addClass('current'); + $addBtn + .closest('.note') + .find('.js-awards-block') + .addClass('current'); } else { $addBtn.closest('.js-awards-block').addClass('current'); } @@ -177,32 +190,38 @@ class AwardsHandler { const remainingCategories = Object.keys(categoryMap).slice(1); const allCategoriesAddedPromise = remainingCategories.reduce( (promiseChain, categoryNameKey) => - promiseChain.then(() => - new Promise((resolve) => { - const emojisInCategory = categoryMap[categoryNameKey]; - const categoryMarkup = this.renderCategory( - categoryLabelMap[categoryNameKey], - emojisInCategory, - ); - requestAnimationFrame(() => { - emojiContentElement.insertAdjacentHTML('beforeend', categoryMarkup); - resolve(); - }); - }), - ), + promiseChain.then( + () => + new Promise(resolve => { + const emojisInCategory = categoryMap[categoryNameKey]; + const categoryMarkup = this.renderCategory( + categoryLabelMap[categoryNameKey], + emojisInCategory, + ); + requestAnimationFrame(() => { + emojiContentElement.insertAdjacentHTML('beforeend', categoryMarkup); + resolve(); + }); + }), + ), Promise.resolve(), ); - allCategoriesAddedPromise.then(() => { - // Used for tests - // We check for the menu in case it was destroyed in the meantime - if (menu) { - menu.dispatchEvent(new CustomEvent('build-emoji-menu-finish')); - } - }).catch((err) => { - emojiContentElement.insertAdjacentHTML('beforeend', '

We encountered an error while adding the remaining categories

'); - throw new Error(`Error occurred in addRemainingEmojiMenuCategories: ${err.message}`); - }); + allCategoriesAddedPromise + .then(() => { + // Used for tests + // We check for the menu in case it was destroyed in the meantime + if (menu) { + menu.dispatchEvent(new CustomEvent('build-emoji-menu-finish')); + } + }) + .catch(err => { + emojiContentElement.insertAdjacentHTML( + 'beforeend', + '

We encountered an error while adding the remaining categories

', + ); + throw new Error(`Error occurred in addRemainingEmojiMenuCategories: ${err.message}`); + }); } renderCategory(name, emojiList, opts = {}) { @@ -211,7 +230,9 @@ class AwardsHandler { ${name} `; } @@ -232,7 +255,7 @@ class AwardsHandler { top: `${$addBtn.offset().top + $addBtn.outerHeight()}px`, }; if (position === 'right') { - css.left = `${($addBtn.offset().left - $menu.outerWidth()) + 20}px`; + css.left = `${$addBtn.offset().left - $menu.outerWidth() + 20}px`; $menu.addClass('is-aligned-right'); } else { css.left = `${$addBtn.offset().left}px`; @@ -416,7 +439,10 @@ class AwardsHandler { `; const $emojiButton = $(buttonHtml); - $emojiButton.insertBefore(votesBlock.find('.js-award-holder')).find('.emoji-icon').data('name', emojiName); + $emojiButton + .insertBefore(votesBlock.find('.js-award-holder')) + .find('.emoji-icon') + .data('name', emojiName); this.animateEmoji($emojiButton); $('.award-control').tooltip(); votesBlock.removeClass('current'); @@ -426,7 +452,7 @@ class AwardsHandler { const className = 'pulse animated once short'; $emoji.addClass(className); - this.registerEventListener('on', $emoji, animationEndEventString, (e) => { + this.registerEventListener('on', $emoji, animationEndEventString, e => { $(e.currentTarget).removeClass(className); }); } @@ -444,15 +470,16 @@ class AwardsHandler { if (this.isUserAuthored($emojiButton)) { this.userAuthored($emojiButton); } else { - axios.post(awardUrl, { - name: emoji, - }) - .then(({ data }) => { - if (data.ok) { - callback(); - } - }) - .catch(() => flash(__('Something went wrong on our end.'))); + axios + .post(awardUrl, { + name: emoji, + }) + .then(({ data }) => { + if (data.ok) { + callback(); + } + }) + .catch(() => flash(__('Something went wrong on our end.'))); } } @@ -486,26 +513,33 @@ class AwardsHandler { } getFrequentlyUsedEmojis() { - return this.frequentlyUsedEmojis || (() => { - const frequentlyUsedEmojis = _.uniq((Cookies.get('frequently_used_emojis') || '').split(',')); - this.frequentlyUsedEmojis = frequentlyUsedEmojis.filter( - inputName => this.emoji.isEmojiNameValid(inputName), - ); - - return this.frequentlyUsedEmojis; - })(); + return ( + this.frequentlyUsedEmojis || + (() => { + const frequentlyUsedEmojis = _.uniq( + (Cookies.get('frequently_used_emojis') || '').split(','), + ); + this.frequentlyUsedEmojis = frequentlyUsedEmojis.filter(inputName => + this.emoji.isEmojiNameValid(inputName), + ); + + return this.frequentlyUsedEmojis; + })() + ); } setupSearch() { const $search = $('.js-emoji-menu-search'); - this.registerEventListener('on', $search, 'input', (e) => { - const term = $(e.target).val().trim(); + this.registerEventListener('on', $search, 'input', e => { + const term = $(e.target) + .val() + .trim(); this.searchEmojis(term); }); const $menu = $('.emoji-menu'); - this.registerEventListener('on', $menu, transitionEndEventString, (e) => { + this.registerEventListener('on', $menu, transitionEndEventString, e => { if (e.target === e.currentTarget) { // Clear the search this.searchEmojis(''); @@ -523,19 +557,26 @@ class AwardsHandler { // Generate a search result block const h5 = $('
').text('Search results'); const foundEmojis = this.findMatchingEmojiElements(term).show(); - const ul = $('