summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/assets/javascripts/ide/components/file_finder/index.vue22
-rw-r--r--app/assets/javascripts/ide/components/file_finder/item.vue8
-rw-r--r--app/assets/javascripts/ide/stores/mutation_types.js2
-rw-r--r--changelogs/unreleased/ide-file-finder.yml5
-rw-r--r--spec/javascripts/ide/components/file_finder/index_spec.js44
-rw-r--r--spec/javascripts/ide/stores/actions_spec.js19
-rw-r--r--spec/javascripts/ide/stores/mutations_spec.js8
7 files changed, 101 insertions, 7 deletions
diff --git a/app/assets/javascripts/ide/components/file_finder/index.vue b/app/assets/javascripts/ide/components/file_finder/index.vue
index 5049588e0a4..864c9234979 100644
--- a/app/assets/javascripts/ide/components/file_finder/index.vue
+++ b/app/assets/javascripts/ide/components/file_finder/index.vue
@@ -42,6 +42,9 @@ export default {
listHeight() {
return this.filteredBlobsLength ? 55 : 33;
},
+ showClearInputButton() {
+ return this.searchText.trim() !== '';
+ },
},
watch: {
fileFindVisible() {
@@ -61,6 +64,13 @@ export default {
},
methods: {
...mapActions(['toggleFileFinder']),
+ clearSearchInput() {
+ this.searchText = '';
+
+ this.$nextTick(() => {
+ this.$refs.searchInput.focus();
+ });
+ },
onKeydown(e) {
switch (e.keyCode) {
case 38:
@@ -129,6 +139,18 @@ export default {
<i
aria-hidden="true"
class="fa fa-search dropdown-input-search"
+ :class="{
+ hidden: showClearInputButton
+ }"
+ ></i>
+ <i
+ role="button"
+ aria-hidden="true"
+ class="fa fa-times dropdown-input-clear"
+ :class="{
+ show: showClearInputButton
+ }"
+ @click="clearSearchInput"
></i>
</div>
<div>
diff --git a/app/assets/javascripts/ide/components/file_finder/item.vue b/app/assets/javascripts/ide/components/file_finder/item.vue
index 2f72d6799b6..af4d07ef543 100644
--- a/app/assets/javascripts/ide/components/file_finder/item.vue
+++ b/app/assets/javascripts/ide/components/file_finder/item.vue
@@ -1,4 +1,5 @@
<script>
+import { escape } from 'underscore';
import fuzzaldrinPlus from 'fuzzaldrin-plus';
import FileIcon from '../../../vue_shared/components/file_icon.vue';
import ChangedFileIcon from '../changed_file_icon.vue';
@@ -29,10 +30,11 @@ export default {
this.$emit('click', this.file);
},
highlightText(text, addEllipsis) {
+ const escapedText = escape(text);
const maxText =
- text.length < MAX_PATH_LENGTH || !addEllipsis
- ? text
- : `...${text.substr(text.length - MAX_PATH_LENGTH)}`;
+ escapedText.length < MAX_PATH_LENGTH || !addEllipsis
+ ? escapedText
+ : `...${escapedText.substr(escapedText.length - MAX_PATH_LENGTH)}`;
const occurrences = fuzzaldrinPlus.match(maxText, this.searchText);
return maxText
diff --git a/app/assets/javascripts/ide/stores/mutation_types.js b/app/assets/javascripts/ide/stores/mutation_types.js
index d64908ea971..742bd40f25d 100644
--- a/app/assets/javascripts/ide/stores/mutation_types.js
+++ b/app/assets/javascripts/ide/stores/mutation_types.js
@@ -54,4 +54,4 @@ export const UPDATE_DELAY_VIEWER_CHANGE = 'UPDATE_DELAY_VIEWER_CHANGE';
export const ADD_PENDING_TAB = 'ADD_PENDING_TAB';
export const REMOVE_PENDING_TAB = 'REMOVE_PENDING_TAB';
-export const TOGGLE_FILE_FINDER = 'SHOW_FILE_FINDER';
+export const TOGGLE_FILE_FINDER = 'TOGGLE_FILE_FINDER';
diff --git a/changelogs/unreleased/ide-file-finder.yml b/changelogs/unreleased/ide-file-finder.yml
new file mode 100644
index 00000000000..252dd3a30c4
--- /dev/null
+++ b/changelogs/unreleased/ide-file-finder.yml
@@ -0,0 +1,5 @@
+---
+title: Added fuzzy file finder to web IDE
+merge_request:
+author:
+type: added
diff --git a/spec/javascripts/ide/components/file_finder/index_spec.js b/spec/javascripts/ide/components/file_finder/index_spec.js
index 1181a886749..6dbe7b84d4e 100644
--- a/spec/javascripts/ide/components/file_finder/index_spec.js
+++ b/spec/javascripts/ide/components/file_finder/index_spec.js
@@ -67,6 +67,50 @@ describe('IDE File finder item spec', () => {
});
});
+ it('shows clear button when searchText is not empty', done => {
+ vm.searchText = 'index';
+
+ vm.$nextTick(() => {
+ expect(vm.$el.querySelector('.dropdown-input-clear').classList).toContain('show');
+ expect(vm.$el.querySelector('.dropdown-input-search').classList).toContain('hidden');
+
+ done();
+ });
+ });
+
+ it('clear button resets searchText', done => {
+ vm.searchText = 'index';
+
+ vm
+ .$nextTick()
+ .then(() => {
+ vm.$el.querySelector('.dropdown-input-clear').click();
+ })
+ .then(vm.$nextTick)
+ .then(() => {
+ expect(vm.searchText).toBe('');
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('clear button focues search input', done => {
+ spyOn(vm.$refs.searchInput, 'focus');
+ vm.searchText = 'index';
+
+ vm
+ .$nextTick()
+ .then(() => {
+ vm.$el.querySelector('.dropdown-input-clear').click();
+ })
+ .then(vm.$nextTick)
+ .then(() => {
+ expect(vm.$refs.searchInput.focus).toHaveBeenCalled();
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+
describe('listShowCount', () => {
it('returns 1 when no filtered entries exist', done => {
vm.searchText = 'testing 123';
diff --git a/spec/javascripts/ide/stores/actions_spec.js b/spec/javascripts/ide/stores/actions_spec.js
index cec572f4507..87471f7a92f 100644
--- a/spec/javascripts/ide/stores/actions_spec.js
+++ b/spec/javascripts/ide/stores/actions_spec.js
@@ -1,7 +1,9 @@
import * as urlUtils from '~/lib/utils/url_utility';
import store from '~/ide/stores';
+import * as actions from '~/ide/stores/actions';
import router from '~/ide/ide_router';
import { resetStore, file } from '../helpers';
+import testAction from '../../helpers/vuex_action_helper';
describe('Multi-file store actions', () => {
beforeEach(() => {
@@ -191,9 +193,7 @@ describe('Multi-file store actions', () => {
})
.then(f => {
expect(f.tempFile).toBeTruthy();
- expect(store.state.trees['abcproject/mybranch'].tree.length).toBe(
- 1,
- );
+ expect(store.state.trees['abcproject/mybranch'].tree.length).toBe(1);
done();
})
@@ -303,4 +303,17 @@ describe('Multi-file store actions', () => {
.catch(done.fail);
});
});
+
+ describe('toggleFileFinder', () => {
+ it('commits TOGGLE_FILE_FINDER', done => {
+ testAction(
+ actions.toggleFileFinder,
+ true,
+ null,
+ [{ type: 'TOGGLE_FILE_FINDER', payload: true }],
+ [],
+ done,
+ );
+ });
+ });
});
diff --git a/spec/javascripts/ide/stores/mutations_spec.js b/spec/javascripts/ide/stores/mutations_spec.js
index 38162a470ad..9edfc080bec 100644
--- a/spec/javascripts/ide/stores/mutations_spec.js
+++ b/spec/javascripts/ide/stores/mutations_spec.js
@@ -76,4 +76,12 @@ describe('Multi-file store mutations', () => {
expect(localState.viewer).toBe('diff');
});
});
+
+ describe('TOGGLE_FILE_FINDER', () => {
+ it('updates fileFindVisible', () => {
+ mutations.TOGGLE_FILE_FINDER(localState, true);
+
+ expect(localState.fileFindVisible).toBe(true);
+ });
+ });
});