diff options
author | Phil Hughes <me@iamphill.com> | 2019-04-05 10:39:40 +0300 |
---|---|---|
committer | Phil Hughes <me@iamphill.com> | 2019-04-05 10:39:40 +0300 |
commit | 36d1d9082cc0d12ebce52050730ae50a0cc51d1a (patch) | |
tree | b8b600b07b258609c892869532250218c076f144 | |
parent | 5402c918d5a202ed381e0b95d528fa43f644c047 (diff) | |
parent | c1a097e1cee43b127de17d769546ffa244cbf484 (diff) |
Merge branch '60021-fix-ide-file-dropdown' into 'master'
Fix IDE file dropdown
Closes #60021
See merge request gitlab-org/gitlab-ce!27015
6 files changed, 79 insertions, 27 deletions
diff --git a/app/assets/javascripts/ide/components/file_row_extra.vue b/app/assets/javascripts/ide/components/file_row_extra.vue index d6673cf0421..80a6ab9598a 100644 --- a/app/assets/javascripts/ide/components/file_row_extra.vue +++ b/app/assets/javascripts/ide/components/file_row_extra.vue @@ -23,7 +23,7 @@ export default { type: Object, required: true, }, - mouseOver: { + dropdownOpen: { type: Boolean, required: true, }, @@ -92,8 +92,9 @@ export default { <new-dropdown :type="file.type" :path="file.path" - :mouse-over="mouseOver" + :is-open="dropdownOpen" class="prepend-left-8" + v-on="$listeners" /> </div> </template> diff --git a/app/assets/javascripts/ide/components/new_dropdown/index.vue b/app/assets/javascripts/ide/components/new_dropdown/index.vue index 593a9162a06..27d24fa5e1d 100644 --- a/app/assets/javascripts/ide/components/new_dropdown/index.vue +++ b/app/assets/javascripts/ide/components/new_dropdown/index.vue @@ -21,38 +21,29 @@ export default { required: false, default: '', }, - mouseOver: { + isOpen: { type: Boolean, - required: true, + required: false, + default: false, }, }, - data() { - return { - dropdownOpen: false, - }; - }, watch: { - dropdownOpen() { + isOpen() { this.$nextTick(() => { this.$refs.dropdownMenu.scrollIntoView({ block: 'nearest', }); }); }, - mouseOver() { - if (!this.mouseOver) { - this.dropdownOpen = false; - } - }, }, methods: { ...mapActions(['createTempEntry', 'openNewEntryModal', 'deleteEntry']), createNewItem(type) { this.openNewEntryModal({ type, path: this.path }); - this.dropdownOpen = false; + this.$emit('toggle', false); }, openDropdown() { - this.dropdownOpen = !this.dropdownOpen; + this.$emit('toggle', !this.isOpen); }, }, modalTypes, @@ -63,7 +54,7 @@ export default { <div class="ide-new-btn"> <div :class="{ - show: dropdownOpen, + show: isOpen, }" class="dropdown d-flex" > diff --git a/app/assets/javascripts/vue_shared/components/file_row.vue b/app/assets/javascripts/vue_shared/components/file_row.vue index 0cbcdbf2eb4..1bfa91500cb 100644 --- a/app/assets/javascripts/vue_shared/components/file_row.vue +++ b/app/assets/javascripts/vue_shared/components/file_row.vue @@ -39,7 +39,7 @@ export default { }, data() { return { - mouseOver: false, + dropdownOpen: false, }; }, computed: { @@ -123,8 +123,8 @@ export default { return this.$router.currentRoute.path === `/project${this.file.url}`; }, - toggleHover(over) { - this.mouseOver = over; + toggleDropdown(val) { + this.dropdownOpen = val; }, }, }; @@ -140,8 +140,7 @@ export default { class="file-row" role="button" @click="clickFile" - @mouseover="toggleHover(true)" - @mouseout="toggleHover(false)" + @mouseleave="toggleDropdown(false)" > <div class="file-row-name-container"> <span ref="textOutput" :style="levelIndentation" class="file-row-name str-truncated"> @@ -160,7 +159,8 @@ export default { :is="extraComponent" v-if="extraComponent && !(hideExtraOnTree && file.type === 'tree')" :file="file" - :mouse-over="mouseOver" + :dropdown-open="dropdownOpen" + @toggle="toggleDropdown($event)" /> </div> </div> diff --git a/spec/javascripts/ide/components/file_row_extra_spec.js b/spec/javascripts/ide/components/file_row_extra_spec.js index c93a939ad71..d7fed3f0681 100644 --- a/spec/javascripts/ide/components/file_row_extra_spec.js +++ b/spec/javascripts/ide/components/file_row_extra_spec.js @@ -20,7 +20,7 @@ describe('IDE extra file row component', () => { file: { ...file('test'), }, - mouseOver: false, + dropdownOpen: false, }); spyOnProperty(vm, 'getUnstagedFilesCountForPath').and.returnValue(() => unstagedFilesCount); diff --git a/spec/javascripts/ide/components/new_dropdown/index_spec.js b/spec/javascripts/ide/components/new_dropdown/index_spec.js index 83e530f0a6a..aaebe88f314 100644 --- a/spec/javascripts/ide/components/new_dropdown/index_spec.js +++ b/spec/javascripts/ide/components/new_dropdown/index_spec.js @@ -56,11 +56,11 @@ describe('new dropdown component', () => { }); }); - describe('dropdownOpen', () => { + describe('isOpen', () => { it('scrolls dropdown into view', done => { spyOn(vm.$refs.dropdownMenu, 'scrollIntoView'); - vm.dropdownOpen = true; + vm.isOpen = true; setTimeout(() => { expect(vm.$refs.dropdownMenu.scrollIntoView).toHaveBeenCalledWith({ diff --git a/spec/javascripts/vue_shared/components/file_row_spec.js b/spec/javascripts/vue_shared/components/file_row_spec.js index d1fd899c1a8..7da69e3fa84 100644 --- a/spec/javascripts/vue_shared/components/file_row_spec.js +++ b/spec/javascripts/vue_shared/components/file_row_spec.js @@ -1,5 +1,6 @@ import Vue from 'vue'; import FileRow from '~/vue_shared/components/file_row.vue'; +import FileRowExtra from '~/ide/components/file_row_extra.vue'; import { file } from 'spec/ide/helpers'; import mountComponent from '../../helpers/vue_mount_component_helper'; @@ -16,6 +17,10 @@ describe('File row component', () => { vm.$destroy(); }); + const findNewDropdown = () => vm.$el.querySelector('.ide-new-btn .dropdown'); + const findNewDropdownButton = () => vm.$el.querySelector('.ide-new-btn .dropdown button'); + const findFileRow = () => vm.$el.querySelector('.file-row'); + it('renders name', () => { createComponent({ file: file('t4'), @@ -84,4 +89,59 @@ describe('File row component', () => { expect(vm.$el.querySelector('.js-file-row-header')).not.toBe(null); }); + + describe('new dropdown', () => { + beforeEach(() => { + createComponent({ + file: file('t5'), + level: 1, + extraComponent: FileRowExtra, + }); + }); + + it('renders in extra component', () => { + expect(findNewDropdown()).not.toBe(null); + }); + + it('is hidden at start', () => { + expect(findNewDropdown()).not.toHaveClass('show'); + }); + + it('is opened when button is clicked', done => { + expect(vm.dropdownOpen).toBe(false); + findNewDropdownButton().dispatchEvent(new Event('click')); + + vm.$nextTick() + .then(() => { + expect(vm.dropdownOpen).toBe(true); + expect(findNewDropdown()).toHaveClass('show'); + }) + .then(done) + .catch(done.fail); + }); + + describe('when opened', () => { + beforeEach(() => { + vm.dropdownOpen = true; + }); + + it('stays open when button triggers mouseout', () => { + findNewDropdownButton().dispatchEvent(new Event('mouseout')); + + expect(vm.dropdownOpen).toBe(true); + }); + + it('stays open when button triggers mouseleave', () => { + findNewDropdownButton().dispatchEvent(new Event('mouseleave')); + + expect(vm.dropdownOpen).toBe(true); + }); + + it('closes when row triggers mouseleave', () => { + findFileRow().dispatchEvent(new Event('mouseleave')); + + expect(vm.dropdownOpen).toBe(false); + }); + }); + }); }); |