Commit 94ccb0a8 authored by Ezekiel Kigbo's avatar Ezekiel Kigbo Committed by Scott Hampton

Fix mismatched custom vue event names

Ensure that the custom emitted events for
the type of work chart labels filters are
consistent
parent abb7fc8f
...@@ -159,7 +159,7 @@ export default { ...@@ -159,7 +159,7 @@ export default {
'cursor-not-allowed': disabled, 'cursor-not-allowed': disabled,
}" }"
:active="isSelectedLabel(label.id)" :active="isSelectedLabel(label.id)"
@click.prevent="$emit('select-label', label.id, selectedLabelIds)" @click.prevent="$emit('select-label', label.id)"
> >
<gl-icon <gl-icon
v-if="multiselect && isSelectedLabel(label.id)" v-if="multiselect && isSelectedLabel(label.id)"
......
<script> <script>
import { GlDropdownDivider, GlSegmentedControl, GlIcon } from '@gitlab/ui'; import { GlDropdownDivider, GlSegmentedControl, GlIcon, GlSprintf } from '@gitlab/ui';
import { deprecatedCreateFlash as createFlash } from '~/flash'; import { deprecatedCreateFlash as createFlash } from '~/flash';
import { s__, sprintf } from '~/locale'; import { s__, sprintf } from '~/locale';
import { import {
...@@ -18,6 +18,7 @@ export default { ...@@ -18,6 +18,7 @@ export default {
GlDropdownDivider, GlDropdownDivider,
GlIcon, GlIcon,
LabelsSelector, LabelsSelector,
GlSprintf,
}, },
props: { props: {
selectedLabelIds: { selectedLabelIds: {
...@@ -45,25 +46,14 @@ export default { ...@@ -45,25 +46,14 @@ export default {
value, value,
})); }));
}, },
selectedFiltersText() { selectedSubjectFilter() {
const { subjectFilter, selectedLabelIds } = this; const { subjectFilter } = this;
const subjectFilterText = TASKS_BY_TYPE_SUBJECT_FILTER_OPTIONS[subjectFilter] return TASKS_BY_TYPE_SUBJECT_FILTER_OPTIONS[subjectFilter]
? TASKS_BY_TYPE_SUBJECT_FILTER_OPTIONS[subjectFilter] ? TASKS_BY_TYPE_SUBJECT_FILTER_OPTIONS[subjectFilter]
: TASKS_BY_TYPE_SUBJECT_FILTER_OPTIONS[TASKS_BY_TYPE_SUBJECT_ISSUE]; : TASKS_BY_TYPE_SUBJECT_FILTER_OPTIONS[TASKS_BY_TYPE_SUBJECT_ISSUE];
return sprintf(
s__('CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels'),
{
subjectFilterText,
selectedLabelsCount: selectedLabelIds.length,
},
);
}, },
selectedLabelLimitText() { selectedLabelsCount() {
const { selectedLabelIds, maxLabels } = this; return this.selectedLabelIds.length;
return sprintf(s__('CycleAnalytics|%{selectedLabelsCount} selected (%{maxLabels} max)'), {
selectedLabelsCount: selectedLabelIds.length,
maxLabels,
});
}, },
maxLabelsSelected() { maxLabelsSelected() {
return this.selectedLabelIds.length >= this.maxLabels; return this.selectedLabelIds.length >= this.maxLabels;
...@@ -77,7 +67,7 @@ export default { ...@@ -77,7 +67,7 @@ export default {
handleLabelSelected(value) { handleLabelSelected(value) {
removeFlash('notice'); removeFlash('notice');
if (this.canUpdateLabelFilters(value)) { if (this.canUpdateLabelFilters(value)) {
this.$emit('updateFilter', { filter: TASKS_BY_TYPE_FILTERS.LABEL, value }); this.$emit('update-filter', { filter: TASKS_BY_TYPE_FILTERS.LABEL, value });
} else { } else {
const { maxLabels } = this; const { maxLabels } = this;
const message = sprintf( const message = sprintf(
...@@ -97,10 +87,24 @@ export default { ...@@ -97,10 +87,24 @@ export default {
> >
<div class="flex-column"> <div class="flex-column">
<h4>{{ s__('CycleAnalytics|Tasks by type') }}</h4> <h4>{{ s__('CycleAnalytics|Tasks by type') }}</h4>
<p v-if="hasData">{{ selectedFiltersText }}</p> <p v-if="hasData">
<gl-sprintf
:message="
n__(
'CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label',
'CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels',
selectedLabelsCount,
)
"
>
<template #selectedLabelsCount>{{ selectedLabelsCount }}</template>
<template #subjectFilterText>{{ selectedSubjectFilter }}</template>
</gl-sprintf>
</p>
</div> </div>
<div class="flex-column"> <div class="flex-column">
<labels-selector <labels-selector
data-testid="type-of-work-filters-label"
:default-selected-labels-ids="selectedLabelIds" :default-selected-labels-ids="selectedLabelIds"
:max-labels="maxLabels" :max-labels="maxLabels"
:aria-label="__('CycleAnalytics|Display chart filters')" :aria-label="__('CycleAnalytics|Display chart filters')"
...@@ -108,7 +112,7 @@ export default { ...@@ -108,7 +112,7 @@ export default {
aria-expanded="false" aria-expanded="false"
multiselect multiselect
right right
@selectLabel="handleLabelSelected" @select-label="handleLabelSelected"
> >
<template #label-dropdown-button> <template #label-dropdown-button>
<gl-icon class="vertical-align-top" name="settings" /> <gl-icon class="vertical-align-top" name="settings" />
...@@ -118,11 +122,12 @@ export default { ...@@ -118,11 +122,12 @@ export default {
<div class="mb-3 px-3"> <div class="mb-3 px-3">
<p class="font-weight-bold text-left mb-2">{{ s__('CycleAnalytics|Show') }}</p> <p class="font-weight-bold text-left mb-2">{{ s__('CycleAnalytics|Show') }}</p>
<gl-segmented-control <gl-segmented-control
data-testid="type-of-work-filters-subject"
:checked="subjectFilter" :checked="subjectFilter"
:options="subjectFilterOptions" :options="subjectFilterOptions"
@input=" @input="
(value) => (value) =>
$emit('updateFilter', { filter: $options.TASKS_BY_TYPE_FILTERS.SUBJECT, value }) $emit('update-filter', { filter: $options.TASKS_BY_TYPE_FILTERS.SUBJECT, value })
" "
/> />
</div> </div>
...@@ -130,7 +135,16 @@ export default { ...@@ -130,7 +135,16 @@ export default {
<div class="mb-3 px-3"> <div class="mb-3 px-3">
<p class="font-weight-bold text-left my-2"> <p class="font-weight-bold text-left my-2">
{{ s__('CycleAnalytics|Select labels') }} {{ s__('CycleAnalytics|Select labels') }}
<br /><small>{{ selectedLabelLimitText }}</small> <br /><small>
<gl-sprintf
:message="
s__('CycleAnalytics|%{selectedLabelsCount} selected (%{maxLabels} max)')
"
>
<template #selectedLabelsCount>{{ selectedLabelsCount }}</template>
<template #maxLabels>{{ maxLabels }}</template>
</gl-sprintf>
</small>
</p> </p>
</div> </div>
</template> </template>
......
...@@ -81,7 +81,7 @@ export default { ...@@ -81,7 +81,7 @@ export default {
:has-data="hasData" :has-data="hasData"
:selected-label-ids="selectedLabelIdsFilter" :selected-label-ids="selectedLabelIdsFilter"
:subject-filter="selectedSubjectFilter" :subject-filter="selectedSubjectFilter"
@updateFilter="onUpdateFilter" @update-filter="onUpdateFilter"
/> />
<tasks-by-type-chart <tasks-by-type-chart
v-if="hasData" v-if="hasData"
......
---
title: Ensure task by type filters refresh the chart data
merge_request: 55958
author:
type: fixed
...@@ -82,6 +82,8 @@ RSpec.describe 'Value stream analytics charts', :js do ...@@ -82,6 +82,8 @@ RSpec.describe 'Value stream analytics charts', :js do
end end
describe 'Tasks by type chart', :js do describe 'Tasks by type chart', :js do
filters_selector = '.js-tasks-by-type-chart-filters'
before do before do
stub_licensed_features(cycle_analytics_for_groups: true, type_of_work_analytics: true) stub_licensed_features(cycle_analytics_for_groups: true, type_of_work_analytics: true)
...@@ -94,6 +96,9 @@ RSpec.describe 'Value stream analytics charts', :js do ...@@ -94,6 +96,9 @@ RSpec.describe 'Value stream analytics charts', :js do
context 'enabled' do context 'enabled' do
context 'with data available' do context 'with data available' do
before do before do
mr_issue = create(:labeled_issue, created_at: 5.days.ago, project: create(:project, group: group), labels: [group_label2])
create(:merge_request, iid: mr_issue.id, created_at: 3.days.ago, source_project: project, labels: [group_label1, group_label2])
3.times do |i| 3.times do |i|
create(:labeled_issue, created_at: i.days.ago, project: create(:project, group: group), labels: [group_label1]) create(:labeled_issue, created_at: i.days.ago, project: create(:project, group: group), labels: [group_label1])
create(:labeled_issue, created_at: i.days.ago, project: create(:project, group: group), labels: [group_label2]) create(:labeled_issue, created_at: i.days.ago, project: create(:project, group: group), labels: [group_label2])
...@@ -113,7 +118,24 @@ RSpec.describe 'Value stream analytics charts', :js do ...@@ -113,7 +118,24 @@ RSpec.describe 'Value stream analytics charts', :js do
end end
it 'has chart filters' do it 'has chart filters' do
expect(page).to have_css('.js-tasks-by-type-chart-filters') expect(page).to have_css(filters_selector)
end
it 'can update the filters' do
page.within filters_selector do
find('.dropdown-toggle').click
first_selected_label = all('[data-testid="type-of-work-filters-label"] .dropdown-item.active').first
first_selected_label.click
end
expect(page).to have_text('Showing Issues and 1 label')
page.within filters_selector do
find('.dropdown-toggle').click
find('[data-testid="type-of-work-filters-subject"] label', text: 'Merge Requests').click
end
expect(page).to have_text('Showing Merge Requests and 1 label')
end end
end end
......
...@@ -100,7 +100,7 @@ describe('Value Stream Analytics LabelsSelector', () => { ...@@ -100,7 +100,7 @@ describe('Value Stream Analytics LabelsSelector', () => {
return waitForPromises(); return waitForPromises();
}); });
it('will emit the "selectLabel" event', () => { it('will emit the "select-label" event', () => {
expect(wrapper.emitted('select-label')).toBeUndefined(); expect(wrapper.emitted('select-label')).toBeUndefined();
const elem = wrapper.findAll('.dropdown-item').at(1); const elem = wrapper.findAll('.dropdown-item').at(1);
......
import { GlDropdownItem, GlSegmentedControl } from '@gitlab/ui'; import { GlDropdownItem, GlSegmentedControl, GlSprintf } from '@gitlab/ui';
import { shallowMount, mount, createLocalVue } from '@vue/test-utils'; import { shallowMount, mount, createLocalVue } from '@vue/test-utils';
import axios from 'axios'; import axios from 'axios';
import MockAdapter from 'axios-mock-adapter'; import MockAdapter from 'axios-mock-adapter';
...@@ -56,6 +56,7 @@ function createComponent({ props = {}, mountFn = shallowMount } = {}) { ...@@ -56,6 +56,7 @@ function createComponent({ props = {}, mountFn = shallowMount } = {}) {
}, },
stubs: { stubs: {
LabelsSelector, LabelsSelector,
GlSprintf,
}, },
}); });
} }
...@@ -63,7 +64,10 @@ function createComponent({ props = {}, mountFn = shallowMount } = {}) { ...@@ -63,7 +64,10 @@ function createComponent({ props = {}, mountFn = shallowMount } = {}) {
describe('TasksByTypeFilters', () => { describe('TasksByTypeFilters', () => {
let wrapper = null; let wrapper = null;
let mock = null; let mock = null;
const selectedFilterText = (count = 1) => `Showing Issues and ${count} labels`; const selectedFilterText = (count = 1) => {
const affix = count > 1 ? 'labels' : 'label';
return `Showing Issues and ${count} ${affix}`;
};
beforeEach(() => { beforeEach(() => {
mock = mockGroupLabelsRequest(); mock = mockGroupLabelsRequest();
...@@ -110,13 +114,13 @@ describe('TasksByTypeFilters', () => { ...@@ -110,13 +114,13 @@ describe('TasksByTypeFilters', () => {
return waitForPromises(); return waitForPromises();
}); });
it('emits the `updateFilter` event when a label is selected', () => { it('emits the `update-filter` event when a label is selected', () => {
expect(wrapper.emitted('updateFilter')).toBeUndefined(); expect(wrapper.emitted('update-filter')).toBeUndefined();
wrapper.find(LabelsSelector).vm.$emit('selectLabel', groupLabels[0].id); wrapper.find(LabelsSelector).vm.$emit('select-label', groupLabels[0].id);
expect(wrapper.emitted('updateFilter')).toBeDefined(); expect(wrapper.emitted('update-filter')).toBeDefined();
expect(wrapper.emitted('updateFilter')[0]).toEqual([ expect(wrapper.emitted('update-filter')[0]).toEqual([
{ filter: TASKS_BY_TYPE_FILTERS.LABEL, value: groupLabels[0].id }, { filter: TASKS_BY_TYPE_FILTERS.LABEL, value: groupLabels[0].id },
]); ]);
}); });
...@@ -157,7 +161,7 @@ describe('TasksByTypeFilters', () => { ...@@ -157,7 +161,7 @@ describe('TasksByTypeFilters', () => {
}); });
return waitForPromises().then(() => { return waitForPromises().then(() => {
wrapper.find(LabelsSelector).vm.$emit('selectLabel', groupLabels[2].id); wrapper.find(LabelsSelector).vm.$emit('select-label', groupLabels[2].id);
}); });
}); });
...@@ -166,7 +170,7 @@ describe('TasksByTypeFilters', () => { ...@@ -166,7 +170,7 @@ describe('TasksByTypeFilters', () => {
}); });
it('should not allow selecting another label', () => { it('should not allow selecting another label', () => {
expect(wrapper.emitted('updateFilter')).toBeUndefined(); expect(wrapper.emitted('update-filter')).toBeUndefined();
}); });
it('should display a message', () => { it('should display a message', () => {
...@@ -183,15 +187,15 @@ describe('TasksByTypeFilters', () => { ...@@ -183,15 +187,15 @@ describe('TasksByTypeFilters', () => {
expect(findSelectedSubjectFilters(wrapper)).toBe(TASKS_BY_TYPE_SUBJECT_ISSUE); expect(findSelectedSubjectFilters(wrapper)).toBe(TASKS_BY_TYPE_SUBJECT_ISSUE);
}); });
it('emits the `updateFilter` event when a subject filter is clicked', () => { it('emits the `update-filter` event when a subject filter is clicked', () => {
wrapper = createComponent({ mountFn: mount }); wrapper = createComponent({ mountFn: mount });
expect(wrapper.emitted('updateFilter')).toBeUndefined(); expect(wrapper.emitted('update-filter')).toBeUndefined();
findSubjectFilters(wrapper).findAll('label:not(.active)').at(0).trigger('click'); findSubjectFilters(wrapper).findAll('label:not(.active)').at(0).trigger('click');
return wrapper.vm.$nextTick(() => { return wrapper.vm.$nextTick(() => {
expect(wrapper.emitted('updateFilter')).toBeDefined(); expect(wrapper.emitted('update-filter')).toBeDefined();
expect(wrapper.emitted('updateFilter')[0]).toEqual([ expect(wrapper.emitted('update-filter')[0]).toEqual([
{ {
filter: TASKS_BY_TYPE_FILTERS.SUBJECT, filter: TASKS_BY_TYPE_FILTERS.SUBJECT,
value: TASKS_BY_TYPE_SUBJECT_MERGE_REQUEST, value: TASKS_BY_TYPE_SUBJECT_MERGE_REQUEST,
......
...@@ -105,7 +105,7 @@ describe('TypeOfWorkCharts', () => { ...@@ -105,7 +105,7 @@ describe('TypeOfWorkCharts', () => {
beforeEach(() => { beforeEach(() => {
wrapper = createComponent(); wrapper = createComponent();
findSubjectFilters(wrapper).vm.$emit('updateFilter', payload); findSubjectFilters(wrapper).vm.$emit('update-filter', payload);
return wrapper.vm.$nextTick(); return wrapper.vm.$nextTick();
}); });
......
...@@ -9289,8 +9289,10 @@ msgstr "" ...@@ -9289,8 +9289,10 @@ msgstr ""
msgid "CycleAnalytics|Show" msgid "CycleAnalytics|Show"
msgstr "" msgstr ""
msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels" msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} label"
msgstr "" msgid_plural "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
msgstr[0] ""
msgstr[1] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}" msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
msgstr "" msgstr ""
......
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