Adds create option in filtered dropdown
In the filtered search dropdopwn adds a button to enable creation of missing element.
This commit is contained in:
parent
8ae38ca2b7
commit
355d8ef72a
2 changed files with 132 additions and 1 deletions
|
@ -1,15 +1,21 @@
|
|||
<script>
|
||||
import $ from 'jquery';
|
||||
import { GlButton } from '@gitlab/ui';
|
||||
import { __ } from '~/locale';
|
||||
import Icon from '~/vue_shared/components/icon.vue';
|
||||
/**
|
||||
* Renders a split dropdown with
|
||||
* an input that allows to search through the given
|
||||
* array of options.
|
||||
*
|
||||
* When there are no results and `showCreateMode` is true
|
||||
* it renders a create button with the value typed.
|
||||
*/
|
||||
export default {
|
||||
name: 'FilteredSearchDropdown',
|
||||
components: {
|
||||
Icon,
|
||||
GlButton,
|
||||
},
|
||||
props: {
|
||||
title: {
|
||||
|
@ -43,6 +49,16 @@ export default {
|
|||
type: String,
|
||||
required: true,
|
||||
},
|
||||
showCreateMode: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
createButtonText: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: __('Create'),
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -64,6 +80,12 @@ export default {
|
|||
|
||||
return this.items.slice(0, this.visibleItems);
|
||||
},
|
||||
computedCreateButtonText() {
|
||||
return `${this.createButtonText} ${this.filter}`;
|
||||
},
|
||||
shouldRenderCreateButton() {
|
||||
return this.showCreateMode && this.filteredResults.length === 0 && this.filter !== '';
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
/**
|
||||
|
@ -112,10 +134,20 @@ export default {
|
|||
<div class="dropdown-content">
|
||||
<ul>
|
||||
<li v-for="(result, i) in filteredResults" :key="i" class="js-filtered-dropdown-result">
|
||||
<slot name="result" :result="result"> {{ result[filterKey] }} </slot>
|
||||
<slot name="result" :result="result">{{ result[filterKey] }}</slot>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div v-if="shouldRenderCreateButton" class="dropdown-footer">
|
||||
<slot name="footer" :filter="filter">
|
||||
<gl-button
|
||||
class="js-dropdown-create-button btn-transparent"
|
||||
@click="$emit('createItem', filter)"
|
||||
>{{ computedCreateButtonText }}</gl-button
|
||||
>
|
||||
</slot>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -88,4 +88,103 @@ describe('Filtered search dropdown', () => {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('with create mode enabled', () => {
|
||||
describe('when there are no matches', () => {
|
||||
beforeEach(() => {
|
||||
vm = mountComponent(Component, {
|
||||
items: [
|
||||
{ title: 'One' },
|
||||
{ title: 'Two/three' },
|
||||
{ title: 'Three four' },
|
||||
{ title: 'Five' },
|
||||
],
|
||||
filterKey: 'title',
|
||||
showCreateMode: true,
|
||||
});
|
||||
|
||||
vm.$el.querySelector('.js-filtered-dropdown-input').value = 'eleven';
|
||||
vm.$el.querySelector('.js-filtered-dropdown-input').dispatchEvent(new Event('input'));
|
||||
});
|
||||
|
||||
it('renders a create button', done => {
|
||||
vm.$nextTick(() => {
|
||||
expect(vm.$el.querySelector('.js-dropdown-create-button')).not.toBeNull();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('renders computed button text', done => {
|
||||
vm.$nextTick(() => {
|
||||
expect(vm.$el.querySelector('.js-dropdown-create-button').textContent.trim()).toEqual(
|
||||
'Create eleven',
|
||||
);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
describe('on click create button', () => {
|
||||
it('emits createItem event with the filter', done => {
|
||||
spyOn(vm, '$emit');
|
||||
vm.$nextTick(() => {
|
||||
vm.$el.querySelector('.js-dropdown-create-button').click();
|
||||
|
||||
expect(vm.$emit).toHaveBeenCalledWith('createItem', 'eleven');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when there are matches', () => {
|
||||
beforeEach(() => {
|
||||
vm = mountComponent(Component, {
|
||||
items: [
|
||||
{ title: 'One' },
|
||||
{ title: 'Two/three' },
|
||||
{ title: 'Three four' },
|
||||
{ title: 'Five' },
|
||||
],
|
||||
filterKey: 'title',
|
||||
showCreateMode: true,
|
||||
});
|
||||
|
||||
vm.$el.querySelector('.js-filtered-dropdown-input').value = 'one';
|
||||
vm.$el.querySelector('.js-filtered-dropdown-input').dispatchEvent(new Event('input'));
|
||||
});
|
||||
|
||||
it('does not render a create button', done => {
|
||||
vm.$nextTick(() => {
|
||||
expect(vm.$el.querySelector('.js-dropdown-create-button')).toBeNull();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('with create mode disabled', () => {
|
||||
describe('when there are no matches', () => {
|
||||
beforeEach(() => {
|
||||
vm = mountComponent(Component, {
|
||||
items: [
|
||||
{ title: 'One' },
|
||||
{ title: 'Two/three' },
|
||||
{ title: 'Three four' },
|
||||
{ title: 'Five' },
|
||||
],
|
||||
filterKey: 'title',
|
||||
});
|
||||
|
||||
vm.$el.querySelector('.js-filtered-dropdown-input').value = 'eleven';
|
||||
vm.$el.querySelector('.js-filtered-dropdown-input').dispatchEvent(new Event('input'));
|
||||
});
|
||||
|
||||
it('does not render a create button', done => {
|
||||
vm.$nextTick(() => {
|
||||
expect(vm.$el.querySelector('.js-dropdown-create-button')).toBeNull();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue