Commit 472a116b authored by Mike Greiling's avatar Mike Greiling

Merge branch '12588-refactor-weightselect' into 'master'

Refactor WeightSelect to use gitlab-ui dropdown

Closes #12588

See merge request gitlab-org/gitlab!20770
parents bab02ee7 a404a66b
<script>
/* eslint-disable vue/require-default-prop */
/* eslint-disable @gitlab/vue-i18n/no-bare-strings */
import WeightSelect from 'ee/weight_select';
import { GlLoadingIcon } from '@gitlab/ui';
import { GlButton, GlDropdown, GlDropdownItem } from '@gitlab/ui';
const ANY_WEIGHT = 'Any Weight';
const NO_WEIGHT = 'No Weight';
export default {
components: {
GlLoadingIcon,
GlButton,
GlDropdown,
GlDropdownItem,
},
props: {
board: {
type: Object,
required: true,
},
value: {
type: [Number, String],
required: false,
},
canEdit: {
type: Boolean,
required: false,
......@@ -33,7 +27,7 @@ export default {
},
data() {
return {
fieldName: 'weight',
dropdownHidden: true,
};
},
computed: {
......@@ -44,21 +38,20 @@ export default {
return 'bold';
},
valueText() {
if (this.value > 0) return this.value;
if (this.value === 0) return NO_WEIGHT;
const { weight } = this.board;
if (weight > 0) return weight.toString();
if (weight === 0 || weight === NO_WEIGHT) return NO_WEIGHT;
return ANY_WEIGHT;
},
},
mounted() {
this.weightDropdown = new WeightSelect(this.$refs.dropdownButton, {
handleClick: this.selectWeight,
selected: this.value,
fieldName: this.fieldName,
});
},
methods: {
selectWeight(weight) {
showDropdown() {
this.dropdownHidden = false;
this.$refs.dropdown.$children[0].show();
},
selectWeight({ target: { value: weight } }) {
this.board.weight = this.weightInt(weight);
this.dropdownHidden = true;
},
weightInt(weight) {
if (weight > 0) {
......@@ -76,38 +69,26 @@ export default {
<template>
<div class="block weight">
<div class="title append-bottom-10">
Weight
<button v-if="canEdit" type="button" class="edit-link btn btn-blank float-right">
{{ __('Weight') }}
<gl-button v-if="canEdit" variant="blank" class="float-right" @click="showDropdown">
{{ __('Edit') }}
</button>
</gl-button>
</div>
<div :class="valueClass" class="value">{{ valueText }}</div>
<div class="selectbox" style="display: none;">
<input :name="fieldName" type="hidden" />
<div class="dropdown">
<button
ref="dropdownButton"
class="dropdown-menu-toggle js-weight-select wide"
type="button"
data-default-label="Weight"
data-toggle="dropdown"
>
<span class="dropdown-toggle-text is-default">{{ __('Weight') }}</span>
<i aria-hidden="true" data-hidden="true" class="fa fa-chevron-down"> </i>
</button>
<div class="dropdown-menu dropdown-select dropdown-menu-selectable dropdown-menu-weight">
<div class="dropdown-content ">
<ul>
<li v-for="weight in weights" :key="weight">
<a :class="{ 'is-active': weight == valueText }" :data-id="weight" href="#">
{{ weight }}
</a>
</li>
</ul>
</div>
<div class="dropdown-loading"><gl-loading-icon /></div>
</div>
<div :class="valueClass" :hidden="!dropdownHidden" class="value">{{ valueText }}</div>
<gl-dropdown
ref="dropdown"
:hidden="dropdownHidden"
:text="valueText"
class="w-100"
menu-class="w-100"
toggle-class="d-flex justify-content-between"
>
<div ref="weight-select" @click="selectWeight">
<gl-dropdown-item v-for="weight in weights" :key="weight" :value="weight">
{{ weight }}
</gl-dropdown-item>
</div>
</div>
</gl-dropdown>
</div>
</template>
---
title: Refactor WeightSelect to use gitlab-ui dropdown
merge_request: 20770
author:
type: change
......@@ -508,6 +508,8 @@ describe 'Scoped issue boards', :js do
if value.is_a?(Array)
value.each { |value| click_link value }
elsif filter == 'weight'
click_button value
else
click_link value
end
......@@ -536,7 +538,7 @@ describe 'Scoped issue boards', :js do
page.within(".#{filter}") do
click_button 'Edit'
click_link value
filter == 'weight' ? click_button(value) : click_link(value)
end
click_on_board_modal
......
import { mount } from '@vue/test-utils';
import WeightSelect from 'ee/boards/components/weight_select.vue';
import { GlButton, GlDropdown } from '@gitlab/ui';
describe('WeightSelect', () => {
let wrapper;
const editButton = () => wrapper.find(GlButton);
const valueContainer = () => wrapper.find('.value');
const weightDropdown = () => wrapper.find(GlDropdown);
const weightSelect = () => wrapper.find({ ref: 'weight-select' });
const defaultProps = {
weights: ['Any Weight', 'No Weight', 1, 2, 3],
board: {
weight: null,
},
canEdit: true,
};
const createComponent = (props = {}) => {
wrapper = mount(WeightSelect, {
propsData: {
...defaultProps,
...props,
},
});
};
afterEach(() => {
wrapper.destroy();
});
describe('when no weight has been selected', () => {
beforeEach(() => {
createComponent();
});
it('displays "Any Weight"', () => {
expect(valueContainer().text()).toEqual('Any Weight');
});
it('hides the weight dropdown', () => {
expect(weightDropdown().isVisible()).toBeFalsy();
});
});
describe('when the weight cannot be edited', () => {
beforeEach(() => {
createComponent({ canEdit: false });
});
it('does not render the edit button', () => {
expect(editButton().exists()).toBeFalsy();
});
});
describe('when the weight can be edited', () => {
beforeEach(() => {
createComponent();
});
it('shows the edit button', () => {
expect(editButton().isVisible()).toBeTruthy();
});
describe('and the edit button is clicked', () => {
beforeEach(() => {
editButton().trigger('click');
});
describe('and no weight has been selected yet', () => {
it('hides the value text', () => {
expect(valueContainer().isVisible()).toBeFalsy();
});
it('shows the weight dropdown', () => {
expect(weightDropdown().isVisible()).toBeTruthy();
});
});
describe('and a weight has been selected', () => {
beforeEach(() => {
weightSelect().trigger('click');
});
it('shows the value text', () => {
expect(valueContainer().isVisible()).toBeTruthy();
});
it('hides the weight dropdown', () => {
expect(weightDropdown().isVisible()).toBeFalsy();
});
});
});
});
describe('when a new weight value is selected', () => {
it.each`
weight | text
${'Any Weight'} | ${'Any Weight'}
${'No Weight'} | ${'No Weight'}
${0} | ${'No Weight'}
${-1} | ${'Any Weight'}
${1} | ${'1'}
`('$weight displays as "$text"', ({ weight, text }) => {
createComponent({ board: { weight } });
expect(valueContainer().text()).toEqual(text);
});
});
});
import Vue from 'vue';
import WeightSelect from 'ee/boards/components/weight_select.vue';
import IssuableContext from '~/issuable_context';
let vm;
let board;
const weights = ['Any Weight', 'No Weight', 1, 2, 3];
function getSelectedText() {
return vm.$el.querySelector('.value').innerText.trim();
}
function activeDropdownItem() {
return vm.$el.querySelector('.is-active').innerText.trim();
}
describe('WeightSelect', () => {
beforeEach(done => {
setFixtures('<div class="test-container"></div>');
board = {
weight: 0,
labels: [],
};
// eslint-disable-next-line no-new
new IssuableContext();
const Component = Vue.extend(WeightSelect);
vm = new Component({
propsData: {
board,
canEdit: true,
weights,
},
}).$mount('.test-container');
Vue.nextTick(done);
});
describe('selected value', () => {
it('defaults to Any Weight', () => {
expect(getSelectedText()).toBe('Any Weight');
});
it('displays Any Weight for value -1', done => {
vm.value = -1;
Vue.nextTick(() => {
expect(getSelectedText()).toEqual('Any Weight');
done();
});
});
it('displays No Weight', done => {
vm.value = 0;
Vue.nextTick(() => {
expect(getSelectedText()).toEqual('No Weight');
done();
});
});
it('weight 1', done => {
vm.value = 1;
Vue.nextTick(() => {
expect(getSelectedText()).toEqual('1');
done();
});
});
});
describe('active item in dropdown', () => {
it('defaults to Any Weight', done => {
vm.$el.querySelector('.edit-link').click();
setTimeout(() => {
expect(activeDropdownItem()).toEqual('Any Weight');
done();
});
});
it('shows No Weight', done => {
vm.value = 0;
vm.$el.querySelector('.edit-link').click();
setTimeout(() => {
expect(activeDropdownItem()).toEqual('No Weight');
done();
});
});
it('shows correct weight', done => {
vm.value = 1;
vm.$el.querySelector('.edit-link').click();
setTimeout(() => {
expect(activeDropdownItem()).toEqual('1');
done();
});
});
});
describe('changing weight', () => {
it('sets value', done => {
vm.$el.querySelector('.edit-link').click();
setTimeout(() => {
vm.$el.querySelectorAll('li a')[3].click();
});
setTimeout(() => {
expect(activeDropdownItem()).toEqual('2');
expect(board.weight).toEqual('2');
done();
});
});
it('sets Any Weight', done => {
vm.value = 2;
vm.$el.querySelector('.edit-link').click();
setTimeout(() => {
vm.$el.querySelectorAll('li a')[0].click();
});
setTimeout(() => {
expect(activeDropdownItem()).toEqual('Any Weight');
expect(board.weight).toEqual(-1);
done();
});
});
it('sets No Weight', done => {
vm.value = 2;
vm.$el.querySelector('.edit-link').click();
setTimeout(() => {
vm.$el.querySelectorAll('li a')[1].click();
});
setTimeout(() => {
expect(activeDropdownItem()).toEqual('No Weight');
expect(board.weight).toEqual(0);
done();
});
});
});
});
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment