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