Commit db4d88f9 authored by Enrique Alcántara's avatar Enrique Alcántara

Merge branch '322126-vsa-remove-days-to-completion-scatterplot-dropdown' into 'master'

[VSA] Remove total time chart stage dropdown

See merge request gitlab-org/gitlab!80365
parents b39a7218 a5a58e7e
...@@ -280,7 +280,7 @@ Shown metrics and charts includes: ...@@ -280,7 +280,7 @@ Shown metrics and charts includes:
- [Lead time](#how-metrics-are-measured) - [Lead time](#how-metrics-are-measured)
- [Cycle time](#how-metrics-are-measured) - [Cycle time](#how-metrics-are-measured)
- [Days to completion chart](#days-to-completion-chart) - [Total time chart](#total-time-chart)
- [Tasks by type chart](#type-of-work---tasks-by-type-chart) - [Tasks by type chart](#type-of-work---tasks-by-type-chart)
### Stage table ### Stage table
...@@ -413,7 +413,7 @@ To delete a custom value stream: ...@@ -413,7 +413,7 @@ To delete a custom value stream:
![Delete value stream](img/delete_value_stream_v13_12.png "Deleting a custom value stream") ![Delete value stream](img/delete_value_stream_v13_12.png "Deleting a custom value stream")
## Days to completion chart ## Total time chart
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21631) in GitLab 12.6. > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21631) in GitLab 12.6.
> - Chart median line [removed](https://gitlab.com/gitlab-org/gitlab/-/issues/235455) in GitLab 13.4. > - Chart median line [removed](https://gitlab.com/gitlab-org/gitlab/-/issues/235455) in GitLab 13.4.
...@@ -422,8 +422,9 @@ To delete a custom value stream: ...@@ -422,8 +422,9 @@ To delete a custom value stream:
This chart visually depicts the average number of days it takes for cycles to be completed. This chart visually depicts the average number of days it takes for cycles to be completed.
This chart uses the global page filters for displaying data based on the selected This chart uses the global page filters for displaying data based on the selected
group, projects, and time frame. In addition, specific stages can be selected group, projects, and time frame.
from the chart itself.
When a stage is selected the chart only displays data relevant to the selected stage. On the overview the chart displays a sum of the times for all stages in the value stream.
The chart data is limited to the last 500 items. The chart data is limited to the last 500 items.
......
<script> <script>
import { GlAlert, GlIcon, GlTooltipDirective } from '@gitlab/ui'; import { GlAlert, GlIcon, GlTooltipDirective } from '@gitlab/ui';
import { dataVizBlue500 } from '@gitlab/ui/scss_to_js/scss_variables'; import { dataVizBlue500 } from '@gitlab/ui/scss_to_js/scss_variables';
import { mapActions, mapState, mapGetters } from 'vuex'; import { mapState, mapGetters } from 'vuex';
import { dateFormats } from '~/analytics/shared/constants'; import { dateFormats } from '~/analytics/shared/constants';
import { capitalizeFirstCharacter } from '~/lib/utils/text_utility'; import { capitalizeFirstCharacter } from '~/lib/utils/text_utility';
import { sprintf } from '~/locale'; import { sprintf } from '~/locale';
...@@ -15,7 +15,6 @@ import { ...@@ -15,7 +15,6 @@ import {
DURATION_TOTAL_TIME_NO_DATA, DURATION_TOTAL_TIME_NO_DATA,
DURATION_TOTAL_TIME_LABEL, DURATION_TOTAL_TIME_LABEL,
} from '../constants'; } from '../constants';
import StageDropdownFilter from './stage_dropdown_filter.vue';
export default { export default {
name: 'DurationChart', name: 'DurationChart',
...@@ -23,7 +22,6 @@ export default { ...@@ -23,7 +22,6 @@ export default {
GlAlert, GlAlert,
GlIcon, GlIcon,
Scatterplot, Scatterplot,
StageDropdownFilter,
ChartSkeletonLoader, ChartSkeletonLoader,
}, },
directives: { directives: {
...@@ -64,12 +62,6 @@ export default { ...@@ -64,12 +62,6 @@ export default {
: DURATION_STAGE_TIME_DESCRIPTION; : DURATION_STAGE_TIME_DESCRIPTION;
}, },
}, },
methods: {
...mapActions('durationChart', ['updateSelectedDurationChartStages']),
onDurationStageSelect(stages) {
this.updateSelectedDurationChartStages(stages);
},
},
durationChartTooltipDateFormat: dateFormats.defaultDate, durationChartTooltipDateFormat: dateFormats.defaultDate,
medianAdditionalOptions: { medianAdditionalOptions: {
lineStyle: { lineStyle: {
...@@ -85,12 +77,6 @@ export default { ...@@ -85,12 +77,6 @@ export default {
<h4 class="gl-mt-0"> <h4 class="gl-mt-0">
{{ title }}&nbsp;<gl-icon v-gl-tooltip.hover name="information-o" :title="tooltipText" /> {{ title }}&nbsp;<gl-icon v-gl-tooltip.hover name="information-o" :title="tooltipText" />
</h4> </h4>
<stage-dropdown-filter
v-if="isOverviewStageSelected && stages.length"
class="gl-ml-auto"
:stages="stages"
@selected="onDurationStageSelect"
/>
<scatterplot <scatterplot
v-if="hasData" v-if="hasData"
:x-axis-title="s__('CycleAnalytics|Date')" :x-axis-title="s__('CycleAnalytics|Date')"
......
<script>
import { GlDropdown, GlDropdownSectionHeader, GlDropdownItem } from '@gitlab/ui';
import { sprintf, s__ } from '~/locale';
export default {
name: 'StageDropdownFilter',
components: {
GlDropdown,
GlDropdownSectionHeader,
GlDropdownItem,
},
props: {
stages: {
type: Array,
required: true,
},
label: {
type: String,
required: false,
default: s__('CycleAnalytics|stage dropdown'),
},
},
data() {
return {
selectedStages: this.stages,
};
},
computed: {
selectedStagesLabel() {
const { stages, selectedStages } = this;
if (selectedStages.length === 1) {
return selectedStages[0].title;
} else if (selectedStages.length === stages.length) {
return s__('CycleAnalytics|All stages');
} else if (selectedStages.length > 1) {
return sprintf(s__('CycleAnalytics|%{stageCount} stages selected'), {
stageCount: selectedStages.length,
});
}
return s__('CycleAnalytics|No stages selected');
},
},
methods: {
isStageSelected(stageId) {
return this.selectedStages.some(({ id }) => id === stageId);
},
onClick({ stage, isMarking }) {
this.selectedStages = isMarking
? this.selectedStages.filter((s) => s.id !== stage.id)
: this.selectedStages.concat([stage]);
this.$emit('selected', this.selectedStages);
},
},
};
</script>
<template>
<gl-dropdown
ref="stagesDropdown"
class="js-dropdown-stages"
toggle-class="gl-shadow-none"
:text="selectedStagesLabel"
right
>
<gl-dropdown-section-header>{{ s__('CycleAnalytics|Stages') }}</gl-dropdown-section-header>
<gl-dropdown-item
v-for="stage in stages"
:key="stage.id"
:active="isStageSelected(stage.id)"
:is-check-item="true"
:is-checked="isStageSelected(stage.id)"
@click="onClick({ stage, isMarking: isStageSelected(stage.id) })"
>
{{ stage.title }}
</gl-dropdown-item>
</gl-dropdown>
</template>
...@@ -40,25 +40,3 @@ export const fetchDurationData = ({ dispatch, commit, rootGetters }) => { ...@@ -40,25 +40,3 @@ export const fetchDurationData = ({ dispatch, commit, rootGetters }) => {
.then((data) => commit(types.RECEIVE_DURATION_DATA_SUCCESS, data)) .then((data) => commit(types.RECEIVE_DURATION_DATA_SUCCESS, data))
.catch((error) => dispatch('receiveDurationDataError', error)); .catch((error) => dispatch('receiveDurationDataError', error));
}; };
export const updateSelectedDurationChartStages = ({ state, commit }, stages) => {
const setSelectedPropertyOnStages = (data) =>
data.map((stage) => {
const selected = stages.reduce((result, object) => {
if (object.id === stage.id) return true;
return result;
}, false);
return {
...stage,
selected,
};
});
const { durationData } = state;
const updatedDurationStageData = setSelectedPropertyOnStages(durationData);
commit(types.UPDATE_SELECTED_DURATION_CHART_STAGES, {
updatedDurationStageData,
});
};
...@@ -5,7 +5,7 @@ export const durationChartPlottableData = (state, _, rootState, rootGetters) => ...@@ -5,7 +5,7 @@ export const durationChartPlottableData = (state, _, rootState, rootGetters) =>
const { durationData } = state; const { durationData } = state;
const { isOverviewStageSelected } = rootGetters; const { isOverviewStageSelected } = rootGetters;
const selectedStagesDurationData = isOverviewStageSelected const selectedStagesDurationData = isOverviewStageSelected
? durationData.filter((stage) => stage.selected) ? durationData
: durationData.filter((stage) => stage.id === selectedStage.id); : durationData.filter((stage) => stage.id === selectedStage.id);
const plottableData = getDurationChartData( const plottableData = getDurationChartData(
selectedStagesDurationData, selectedStagesDurationData,
......
export const SET_LOADING = 'SET_LOADING'; export const SET_LOADING = 'SET_LOADING';
export const UPDATE_SELECTED_DURATION_CHART_STAGES = 'UPDATE_SELECTED_DURATION_CHART_STAGES';
export const REQUEST_DURATION_DATA = 'REQUEST_DURATION_DATA'; export const REQUEST_DURATION_DATA = 'REQUEST_DURATION_DATA';
export const RECEIVE_DURATION_DATA_SUCCESS = 'RECEIVE_DURATION_DATA_SUCCESS'; export const RECEIVE_DURATION_DATA_SUCCESS = 'RECEIVE_DURATION_DATA_SUCCESS';
export const RECEIVE_DURATION_DATA_ERROR = 'RECEIVE_DURATION_DATA_ERROR'; export const RECEIVE_DURATION_DATA_ERROR = 'RECEIVE_DURATION_DATA_ERROR';
...@@ -4,9 +4,6 @@ export default { ...@@ -4,9 +4,6 @@ export default {
[types.SET_LOADING](state, loading) { [types.SET_LOADING](state, loading) {
state.isLoading = loading; state.isLoading = loading;
}, },
[types.UPDATE_SELECTED_DURATION_CHART_STAGES](state, { updatedDurationStageData }) {
state.durationData = updatedDurationStageData;
},
[types.REQUEST_DURATION_DATA](state) { [types.REQUEST_DURATION_DATA](state) {
state.isLoading = true; state.isLoading = true;
state.errorCode = null; state.errorCode = null;
......
...@@ -32,63 +32,29 @@ RSpec.describe 'Value stream analytics charts', :js do ...@@ -32,63 +32,29 @@ RSpec.describe 'Value stream analytics charts', :js do
sign_in(user) sign_in(user)
end end
shared_examples 'has all the default stages' do
it 'has all the default stages in the duration dropdown' do
toggle_duration_chart_dropdown
expect(duration_chart_stages).to eq(translated_default_stage_names + [latest_custom_stage_name])
end
end
context 'Duration chart' do context 'Duration chart' do
duration_stage_selector = '.js-dropdown-stages'
let(:duration_chart_dropdown) { page.find(duration_stage_selector) }
let(:custom_value_stream_name) { "New created value stream" } let(:custom_value_stream_name) { "New created value stream" }
let_it_be(:translated_default_stage_names) do
Gitlab::Analytics::CycleAnalytics::DefaultStages.names.map do |name|
stage = Analytics::CycleAnalytics::GroupStage.new(name: name)
Analytics::CycleAnalytics::StagePresenter.new(stage).title
end.freeze
end
def duration_chart_stages
duration_chart_dropdown.all('.dropdown-item').collect(&:text)
end
def toggle_duration_chart_dropdown
duration_chart_dropdown.click
end
def hide_vsa_stage(index = 0)
page.find_button(_('Edit')).click
page.find("[data-testid='stage-action-hide-#{index}']").click
click_save_value_stream_button
wait_for_requests
end
def latest_custom_stage_name
index = duration_chart_stages.length
"Cool custom stage - name #{index}"
end
before do before do
select_group(group) select_group(group)
create_custom_value_stream(custom_value_stream_name) create_custom_value_stream(custom_value_stream_name)
end end
it_behaves_like 'has all the default stages' it 'displays data for all stages on the overview' do
page.within('[data-testid="vsa-path-navigation"]') do
click_button "Overview"
end
it 'hidden stages will not appear in the duration chart dropdown' do expect(page).to have_text("Total time")
first_stage_name = duration_chart_stages.first end
hide_vsa_stage it 'displays data for a specific stage when selected' do
toggle_duration_chart_dropdown page.within('[data-testid="vsa-path-navigation"]') do
click_button "Issue"
end
expect(duration_chart_stages).not_to include(first_stage_name) expect(page).to have_text("Stage time: Issue")
end end
end end
......
...@@ -17,12 +17,6 @@ exports[`DurationChart with the overiew stage selected renders the duration char ...@@ -17,12 +17,6 @@ exports[`DurationChart with the overiew stage selected renders the duration char
/> />
</h4> </h4>
<stagedropdownfilter-stub
class="gl-ml-auto"
label="stage dropdown"
stages="[object Object],[object Object],[object Object]"
/>
<scatterplot-stub <scatterplot-stub
medianlinedata="2019-01-01,17,2019-01-01,2019-01-02,40,2019-01-02" medianlinedata="2019-01-01,17,2019-01-01,2019-01-02,40,2019-01-02"
medianlineoptions="[object Object]" medianlineoptions="[object Object]"
......
import { GlDropdownItem, GlIcon } from '@gitlab/ui'; import { GlIcon } from '@gitlab/ui';
import { shallowMount, mount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import Vue from 'vue'; import Vue from 'vue';
import Vuex from 'vuex'; import Vuex from 'vuex';
import { import {
...@@ -9,7 +9,6 @@ import { ...@@ -9,7 +9,6 @@ import {
DURATION_TOTAL_TIME_NO_DATA, DURATION_TOTAL_TIME_NO_DATA,
} from 'ee/analytics/cycle_analytics/constants'; } from 'ee/analytics/cycle_analytics/constants';
import DurationChart from 'ee/analytics/cycle_analytics/components/duration_chart.vue'; import DurationChart from 'ee/analytics/cycle_analytics/components/duration_chart.vue';
import StageDropdownFilter from 'ee/analytics/cycle_analytics/components/stage_dropdown_filter.vue';
import Scatterplot from 'ee/analytics/shared/components/scatterplot.vue'; import Scatterplot from 'ee/analytics/shared/components/scatterplot.vue';
import ChartSkeletonLoader from '~/vue_shared/components/resizable_chart/skeleton_loader.vue'; import ChartSkeletonLoader from '~/vue_shared/components/resizable_chart/skeleton_loader.vue';
import { allowedStages as stages, durationChartPlottableData as durationData } from '../mock_data'; import { allowedStages as stages, durationChartPlottableData as durationData } from '../mock_data';
...@@ -18,7 +17,6 @@ Vue.use(Vuex); ...@@ -18,7 +17,6 @@ Vue.use(Vuex);
const actionSpies = { const actionSpies = {
fetchDurationData: jest.fn(), fetchDurationData: jest.fn(),
updateSelectedDurationChartStages: jest.fn(),
}; };
const fakeStore = ({ initialGetters, initialState, rootGetters, rootState }) => const fakeStore = ({ initialGetters, initialState, rootGetters, rootState }) =>
...@@ -47,7 +45,6 @@ const fakeStore = ({ initialGetters, initialState, rootGetters, rootState }) => ...@@ -47,7 +45,6 @@ const fakeStore = ({ initialGetters, initialState, rootGetters, rootState }) =>
}); });
function createComponent({ function createComponent({
mountFn = shallowMount,
stubs = {}, stubs = {},
initialState = {}, initialState = {},
initialGetters = {}, initialGetters = {},
...@@ -55,7 +52,7 @@ function createComponent({ ...@@ -55,7 +52,7 @@ function createComponent({
rootState = {}, rootState = {},
props = {}, props = {},
} = {}) { } = {}) {
return mountFn(DurationChart, { return shallowMount(DurationChart, {
store: fakeStore({ initialState, initialGetters, rootGetters, rootState }), store: fakeStore({ initialState, initialGetters, rootGetters, rootState }),
propsData: { propsData: {
stages, stages,
...@@ -64,7 +61,6 @@ function createComponent({ ...@@ -64,7 +61,6 @@ function createComponent({
stubs: { stubs: {
ChartSkeletonLoader: true, ChartSkeletonLoader: true,
Scatterplot: true, Scatterplot: true,
StageDropdownFilter: true,
...stubs, ...stubs,
}, },
}); });
...@@ -76,13 +72,8 @@ describe('DurationChart', () => { ...@@ -76,13 +72,8 @@ describe('DurationChart', () => {
const findContainer = (_wrapper) => _wrapper.find('[data-testid="vsa-duration-chart"]'); const findContainer = (_wrapper) => _wrapper.find('[data-testid="vsa-duration-chart"]');
const findChartDescription = (_wrapper) => _wrapper.findComponent(GlIcon); const findChartDescription = (_wrapper) => _wrapper.findComponent(GlIcon);
const findScatterPlot = (_wrapper) => _wrapper.findComponent(Scatterplot); const findScatterPlot = (_wrapper) => _wrapper.findComponent(Scatterplot);
const findStageDropdown = (_wrapper) => _wrapper.findComponent(StageDropdownFilter);
const findLoader = (_wrapper) => _wrapper.findComponent(ChartSkeletonLoader); const findLoader = (_wrapper) => _wrapper.findComponent(ChartSkeletonLoader);
const selectStage = (_wrapper, index = 0) => {
findStageDropdown(_wrapper).findAllComponents(GlDropdownItem).at(index).vm.$emit('click');
};
afterEach(() => { afterEach(() => {
wrapper.destroy(); wrapper.destroy();
wrapper = null; wrapper = null;
...@@ -101,10 +92,6 @@ describe('DurationChart', () => { ...@@ -101,10 +92,6 @@ describe('DurationChart', () => {
expect(findScatterPlot(wrapper).exists()).toBe(true); expect(findScatterPlot(wrapper).exists()).toBe(true);
}); });
it('renders the stage dropdown', () => {
expect(findStageDropdown(wrapper).exists()).toBe(true);
});
it('renders the chart description', () => { it('renders the chart description', () => {
expect(findChartDescription(wrapper).attributes('title')).toBe( expect(findChartDescription(wrapper).attributes('title')).toBe(
DURATION_TOTAL_TIME_DESCRIPTION, DURATION_TOTAL_TIME_DESCRIPTION,
...@@ -126,22 +113,6 @@ describe('DurationChart', () => { ...@@ -126,22 +113,6 @@ describe('DurationChart', () => {
}); });
}); });
describe('when a stage is selected', () => {
const selectedIndex = 1;
const selectedStages = stages.filter((_, index) => index !== selectedIndex);
beforeEach(() => {
wrapper = createComponent({ stubs: { StageDropdownFilter } });
selectStage(wrapper, selectedIndex);
});
it('calls the `updateSelectedDurationChartStages` action', () => {
expect(actionSpies.updateSelectedDurationChartStages).toHaveBeenCalledWith(
expect.any(Object),
selectedStages,
);
});
});
describe('with a value stream stage selected', () => { describe('with a value stream stage selected', () => {
const [selectedStage] = stages; const [selectedStage] = stages;
...@@ -160,10 +131,6 @@ describe('DurationChart', () => { ...@@ -160,10 +131,6 @@ describe('DurationChart', () => {
expect(findScatterPlot(wrapper).exists()).toBe(true); expect(findScatterPlot(wrapper).exists()).toBe(true);
}); });
it('does not render the stage dropdown', () => {
expect(findStageDropdown(wrapper).exists()).toBe(false);
});
it('renders the stage title', () => { it('renders the stage title', () => {
expect(wrapper.text()).toContain(`Stage time: ${selectedStage.title}`); expect(wrapper.text()).toContain(`Stage time: ${selectedStage.title}`);
}); });
...@@ -203,20 +170,6 @@ describe('DurationChart', () => { ...@@ -203,20 +170,6 @@ describe('DurationChart', () => {
}); });
}); });
describe('with no stages', () => {
beforeEach(() => {
wrapper = createComponent({
mountFn: mount,
props: { stages: [] },
stubs: { StageDropdownFilter: false },
});
});
it('does not render the stage dropdown', () => {
expect(findStageDropdown(wrapper).exists()).toBe(false);
});
});
describe('when isLoading=true', () => { describe('when isLoading=true', () => {
beforeEach(() => { beforeEach(() => {
wrapper = createComponent({ initialState: { isLoading: true } }); wrapper = createComponent({ initialState: { isLoading: true } });
......
import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import StageDropdownFilter from 'ee/analytics/cycle_analytics/components/stage_dropdown_filter.vue';
const stages = [
{
id: 1,
title: 'Issue',
},
{
id: 2,
title: 'Plan',
},
{
id: 3,
title: 'Code',
},
];
describe('StageDropdownFilter component', () => {
let wrapper;
const createComponent = () => {
wrapper = shallowMount(StageDropdownFilter, {
propsData: {
stages,
},
});
};
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
beforeEach(() => {
createComponent();
});
const findDropdown = () => wrapper.findComponent(GlDropdown);
const selectDropdownItemAtIndex = (index) =>
findDropdown().findAllComponents(GlDropdownItem).at(index).vm.$emit('click');
describe('on stage click', () => {
describe('clicking a selected stage', () => {
it('should remove from selection', () => {
selectDropdownItemAtIndex(0);
expect(wrapper.emitted().selected).toEqual([[[stages[1], stages[2]]]]);
});
});
describe('clicking a deselected stage', () => {
beforeEach(() => {
selectDropdownItemAtIndex(0);
});
it('should add to selection', () => {
selectDropdownItemAtIndex(0);
expect(wrapper.emitted().selected).toEqual([
[[stages[1], stages[2]]],
[[stages[1], stages[2], stages[0]]],
]);
});
});
});
});
...@@ -192,79 +192,4 @@ describe('DurationChart actions', () => { ...@@ -192,79 +192,4 @@ describe('DurationChart actions', () => {
}); });
}); });
}); });
describe('updateSelectedDurationChartStages', () => {
it("commits the 'UPDATE_SELECTED_DURATION_CHART_STAGES' mutation with all the selected stages in the duration data", () => {
const stateWithDurationData = {
...state,
durationData: transformedDurationData,
};
testAction(
actions.updateSelectedDurationChartStages,
activeStages,
stateWithDurationData,
[
{
type: types.UPDATE_SELECTED_DURATION_CHART_STAGES,
payload: {
updatedDurationStageData: transformedDurationData,
},
},
],
[],
);
});
it("commits the 'UPDATE_SELECTED_DURATION_CHART_STAGES' mutation with all the selected and deselected stages in the duration data", () => {
const stateWithDurationData = {
...state,
durationData: transformedDurationData,
};
testAction(
actions.updateSelectedDurationChartStages,
[activeStages[0], activeStages[1]],
stateWithDurationData,
[
{
type: types.UPDATE_SELECTED_DURATION_CHART_STAGES,
payload: {
updatedDurationStageData: [
transformedDurationData[0],
transformedDurationData[1],
{ ...transformedDurationData[2], selected: false },
],
},
},
],
[],
);
});
it("commits the 'UPDATE_SELECTED_DURATION_CHART_STAGES' mutation with all deselected stages in the duration data", () => {
const stateWithDurationData = {
...state,
durationData: transformedDurationData,
};
testAction(
actions.updateSelectedDurationChartStages,
[],
stateWithDurationData,
[
{
type: types.UPDATE_SELECTED_DURATION_CHART_STAGES,
payload: {
updatedDurationStageData: transformedDurationData.map((d) => ({
...d,
selected: false,
})),
},
},
],
[],
);
});
});
}); });
...@@ -25,9 +25,8 @@ describe('DurationChart mutations', () => { ...@@ -25,9 +25,8 @@ describe('DurationChart mutations', () => {
}); });
it.each` it.each`
mutation | payload | expectedState mutation | payload | expectedState
${types.UPDATE_SELECTED_DURATION_CHART_STAGES} | ${{ updatedDurationStageData: transformedDurationData }} | ${{ durationData: transformedDurationData }} ${types.SET_LOADING} | ${true} | ${{ isLoading: true }}
${types.SET_LOADING} | ${true} | ${{ isLoading: true }}
`( `(
'$mutation with payload $payload will update state with $expectedState', '$mutation with payload $payload will update state with $expectedState',
({ mutation, payload, expectedState }) => { ({ mutation, payload, expectedState }) => {
......
...@@ -10868,12 +10868,6 @@ msgstr "" ...@@ -10868,12 +10868,6 @@ msgstr ""
msgid "CycleAnalytics|%{selectedLabelsCount} selected (%{maxLabels} max)" msgid "CycleAnalytics|%{selectedLabelsCount} selected (%{maxLabels} max)"
msgstr "" msgstr ""
msgid "CycleAnalytics|%{stageCount} stages selected"
msgstr ""
msgid "CycleAnalytics|All stages"
msgstr ""
msgid "CycleAnalytics|Average time to completion" msgid "CycleAnalytics|Average time to completion"
msgstr "" msgstr ""
...@@ -10886,9 +10880,6 @@ msgstr "" ...@@ -10886,9 +10880,6 @@ msgstr ""
msgid "CycleAnalytics|Lead Time for Changes" msgid "CycleAnalytics|Lead Time for Changes"
msgstr "" msgstr ""
msgid "CycleAnalytics|No stages selected"
msgstr ""
msgid "CycleAnalytics|Number of tasks" msgid "CycleAnalytics|Number of tasks"
msgstr "" msgstr ""
...@@ -10920,9 +10911,6 @@ msgstr "" ...@@ -10920,9 +10911,6 @@ msgstr ""
msgid "CycleAnalytics|Stage time: %{title}" msgid "CycleAnalytics|Stage time: %{title}"
msgstr "" msgstr ""
msgid "CycleAnalytics|Stages"
msgstr ""
msgid "CycleAnalytics|Tasks by type" msgid "CycleAnalytics|Tasks by type"
msgstr "" msgstr ""
...@@ -10956,9 +10944,6 @@ msgstr "" ...@@ -10956,9 +10944,6 @@ msgstr ""
msgid "CycleAnalytics|project dropdown filter" msgid "CycleAnalytics|project dropdown filter"
msgstr "" msgstr ""
msgid "CycleAnalytics|stage dropdown"
msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs." msgid "DAG visualization requires at least 3 dependent jobs."
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