Commit 8b4ab25c authored by Kushal Pandya's avatar Kushal Pandya

Merge branch 'afontaine/deployment-empty-state' into 'master'

Add empty state for environments

See merge request gitlab-org/gitlab!78908
parents ba765c13 6fefe1cc
......@@ -4,9 +4,10 @@ import {
GlDropdown,
GlButton,
GlLink,
GlSprintf,
GlTooltipDirective as GlTooltip,
} from '@gitlab/ui';
import { __ } from '~/locale';
import { __, s__ } from '~/locale';
import { truncate } from '~/lib/utils/text_utility';
import isLastDeployment from '../graphql/queries/is_last_deployment.query.graphql';
import ExternalUrl from './environment_external_url.vue';
......@@ -25,6 +26,7 @@ export default {
GlDropdown,
GlButton,
GlLink,
GlSprintf,
Actions,
Deployment,
ExternalUrl,
......@@ -38,6 +40,7 @@ export default {
directives: {
GlTooltip,
},
inject: ['helpPagePath'],
props: {
environment: {
required: true,
......@@ -60,6 +63,9 @@ export default {
i18n: {
collapse: __('Collapse'),
expand: __('Expand'),
emptyState: s__(
'Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}',
),
},
data() {
return { visible: false };
......@@ -83,6 +89,9 @@ export default {
upcomingDeployment() {
return this.environment?.upcomingDeployment;
},
hasDeployment() {
return Boolean(this.environment?.upcomingDeployment || this.environment?.lastDeployment);
},
actions() {
if (!this.lastDeployment) {
return [];
......@@ -254,20 +263,29 @@ export default {
</div>
</div>
<gl-collapse :visible="visible">
<div v-if="lastDeployment" :class="$options.deploymentClasses">
<deployment
:deployment="lastDeployment"
:class="{ 'gl-ml-7': inFolder }"
latest
class="gl-pl-4"
/>
</div>
<div v-if="upcomingDeployment" :class="$options.deploymentClasses">
<deployment
:deployment="upcomingDeployment"
:class="{ 'gl-ml-7': inFolder }"
class="gl-pl-4"
/>
<template v-if="hasDeployment">
<div v-if="lastDeployment" :class="$options.deploymentClasses">
<deployment
:deployment="lastDeployment"
:class="{ 'gl-ml-7': inFolder }"
latest
class="gl-pl-4"
/>
</div>
<div v-if="upcomingDeployment" :class="$options.deploymentClasses">
<deployment
:deployment="upcomingDeployment"
:class="{ 'gl-ml-7': inFolder }"
class="gl-pl-4"
/>
</div>
</template>
<div v-else :class="$options.deploymentClasses">
<gl-sprintf :message="$options.i18n.emptyState">
<template #link="{ content }">
<gl-link :href="helpPagePath">{{ content }}</gl-link>
</template>
</gl-sprintf>
</div>
</gl-collapse>
</div>
......
......@@ -13728,6 +13728,9 @@ msgstr ""
msgid "Environments|Stopping %{environmentName}"
msgstr ""
msgid "Environments|There are no deployments for this environment yet. %{linkStart}Learn more about setting up deployments.%{linkEnd}"
msgstr ""
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr ""
......
......@@ -32,6 +32,7 @@ describe('~/environments/components/new_environments_folder.vue', () => {
apolloProvider,
propsData,
stubs: { transition: stubTransition() },
provide: { helpPagePath: '/help' },
});
beforeEach(async () => {
......
......@@ -2,7 +2,7 @@ import VueApollo from 'vue-apollo';
import Vue from 'vue';
import { GlCollapse, GlIcon } from '@gitlab/ui';
import createMockApollo from 'helpers/mock_apollo_helper';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import { mountExtended, extendedWrapper } from 'helpers/vue_test_utils_helper';
import { stubTransition } from 'helpers/stub_transition';
import { __, s__ } from '~/locale';
import EnvironmentItem from '~/environments/components/new_environment_item.vue';
......@@ -22,11 +22,19 @@ describe('~/environments/components/new_environment_item.vue', () => {
mountExtended(EnvironmentItem, {
apolloProvider,
propsData: { environment: resolvedEnvironment, ...propsData },
provide: { helpPagePath: '/help' },
stubs: { transition: stubTransition() },
});
const findDeployment = () => wrapper.findComponent(Deployment);
const expandCollapsedSection = async () => {
const button = wrapper.findByRole('button', { name: __('Expand') });
await button.trigger('click');
return button;
};
afterEach(() => {
wrapper?.destroy();
});
......@@ -258,14 +266,12 @@ describe('~/environments/components/new_environment_item.vue', () => {
describe('collapse', () => {
let icon;
let collapse;
let button;
let environmentName;
beforeEach(() => {
wrapper = createWrapper({ apolloProvider: createApolloProvider() });
collapse = wrapper.findComponent(GlCollapse);
icon = wrapper.findComponent(GlIcon);
button = wrapper.findByRole('button', { name: __('Expand') });
environmentName = wrapper.findByText(resolvedEnvironment.name);
});
......@@ -278,7 +284,7 @@ describe('~/environments/components/new_environment_item.vue', () => {
it('opens on click', async () => {
expect(findDeployment().isVisible()).toBe(false);
await button.trigger('click');
const button = await expandCollapsedSection();
expect(button.attributes('aria-label')).toBe(__('Collapse'));
expect(collapse.attributes('visible')).toBe('visible');
......@@ -338,4 +344,47 @@ describe('~/environments/components/new_environment_item.vue', () => {
expect(deployment.exists()).toBe(false);
});
});
describe('empty state', () => {
it('should link to documentation', async () => {
const environment = {
...resolvedEnvironment,
lastDeployment: null,
upcomingDeployment: null,
};
wrapper = createWrapper({
propsData: { environment },
apolloProvider: createApolloProvider(),
});
await expandCollapsedSection();
const text = s__(
'Environments|There are no deployments for this environment yet. Learn more about setting up deployments.',
);
const emptyState = wrapper.findByText((_content, element) => element.textContent === text);
const link = extendedWrapper(emptyState).findByRole('link');
expect(link.attributes('href')).toBe('/help');
});
it('should not link to the documentation when there are deployments', async () => {
wrapper = createWrapper({
apolloProvider: createApolloProvider(),
});
await expandCollapsedSection();
const text = s__(
'Environments|There are no deployments for this environment yet. Learn more about setting up deployments.',
);
const emptyState = wrapper.findByText((_content, element) => element.textContent === text);
expect(emptyState.exists()).toBe(false);
});
});
});
......@@ -40,6 +40,7 @@ describe('~/environments/components/new_environments_app.vue', () => {
newEnvironmentPath: '/environments/new',
canCreateEnvironment: true,
defaultBranchName: 'main',
helpPagePath: '/help',
...provide,
},
apolloProvider,
......
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