Commit f23ed8d9 authored by Andrew Fontaine's avatar Andrew Fontaine

Merge branch '298930-ff-and-basic-toggle' into 'master'

Add dropdown and feature flag [RUN ALL RSPEC] [RUN AS-IF-FOSS]

See merge request gitlab-org/gitlab!56865
parents d50d836e 67fbe9e5
......@@ -10,3 +10,6 @@ export const ONE_COL_WIDTH = 180;
export const REST = 'rest';
export const GRAPHQL = 'graphql';
export const STAGE_VIEW = 'stage';
export const LAYER_VIEW = 'layer';
......@@ -2,8 +2,11 @@
import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
import getPipelineDetails from 'shared_queries/pipelines/get_pipeline_details.query.graphql';
import { __ } from '~/locale';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { DEFAULT, DRAW_FAILURE, LOAD_FAILURE } from '../../constants';
import { STAGE_VIEW } from './constants';
import PipelineGraph from './graph_component.vue';
import GraphViewSelector from './graph_view_selector.vue';
import {
getQueryHeaders,
reportToSentry,
......@@ -17,8 +20,10 @@ export default {
components: {
GlAlert,
GlLoadingIcon,
GraphViewSelector,
PipelineGraph,
},
mixins: [glFeatureFlagMixin()],
inject: {
graphqlResourceEtag: {
default: '',
......@@ -35,8 +40,9 @@ export default {
},
data() {
return {
pipeline: null,
alertType: null,
currentViewType: STAGE_VIEW,
pipeline: null,
showAlert: false,
};
},
......@@ -147,6 +153,9 @@ export default {
}
},
/* eslint-enable @gitlab/require-i18n-strings */
updateViewType(type) {
this.currentViewType = type;
},
},
};
</script>
......@@ -155,6 +164,11 @@ export default {
<gl-alert v-if="showAlert" :variant="alert.variant" @dismiss="hideAlert">
{{ alert.text }}
</gl-alert>
<graph-view-selector
v-if="glFeatures.pipelineGraphLayersView"
:type="currentViewType"
@updateViewType="updateViewType"
/>
<gl-loading-icon v-if="showLoadingIcon" class="gl-mx-auto gl-my-4" size="lg" />
<pipeline-graph
v-if="pipeline"
......
<script>
import { GlDropdown, GlDropdownItem, GlIcon, GlSprintf } from '@gitlab/ui';
import { __ } from '~/locale';
import { STAGE_VIEW, LAYER_VIEW } from './constants';
export default {
name: 'GraphViewSelector',
components: {
GlDropdown,
GlDropdownItem,
GlIcon,
GlSprintf,
},
props: {
type: {
type: String,
required: true,
},
},
data() {
return {
currentViewType: STAGE_VIEW,
};
},
i18n: {
labelText: __('Order jobs by'),
},
views: {
[STAGE_VIEW]: {
type: STAGE_VIEW,
text: {
primary: __('Stage'),
secondary: __('View the jobs grouped into stages'),
},
},
[LAYER_VIEW]: {
type: LAYER_VIEW,
text: {
primary: __('%{codeStart}needs:%{codeEnd} relationships'),
secondary: __('View what jobs are needed for a job to run'),
},
},
},
computed: {
currentDropdownText() {
return this.$options.views[this.type].text.primary;
},
},
methods: {
itemClick(type) {
this.$emit('updateViewType', type);
},
},
};
</script>
<template>
<div class="gl-display-flex gl-justify-content-end gl-align-items-center gl-my-4">
<span>{{ $options.i18n.labelText }}</span>
<gl-dropdown class="gl-ml-4" :right="true">
<template #button-content>
<gl-sprintf :message="currentDropdownText">
<template #code="{ content }">
<code> {{ content }} </code>
</template>
</gl-sprintf>
<gl-icon class="gl-px-2" name="angle-down" :size="18" />
</template>
<gl-dropdown-item
v-for="view in $options.views"
:key="view.type"
:secondary-text="view.text.secondary"
@click="itemClick(view.type)"
>
<b>
<gl-sprintf :message="view.text.primary">
<template #code="{ content }">
<code> {{ content }} </code>
</template>
</gl-sprintf>
</b>
</gl-dropdown-item>
</gl-dropdown>
</div>
</template>
......@@ -14,6 +14,7 @@ class Projects::PipelinesController < Projects::ApplicationController
before_action :authorize_update_pipeline!, only: [:retry, :cancel]
before_action do
push_frontend_feature_flag(:new_pipeline_form, project, default_enabled: :yaml)
push_frontend_feature_flag(:pipeline_graph_layers_view, project, type: :development, default_enabled: :yaml)
push_frontend_feature_flag(:graphql_pipeline_details, project, type: :development, default_enabled: :yaml)
push_frontend_feature_flag(:graphql_pipeline_details_users, current_user, type: :development, default_enabled: :yaml)
push_frontend_feature_flag(:jira_for_vulnerabilities, project, type: :development, default_enabled: :yaml)
......
---
name: pipeline_graph_layers_view
introduced_by_url:
rollout_issue_url:
milestone: '13.11'
type: development
group: group::pipeline authoring
default_enabled: false
......@@ -402,6 +402,9 @@ msgstr ""
msgid "%{board_target} not found"
msgstr ""
msgid "%{codeStart}needs:%{codeEnd} relationships"
msgstr ""
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
msgstr ""
......@@ -21684,6 +21687,9 @@ msgstr ""
msgid "Or you can choose one of the suggested colors below"
msgstr ""
msgid "Order jobs by"
msgstr ""
msgid "Orphaned member"
msgstr ""
......@@ -33507,6 +33513,9 @@ msgstr ""
msgid "View the documentation"
msgstr ""
msgid "View the jobs grouped into stages"
msgstr ""
msgid "View the latest successful deployment to this environment"
msgstr ""
......@@ -33516,6 +33525,9 @@ msgstr ""
msgid "View users statistics"
msgstr ""
msgid "View what jobs are needed for a job to run"
msgstr ""
msgid "Viewed"
msgstr ""
......
......@@ -6,6 +6,7 @@ import createMockApollo from 'helpers/mock_apollo_helper';
import getPipelineDetails from 'shared_queries/pipelines/get_pipeline_details.query.graphql';
import PipelineGraph from '~/pipelines/components/graph/graph_component.vue';
import PipelineGraphWrapper from '~/pipelines/components/graph/graph_component_wrapper.vue';
import GraphViewSelector from '~/pipelines/components/graph/graph_view_selector.vue';
import { mockPipelineResponse } from './mock_data';
const defaultProvide = {
......@@ -22,15 +23,19 @@ describe('Pipeline graph wrapper', () => {
const getAlert = () => wrapper.find(GlAlert);
const getLoadingIcon = () => wrapper.find(GlLoadingIcon);
const getGraph = () => wrapper.find(PipelineGraph);
const getViewSelector = () => wrapper.find(GraphViewSelector);
const createComponent = ({
apolloProvider,
data = {},
provide = defaultProvide,
provide = {},
mountFn = shallowMount,
} = {}) => {
wrapper = mountFn(PipelineGraphWrapper, {
provide,
provide: {
...defaultProvide,
...provide,
},
apolloProvider,
data() {
return {
......@@ -40,13 +45,14 @@ describe('Pipeline graph wrapper', () => {
});
};
const createComponentWithApollo = (
const createComponentWithApollo = ({
getPipelineDetailsHandler = jest.fn().mockResolvedValue(mockPipelineResponse),
) => {
provide = {},
} = {}) => {
const requestHandlers = [[getPipelineDetails, getPipelineDetailsHandler]];
const apolloProvider = createMockApollo(requestHandlers);
createComponent({ apolloProvider });
createComponent({ apolloProvider, provide });
};
afterEach(() => {
......@@ -100,7 +106,9 @@ describe('Pipeline graph wrapper', () => {
describe('when there is an error', () => {
beforeEach(async () => {
createComponentWithApollo(jest.fn().mockRejectedValue(new Error('GraphQL error')));
createComponentWithApollo({
getPipelineDetailsHandler: jest.fn().mockRejectedValue(new Error('GraphQL error')),
});
jest.runOnlyPendingTimers();
await wrapper.vm.$nextTick();
});
......@@ -154,7 +162,7 @@ describe('Pipeline graph wrapper', () => {
.mockResolvedValueOnce(mockPipelineResponse)
.mockResolvedValueOnce(errorData);
createComponentWithApollo(failSucceedFail);
createComponentWithApollo({ getPipelineDetailsHandler: failSucceedFail });
await wrapper.vm.$nextTick();
});
......@@ -174,4 +182,37 @@ describe('Pipeline graph wrapper', () => {
expect(getGraph().exists()).toBe(true);
});
});
describe('view dropdown', () => {
describe('when feature flag is off', () => {
beforeEach(async () => {
createComponentWithApollo();
jest.runOnlyPendingTimers();
await wrapper.vm.$nextTick();
});
it('does not appear', () => {
expect(getViewSelector().exists()).toBe(false);
});
});
describe('when feature flag is on', () => {
beforeEach(async () => {
createComponentWithApollo({
provide: {
glFeatures: {
pipelineGraphLayersView: true,
},
},
});
jest.runOnlyPendingTimers();
await wrapper.vm.$nextTick();
});
it('appears', () => {
expect(getViewSelector().exists()).toBe(true);
});
});
});
});
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