Commit 6ce2b93c authored by Ezekiel Kigbo's avatar Ezekiel Kigbo

Display a warning when maximum labels reached

Indicate how many labels are selected

When the user selects more than 10 labels
we should display how many labels are currently
selected and what the maximum is

Cleaned up tests

Fix alignment of label checkmarks

Display selected number of labels at all times

Disable selection of new labels
after max labels selected
parent d8f8ecb8
......@@ -524,6 +524,8 @@ img.emoji {
cursor: pointer;
}
.cursor-not-allowed { cursor: not-allowed; }
// this needs to use "!important" due to some very specific styles
// around buttons
.cursor-default {
......
......@@ -5,8 +5,11 @@ import {
GlNewDropdown,
GlNewDropdownItem,
GlSearchBoxByType,
GlIcon,
} from '@gitlab/ui';
import { s__, sprintf } from '~/locale';
import createFlash from '~/flash';
import { removeFlash } from '../utils';
import {
TASKS_BY_TYPE_FILTERS,
TASKS_BY_TYPE_SUBJECT_ISSUE,
......@@ -19,6 +22,7 @@ export default {
components: {
GlSegmentedControl,
GlDropdownDivider,
GlIcon,
GlNewDropdown,
GlNewDropdownItem,
GlSearchBoxByType,
......@@ -27,8 +31,7 @@ export default {
maxLabels: {
type: Number,
required: false,
// default: TASKS_BY_TYPE_MAX_LABELS,
default: 2,
default: TASKS_BY_TYPE_MAX_LABELS,
},
labels: {
type: Array,
......@@ -87,6 +90,9 @@ export default {
maxLabelsSelected() {
return this.selectedLabelIds.length >= this.maxLabels;
},
hasMatchingLabels() {
return this.availableLabels.length;
},
},
methods: {
canUpdateLabelFilters(value) {
......@@ -96,11 +102,20 @@ export default {
isLabelSelected(id) {
return this.selectedLabelIds.includes(id);
},
isLabelDisabled(id) {
return this.maxLabelsSelected && !this.isLabelSelected(id);
},
handleLabelSelected(value) {
console.log('handleLabelSelected', value);
// e.preventDefault();
removeFlash('notice');
if (this.canUpdateLabelFilters(value)) {
this.$emit('updateFilter', { filter: TASKS_BY_TYPE_FILTERS.LABEL, value });
} else {
const { maxLabels } = this;
const message = sprintf(
s__('CycleAnalytics|Only %{maxLabels} labels can be selected at this time'),
{ maxLabels },
);
createFlash(message, 'notice');
}
},
},
......@@ -138,27 +153,34 @@ export default {
<div ref="labelsFilter" class="js-tasks-by-type-chart-filters-labels mb-3 px-3">
<p class="font-weight-bold text-left my-2">
{{ s__('CycleAnalytics|Select labels') }}
<br />
<small>{{ selectedLabelLimitText }}</small>
</p>
<small>{{ selectedLabelLimitText }}</small>
<gl-search-box-by-type
v-model.trim="labelsSearchTerm"
class="js-tasks-by-type-chart-filters-subject mb-2"
/>
<!-- TODO: make label dropdown item? -->
<gl-new-dropdown-item
v-for="label in availableLabels"
:key="label.id"
:is-checked="isLabelSelected(label.id)"
:disabled="isLabelDisabled(label.id)"
:class="{
'pl-4': !isLabelSelected(label.id),
'cursor-not-allowed': isLabelDisabled(label.id),
}"
@click="() => handleLabelSelected(label.id)"
>
<gl-icon
v-if="isLabelSelected(label.id)"
class="text-gray-700 mr-1 vertical-align-middle"
name="mobile-issue-close"
/>
<span
:style="{ 'background-color': label.color }"
class="d-inline-block dropdown-label-box"
></span>
{{ label.name }}
</gl-new-dropdown-item>
<div v-show="availableLabels.length < 1" class="text-secondary">
<div v-show="!hasMatchingLabels" class="text-secondary">
{{ __('No matching labels') }}
</div>
</div>
......
......@@ -3,19 +3,13 @@ import Api from 'ee/api';
import { getDayDifference, getDateInPast } from '~/lib/utils/datetime_utility';
import { historyPushState } from '~/lib/utils/common_utils';
import { setUrlParams } from '~/lib/utils/url_utility';
import createFlash, { hideFlash } from '~/flash';
import createFlash from '~/flash';
import { __, sprintf } from '~/locale';
import httpStatus from '~/lib/utils/http_status';
import * as types from './mutation_types';
import { dateFormats } from '../../shared/constants';
import { toYmd } from '../../shared/utils';
const removeError = () => {
const flashEl = document.querySelector('.flash-alert');
if (flashEl) {
hideFlash(flashEl);
}
};
import { removeFlash } from '../utils';
const handleErrorOrRethrow = ({ action, error }) => {
if (error?.response?.status === httpStatus.FORBIDDEN) {
......@@ -167,7 +161,7 @@ export const receiveCycleAnalyticsDataError = ({ commit }, { response }) => {
};
export const fetchCycleAnalyticsData = ({ dispatch }) => {
removeError();
removeFlash();
dispatch('requestCycleAnalyticsData');
return Promise.resolve()
......@@ -182,12 +176,12 @@ export const fetchCycleAnalyticsData = ({ dispatch }) => {
export const hideCustomStageForm = ({ commit }) => {
commit(types.HIDE_CUSTOM_STAGE_FORM);
removeError();
removeFlash();
};
export const showCustomStageForm = ({ commit }) => {
commit(types.SHOW_CUSTOM_STAGE_FORM);
removeError();
removeFlash();
};
export const showEditCustomStageForm = ({ commit, dispatch }, selectedStage = {}) => {
......@@ -209,7 +203,7 @@ export const showEditCustomStageForm = ({ commit, dispatch }, selectedStage = {}
endEventLabelId,
});
dispatch('setSelectedStage', selectedStage);
removeError();
removeFlash();
};
export const requestSummaryData = ({ commit }) => commit(types.REQUEST_SUMMARY_DATA);
......@@ -346,7 +340,7 @@ export const fetchGroupStagesAndEvents = ({ state, dispatch, getters }) => {
export const clearCustomStageFormErrors = ({ commit }) => {
commit(types.CLEAR_CUSTOM_STAGE_FORM_ERRORS);
removeError();
removeFlash();
};
export const requestCreateCustomStage = ({ commit }) => commit(types.REQUEST_CREATE_CUSTOM_STAGE);
......@@ -622,7 +616,6 @@ export const updateSelectedDurationChartStages = ({ state, commit }, stages) =>
};
export const setTasksByTypeFilters = ({ dispatch, commit }, data) => {
console.log('setTasksByTypeFilters', data);
commit(types.SET_TASKS_BY_TYPE_FILTERS, data);
dispatch('fetchTasksByTypeData');
};
......
......@@ -2,6 +2,7 @@ import { isNumber } from 'underscore';
import dateFormat from 'dateformat';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import { convertToSnakeCase } from '~/lib/utils/text_utility';
import { hideFlash } from '~/flash';
import {
newDate,
dayAfter,
......@@ -17,6 +18,13 @@ import { toYmd } from '../shared/utils';
const EVENT_TYPE_LABEL = 'label';
export const removeFlash = (type = 'alert') => {
const flashEl = document.querySelector(`.flash-${type}`);
if (flashEl) {
hideFlash(flashEl);
}
};
export const isStartEvent = ev => Boolean(ev) && Boolean(ev.canBeStartEvent) && ev.canBeStartEvent;
export const eventToOption = (obj = null) => {
......
......@@ -4,9 +4,9 @@ exports[`MergeRequestTable component template matches the snapshot 1`] = `
<table
aria-busy="false"
aria-colcount="7"
aria-describedby="__BVID__57__caption_"
aria-describedby="__BVID__59__caption_"
class="table b-table gl-table my-3 b-table-stacked-sm"
id="__BVID__57"
id="__BVID__59"
role="table"
>
<!---->
......
......@@ -7,7 +7,7 @@ exports[`CustomStageForm Editing a custom stage isSavingCustomStage=true display
`;
exports[`CustomStageForm Start event with events does not select events with canBeStartEvent=false for the start events dropdown 1`] = `
"<select name=\\"custom-stage-start-event\\" required=\\"required\\" aria-required=\\"true\\" class=\\"gl-form-select custom-select\\" id=\\"__BVID__255\\">
"<select name=\\"custom-stage-start-event\\" required=\\"required\\" aria-required=\\"true\\" class=\\"gl-form-select custom-select\\" id=\\"__BVID__257\\">
<option value=\\"\\">Select start event</option>
<option value=\\"issue_created\\">Issue created</option>
<option value=\\"issue_first_mentioned_in_commit\\">Issue first mentioned in a commit</option>
......@@ -30,7 +30,7 @@ exports[`CustomStageForm Start event with events does not select events with can
`;
exports[`CustomStageForm Start event with events selects events with canBeStartEvent=true for the start events dropdown 1`] = `
"<select name=\\"custom-stage-start-event\\" required=\\"required\\" aria-required=\\"true\\" class=\\"gl-form-select custom-select\\" id=\\"__BVID__215\\">
"<select name=\\"custom-stage-start-event\\" required=\\"required\\" aria-required=\\"true\\" class=\\"gl-form-select custom-select\\" id=\\"__BVID__217\\">
<option value=\\"\\">Select start event</option>
<option value=\\"issue_created\\">Issue created</option>
<option value=\\"issue_first_mentioned_in_commit\\">Issue first mentioned in a commit</option>
......
......@@ -17,7 +17,7 @@ exports[`TasksByTypeChart with data available should render the loading chart 1`
<h3>Type of work</h3>
<div>
<p>Showing data for group 'Gitlab Org' from Dec 11, 2019 to Jan 10, 2020</p>
<tasks-by-type-filters-stub maxlabels=\\"2\\" labels=\\"[object Object],[object Object],[object Object]\\" selectedlabelids=\\"1,2,3\\" subjectfilter=\\"Issue\\"></tasks-by-type-filters-stub>
<tasks-by-type-filters-stub maxlabels=\\"15\\" labels=\\"[object Object],[object Object],[object Object]\\" selectedlabelids=\\"1,2,3\\" subjectfilter=\\"Issue\\"></tasks-by-type-filters-stub>
<gl-stacked-column-chart-stub data=\\"0,1,2,5,2,3,2,4,1\\" option=\\"[object Object]\\" presentation=\\"stacked\\" groupby=\\"Group 1,Group 2,Group 3\\" xaxistype=\\"category\\" xaxistitle=\\"Date\\" yaxistitle=\\"Number of tasks\\" seriesnames=\\"Cool label,Normal label\\" legendaveragetext=\\"Avg\\" legendmaxtext=\\"Max\\" y-axis-type=\\"value\\"></gl-stacked-column-chart-stub>
</div>
</div>
......
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`TasksByTypeFilters no data available should render the no data available message 1`] = `
"<div class=\\"js-tasks-by-type-chart-filters d-flex flex-row justify-content-between align-items-center\\">
<div class=\\"flex-column\\">
<h4>Tasks by type</h4>
<p>Showing Issues and 1 labels</p>
</div>
<div class=\\"flex-column\\">
<glnewdropdown-stub headertext=\\"\\" text=\\"\\" category=\\"tertiary\\" variant=\\"default\\" size=\\"medium\\" icon=\\"settings\\" aria-expanded=\\"false\\" aria-label=\\"CycleAnalytics|Display chart filters\\" right=\\"\\">
<div class=\\"js-tasks-by-type-chart-filters-subject mb-3 px-3\\">
<p class=\\"font-weight-bold text-left mb-2\\">Show</p>
<gl-segmented-control-stub checked=\\"Issue\\" options=\\"[object Object],[object Object]\\"></gl-segmented-control-stub>
</div>
<gl-dropdown-divider-stub></gl-dropdown-divider-stub>
<div class=\\"js-tasks-by-type-chart-filters-labels mb-3 px-3\\">
<p class=\\"font-weight-bold text-left my-2\\">
Select labels
<br> <small>1 selected (2 max)</small></p>
<gl-search-box-by-type-stub value=\\"\\" class=\\"js-tasks-by-type-chart-filters-subject mb-2\\"></gl-search-box-by-type-stub>
<glnewdropdownitem-stub avatarurl=\\"\\" iconcolor=\\"\\" iconname=\\"\\" iconrightname=\\"\\" ischecked=\\"true\\" secondarytext=\\"\\"><span class=\\"d-inline-block dropdown-label-box\\" style=\\"background-color: rgb(255, 0, 0);\\"></span>
roses
</glnewdropdownitem-stub>
<glnewdropdownitem-stub avatarurl=\\"\\" iconcolor=\\"\\" iconname=\\"\\" iconrightname=\\"\\" secondarytext=\\"\\"><span class=\\"d-inline-block dropdown-label-box\\" style=\\"background-color: rgb(255, 255, 255);\\"></span>
some space
</glnewdropdownitem-stub>
<glnewdropdownitem-stub avatarurl=\\"\\" iconcolor=\\"\\" iconname=\\"\\" iconrightname=\\"\\" secondarytext=\\"\\"><span class=\\"d-inline-block dropdown-label-box\\" style=\\"background-color: rgb(0, 0, 255);\\"></span>
violets
</glnewdropdownitem-stub>
<div class=\\"text-secondary\\" style=\\"display: none;\\">
No matching labels
</div>
</div>
</glnewdropdown-stub>
</div>
</div>"
`;
exports[`TasksByTypeFilters with data available labels with label dropdown open renders the group labels as dropdown items 1`] = `
"<glnewdropdown-stub headertext=\\"\\" text=\\"\\" category=\\"tertiary\\" variant=\\"default\\" size=\\"medium\\" icon=\\"settings\\" aria-expanded=\\"false\\" aria-label=\\"CycleAnalytics|Display chart filters\\" right=\\"\\">
<div class=\\"js-tasks-by-type-chart-filters-subject mb-3 px-3\\">
<p class=\\"font-weight-bold text-left mb-2\\">Show</p>
<gl-segmented-control-stub checked=\\"Issue\\" options=\\"[object Object],[object Object]\\"></gl-segmented-control-stub>
</div>
<gl-dropdown-divider-stub></gl-dropdown-divider-stub>
<div class=\\"js-tasks-by-type-chart-filters-labels mb-3 px-3\\">
<p class=\\"font-weight-bold text-left my-2\\">
Select labels
<br> <small>1 selected (2 max)</small></p>
<gl-search-box-by-type-stub value=\\"\\" class=\\"js-tasks-by-type-chart-filters-subject mb-2\\"></gl-search-box-by-type-stub>
<glnewdropdownitem-stub avatarurl=\\"\\" iconcolor=\\"\\" iconname=\\"\\" iconrightname=\\"\\" ischecked=\\"true\\" secondarytext=\\"\\"><span class=\\"d-inline-block dropdown-label-box\\" style=\\"background-color: rgb(255, 0, 0);\\"></span>
roses
</glnewdropdownitem-stub>
<glnewdropdownitem-stub avatarurl=\\"\\" iconcolor=\\"\\" iconname=\\"\\" iconrightname=\\"\\" secondarytext=\\"\\"><span class=\\"d-inline-block dropdown-label-box\\" style=\\"background-color: rgb(255, 255, 255);\\"></span>
some space
</glnewdropdownitem-stub>
<glnewdropdownitem-stub avatarurl=\\"\\" iconcolor=\\"\\" iconname=\\"\\" iconrightname=\\"\\" secondarytext=\\"\\"><span class=\\"d-inline-block dropdown-label-box\\" style=\\"background-color: rgb(0, 0, 255);\\"></span>
violets
</glnewdropdownitem-stub>
<div class=\\"text-secondary\\" style=\\"display: none;\\">
No matching labels
</div>
</div>
</glnewdropdown-stub>"
`;
exports[`TasksByTypeFilters with data available should render the filters 1`] = `
"<div class=\\"js-tasks-by-type-chart-filters d-flex flex-row justify-content-between align-items-center\\">
<div class=\\"flex-column\\">
<h4>Tasks by type</h4>
<p>Showing Issues and 1 labels</p>
</div>
<div class=\\"flex-column\\">
<glnewdropdown-stub headertext=\\"\\" text=\\"\\" category=\\"tertiary\\" variant=\\"default\\" size=\\"medium\\" icon=\\"settings\\" aria-expanded=\\"false\\" aria-label=\\"CycleAnalytics|Display chart filters\\" right=\\"\\">
<div class=\\"js-tasks-by-type-chart-filters-subject mb-3 px-3\\">
<p class=\\"font-weight-bold text-left mb-2\\">Show</p>
<gl-segmented-control-stub checked=\\"Issue\\" options=\\"[object Object],[object Object]\\"></gl-segmented-control-stub>
</div>
<gl-dropdown-divider-stub></gl-dropdown-divider-stub>
<div class=\\"js-tasks-by-type-chart-filters-labels mb-3 px-3\\">
<p class=\\"font-weight-bold text-left my-2\\">
Select labels
<br> <small>1 selected (2 max)</small></p>
<gl-search-box-by-type-stub value=\\"\\" class=\\"js-tasks-by-type-chart-filters-subject mb-2\\"></gl-search-box-by-type-stub>
<glnewdropdownitem-stub avatarurl=\\"\\" iconcolor=\\"\\" iconname=\\"\\" iconrightname=\\"\\" ischecked=\\"true\\" secondarytext=\\"\\"><span class=\\"d-inline-block dropdown-label-box\\" style=\\"background-color: rgb(255, 0, 0);\\"></span>
roses
</glnewdropdownitem-stub>
<glnewdropdownitem-stub avatarurl=\\"\\" iconcolor=\\"\\" iconname=\\"\\" iconrightname=\\"\\" secondarytext=\\"\\"><span class=\\"d-inline-block dropdown-label-box\\" style=\\"background-color: rgb(255, 255, 255);\\"></span>
some space
</glnewdropdownitem-stub>
<glnewdropdownitem-stub avatarurl=\\"\\" iconcolor=\\"\\" iconname=\\"\\" iconrightname=\\"\\" secondarytext=\\"\\"><span class=\\"d-inline-block dropdown-label-box\\" style=\\"background-color: rgb(0, 0, 255);\\"></span>
violets
</glnewdropdownitem-stub>
<div class=\\"text-secondary\\" style=\\"display: none;\\">
No matching labels
</div>
</div>
</glnewdropdown-stub>
</div>
</div>"
`;
exports[`TasksByTypeFilters with data available subject has subject filters 1`] = `"<gl-segmented-control-stub checked=\\"Issue\\" options=\\"[object Object],[object Object]\\"></gl-segmented-control-stub>"`;
import { shallowMount, mount } from '@vue/test-utils';
import { GlNewDropdown, GlNewDropdownItem, GlSegmentedControl } from '@gitlab/ui';
import { GlNewDropdownItem, GlSegmentedControl } from '@gitlab/ui';
import TasksByTypeFilters from 'ee/analytics/cycle_analytics/components/tasks_by_type_filters.vue';
import {
TASKS_BY_TYPE_SUBJECT_ISSUE,
......@@ -13,10 +13,12 @@ const selectedLabelIds = [groupLabels[0].id];
const findSubjectFilters = ctx =>
ctx.find('.js-tasks-by-type-chart-filters-subject').find(GlSegmentedControl);
const findSelectedSubjectFilters = ctx => findSubjectFilters(ctx).attributes('checked');
const findDropdown = ctx => ctx.find(GlNewDropdown);
const findDropdownLabels = ctx =>
ctx.find('.js-tasks-by-type-chart-filters-labels').findAll(GlNewDropdownItem);
const shouldFlashAMessage = (msg = '') =>
expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe(msg);
const selectLabelAtIndex = (ctx, index) => {
findDropdownLabels(ctx)
.at(index)
......@@ -43,104 +45,100 @@ function createComponent({ props = {}, shallow = true }) {
describe('TasksByTypeFilters', () => {
let wrapper = null;
describe('with data available', () => {
beforeEach(() => {
wrapper = createComponent({});
});
afterEach(() => {
wrapper.destroy();
});
describe('labels', () => {
beforeEach(() => {
wrapper = createComponent({});
});
afterEach(() => {
wrapper.destroy();
});
it('emits the `updateFilter` event when a subject label is clicked', () => {
expect(wrapper.emitted().updateFilter).toBeUndefined();
return selectLabelAtIndex(wrapper, 0).then(() => {
expect(wrapper.emitted().updateFilter).toBeDefined();
it('should render the filters', () => {
expect(wrapper.html()).toMatchSnapshot();
});
describe('labels', () => {
it(`should have ${selectedLabelIds.length} selected`, () => {
expect(wrapper.text()).toContain('1 selected (15 max)');
expect(wrapper.emitted().updateFilter[0]).toEqual([
{ filter: TASKS_BY_TYPE_FILTERS.LABEL, value: groupLabels[0].id },
]);
});
});
describe('with label dropdown open', () => {
beforeEach(() => {
wrapper = createComponent({});
});
it('renders the group labels as dropdown items', () => {
expect(findDropdown(wrapper).html()).toMatchSnapshot();
describe('with the warningMessageThreshold label threshold reached', () => {
beforeEach(() => {
setFixtures('<div class="flash-container"></div>');
wrapper = createComponent({
props: {
maxLabels: 5,
selectedLabelIds: [groupLabels[0].id, groupLabels[1].id],
warningMessageThreshold: 2,
},
});
it('emits the `updateFilter` event when a subject label is clicked', () => {
expect(wrapper.emitted().updateFilter).toBeUndefined();
return selectLabelAtIndex(wrapper, 0).then(() => {
expect(wrapper.emitted().updateFilter).toBeDefined();
expect(wrapper.emitted().updateFilter[0]).toEqual([
{ filter: TASKS_BY_TYPE_FILTERS.LABEL, value: groupLabels[0].id },
]);
});
});
return selectLabelAtIndex(wrapper, 2);
});
describe('with maximum labels selected', () => {
beforeEach(() => {
wrapper = createComponent({
props: {
maxLabels: 2,
selectedLabelIds: [groupLabels[0].id, groupLabels[1].id],
},
});
});
it('should not allow selecting another label', () => {
expect(wrapper.emitted().updateFilter).toBeUndefined();
return selectLabelAtIndex(wrapper, 2).then(() => {
expect(wrapper.emitted().updateFilter).toBeUndefined();
});
});
});
it('should indicate how many labels are selected', () => {
expect(wrapper.text()).toContain('2 selected (5 max)');
});
});
describe('subject', () => {
it('has subject filters', () => {
expect(findSubjectFilters(wrapper).html()).toMatchSnapshot();
describe('with maximum labels selected', () => {
beforeEach(() => {
setFixtures('<div class="flash-container"></div>');
wrapper = createComponent({
props: {
maxLabels: 2,
selectedLabelIds: [groupLabels[0].id, groupLabels[1].id],
warningMessageThreshold: 1,
},
});
return selectLabelAtIndex(wrapper, 2);
});
it('has the issue subject set by default', () => {
expect(findSelectedSubjectFilters(wrapper)).toBe(TASKS_BY_TYPE_SUBJECT_ISSUE);
it('should indicate how many labels are selected', () => {
expect(wrapper.text()).toContain('2 selected (2 max)');
});
it('emits the `updateFilter` event when a subject filter is clicked', () => {
wrapper = createComponent({ shallow: false });
it('should not allow selecting another label', () => {
expect(wrapper.emitted().updateFilter).toBeUndefined();
});
findSubjectFilters(wrapper)
.findAll('label:not(.active)')
.at(0)
.trigger('click');
return wrapper.vm.$nextTick(() => {
expect(wrapper.emitted().updateFilter).toBeDefined();
expect(wrapper.emitted().updateFilter[0]).toEqual([
{ filter: TASKS_BY_TYPE_FILTERS.SUBJECT, value: TASKS_BY_TYPE_SUBJECT_MERGE_REQUEST },
]);
});
it('should display a message', () => {
shouldFlashAMessage('Only 2 labels can be selected at this time');
});
});
});
describe('no data available', () => {
beforeEach(() => {
wrapper = createComponent({});
});
afterEach(() => {
wrapper.destroy();
describe('subject', () => {
it('has the issue subject set by default', () => {
expect(findSelectedSubjectFilters(wrapper)).toBe(TASKS_BY_TYPE_SUBJECT_ISSUE);
});
it('should render the no data available message', () => {
expect(wrapper.html()).toMatchSnapshot();
it('emits the `updateFilter` event when a subject filter is clicked', () => {
wrapper = createComponent({ shallow: false });
expect(wrapper.emitted().updateFilter).toBeUndefined();
findSubjectFilters(wrapper)
.findAll('label:not(.active)')
.at(0)
.trigger('click');
return wrapper.vm.$nextTick(() => {
expect(wrapper.emitted().updateFilter).toBeDefined();
expect(wrapper.emitted().updateFilter[0]).toEqual([
{
filter: TASKS_BY_TYPE_FILTERS.SUBJECT,
value: TASKS_BY_TYPE_SUBJECT_MERGE_REQUEST,
},
]);
});
});
});
});
......@@ -303,17 +303,17 @@ describe('Cycle analytics mutations', () => {
expect(state.tasksByType).toEqual({ subject: 'cool-subject' });
});
it('will toggle the specified label id in the tasksByType.labelIds state key', () => {
it('will toggle the specified label id in the tasksByType.selectedLabelIds state key', () => {
state = {
tasksByType: { labelIds: [10, 20, 30] },
tasksByType: { selectedLabelIds: [10, 20, 30] },
};
const labelFilter = { filter: TASKS_BY_TYPE_FILTERS.LABEL, value: 20 };
mutations[types.SET_TASKS_BY_TYPE_FILTERS](state, labelFilter);
expect(state.tasksByType).toEqual({ labelIds: [10, 30] });
expect(state.tasksByType).toEqual({ selectedLabelIds: [10, 30] });
mutations[types.SET_TASKS_BY_TYPE_FILTERS](state, labelFilter);
expect(state.tasksByType).toEqual({ labelIds: [10, 30, 20] });
expect(state.tasksByType).toEqual({ selectedLabelIds: [10, 30, 20] });
});
});
......
......@@ -6134,6 +6134,9 @@ msgstr ""
msgid "CycleAnalytics|Number of tasks"
msgstr ""
msgid "CycleAnalytics|Only %{maxLabels} labels can be selected at this time"
msgstr ""
msgid "CycleAnalytics|Project selected"
msgid_plural "CycleAnalytics|%d projects selected"
msgstr[0] ""
......@@ -13173,6 +13176,9 @@ msgstr ""
msgid "No licenses found."
msgstr ""
msgid "No matching labels"
msgstr ""
msgid "No matching results"
msgstr ""
......
......@@ -821,25 +821,6 @@
vue-loader "^15.4.2"
vue-runtime-helpers "^1.1.2"
"@gitlab/ui@https://gitlab.com/gitlab-org/gitlab-ui":
version "9.20.0"
resolved "https://gitlab.com/gitlab-org/gitlab-ui#53509c2a2fa8b1410941212a0aa8a2b05a7558e9"
dependencies:
"@babel/standalone" "^7.0.0"
"@gitlab/vue-toasted" "^1.3.0"
bootstrap-vue "2.1.0"
copy-to-clipboard "^3.0.8"
echarts "^4.2.1"
highlight.js "^9.13.1"
js-beautify "^1.8.8"
lodash "^4.17.14"
portal-vue "^2.1.6"
resize-observer-polyfill "^1.5.1"
url-search-params-polyfill "^5.0.0"
vue "^2.6.10"
vue-loader "^15.4.2"
vue-runtime-helpers "^1.1.2"
"@gitlab/visual-review-tools@1.5.1":
version "1.5.1"
resolved "https://registry.yarnpkg.com/@gitlab/visual-review-tools/-/visual-review-tools-1.5.1.tgz#2552927cd7a376f1f06ef3293a69fe2ffcdddb52"
......
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