Commit 7257b683 authored by anna_vovchenko's avatar anna_vovchenko

Implemented the suggestions after UX review

- changed alert to banner
- made the banner dismissable using LocalStorageSync
- changed copy
parent f4bb6c4e
<script> <script>
import { GlAlert, GlKeysetPagination, GlLoadingIcon, GlSprintf, GlLink } from '@gitlab/ui'; import { GlAlert, GlKeysetPagination, GlLoadingIcon, GlBanner } from '@gitlab/ui';
import { s__ } from '~/locale'; import { s__ } from '~/locale';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { MAX_LIST_COUNT, ACTIVE_CONNECTION_TIME, AGENT_FEEDBACK_ISSUE } from '../constants'; import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
import {
MAX_LIST_COUNT,
ACTIVE_CONNECTION_TIME,
AGENT_FEEDBACK_ISSUE,
AGENT_FEEDBACK_KEY,
} from '../constants';
import getAgentsQuery from '../graphql/queries/get_agents.query.graphql'; import getAgentsQuery from '../graphql/queries/get_agents.query.graphql';
import AgentEmptyState from './agent_empty_state.vue'; import AgentEmptyState from './agent_empty_state.vue';
import AgentTable from './agent_table.vue'; import AgentTable from './agent_table.vue';
export default { export default {
i18n: { i18n: {
feedbackAlert: s__( feedbackBannerTitle: s__('ClusterAgents|Tell us what you think'),
'ClusterAgents|Tell us your experience with the GitLab Agent %{linkStart}in this feedback issue%{linkEnd}.', feedbackBannerText: s__(
'ClusterAgents|We would love to learn more about your experience with the GitLab Agent.',
), ),
error: s__('ClusterAgents|An error occurred while loading your GitLab Agents'), feedbackBannerButton: s__('ClusterAgents|Give feedback'),
error: s__('ClusterAgents|An error occurred while loading your Agents'),
}, },
AGENT_FEEDBACK_ISSUE, AGENT_FEEDBACK_ISSUE,
AGENT_FEEDBACK_KEY,
apollo: { apollo: {
agents: { agents: {
query: getAgentsQuery, query: getAgentsQuery,
...@@ -40,8 +49,8 @@ export default { ...@@ -40,8 +49,8 @@ export default {
GlAlert, GlAlert,
GlKeysetPagination, GlKeysetPagination,
GlLoadingIcon, GlLoadingIcon,
GlSprintf, GlBanner,
GlLink, LocalStorageSync,
}, },
mixins: [glFeatureFlagMixin()], mixins: [glFeatureFlagMixin()],
inject: ['projectPath'], inject: ['projectPath'],
...@@ -69,6 +78,7 @@ export default { ...@@ -69,6 +78,7 @@ export default {
last: null, last: null,
}, },
folderList: {}, folderList: {},
feedbackBannerDismissed: false,
}; };
}, },
computed: { computed: {
...@@ -98,10 +108,10 @@ export default { ...@@ -98,10 +108,10 @@ export default {
treePageInfo() { treePageInfo() {
return this.agents?.project?.repository?.tree?.trees?.pageInfo || {}; return this.agents?.project?.repository?.tree?.trees?.pageInfo || {};
}, },
showFeedbackAlert() { feedbackBannerEnabled() {
return this.glFeatures.showGitlabAgentFeedback; return this.glFeatures.showGitlabAgentFeedback;
}, },
feedbackAlertClasses() { feedbackBannerClasses() {
return this.isChildComponent ? 'gl-my-2' : 'gl-mb-4'; return this.isChildComponent ? 'gl-my-2' : 'gl-mb-4';
}, },
}, },
...@@ -160,6 +170,9 @@ export default { ...@@ -160,6 +170,9 @@ export default {
const count = this.agents?.project?.clusterAgents?.count; const count = this.agents?.project?.clusterAgents?.count;
this.$emit('onAgentsLoad', count); this.$emit('onAgentsLoad', count);
}, },
handleBannerClose() {
this.feedbackBannerDismissed = true;
},
}, },
}; };
</script> </script>
...@@ -169,18 +182,23 @@ export default { ...@@ -169,18 +182,23 @@ export default {
<section v-else-if="agentList"> <section v-else-if="agentList">
<div v-if="agentList.length"> <div v-if="agentList.length">
<gl-alert <local-storage-sync
v-if="showFeedbackAlert" v-if="feedbackBannerEnabled"
variant="tip" v-model="feedbackBannerDismissed"
:class="feedbackAlertClasses" :storage-key="$options.AGENT_FEEDBACK_KEY"
:dismissible="false"
> >
<gl-sprintf :message="$options.i18n.feedbackAlert" <gl-banner
><template #link="{ content }"> v-if="!feedbackBannerDismissed"
<gl-link :href="$options.AGENT_FEEDBACK_ISSUE">{{ content }}</gl-link> variant="introduction"
</template> :class="feedbackBannerClasses"
</gl-sprintf> :title="$options.i18n.feedbackBannerTitle"
</gl-alert> :button-text="$options.i18n.feedbackBannerButton"
:button-link="$options.AGENT_FEEDBACK_ISSUE"
@close="handleBannerClose"
>
<p>{{ $options.i18n.feedbackBannerText }}</p>
</gl-banner>
</local-storage-sync>
<agent-table <agent-table
:agents="agentList" :agents="agentList"
......
...@@ -123,7 +123,7 @@ export default { ...@@ -123,7 +123,7 @@ export default {
<div v-show="!isLoading" data-testid="clusters-cards-container"> <div v-show="!isLoading" data-testid="clusters-cards-container">
<gl-card <gl-card
header-class="gl-bg-white gl-display-flex gl-align-items-center gl-justify-content-space-between gl-py-4" header-class="gl-bg-white gl-display-flex gl-align-items-center gl-justify-content-space-between gl-py-4"
body-class="gl-pb-0" body-class="gl-pb-0 cluster-card-item"
footer-class="gl-text-right" footer-class="gl-text-right"
> >
<template #header> <template #header>
...@@ -198,7 +198,7 @@ export default { ...@@ -198,7 +198,7 @@ export default {
<gl-card <gl-card
class="gl-mt-6" class="gl-mt-6"
header-class="gl-bg-white gl-display-flex gl-align-items-center gl-justify-content-space-between" header-class="gl-bg-white gl-display-flex gl-align-items-center gl-justify-content-space-between"
body-class="gl-pb-0" body-class="gl-pb-0 cluster-card-item"
footer-class="gl-text-right" footer-class="gl-text-right"
> >
<template #header> <template #header>
......
...@@ -267,3 +267,4 @@ export const MODAL_TYPE_REGISTER = 'agent_registration'; ...@@ -267,3 +267,4 @@ export const MODAL_TYPE_REGISTER = 'agent_registration';
export const DELETE_AGENT_MODAL_ID = 'delete-agent-modal-%{agentName}'; export const DELETE_AGENT_MODAL_ID = 'delete-agent-modal-%{agentName}';
export const AGENT_FEEDBACK_ISSUE = 'https://gitlab.com/gitlab-org/gitlab/-/issues/342696'; export const AGENT_FEEDBACK_ISSUE = 'https://gitlab.com/gitlab-org/gitlab/-/issues/342696';
export const AGENT_FEEDBACK_KEY = 'agent_feedback_banner';
...@@ -7,13 +7,6 @@ ...@@ -7,13 +7,6 @@
} }
} }
.gl-card-body {
@include media-breakpoint-up(sm) {
@include gl-pt-2;
min-height: 372px;
}
}
@include media-breakpoint-down(xs) { @include media-breakpoint-down(xs) {
.nav-controls { .nav-controls {
@include gl-w-full; @include gl-w-full;
...@@ -27,6 +20,13 @@ ...@@ -27,6 +20,13 @@
} }
} }
.cluster-card-item {
@include media-breakpoint-up(sm) {
@include gl-pt-2;
min-height: 372px;
}
}
.agent-activity-list { .agent-activity-list {
.system-note .timeline-entry-inner { .system-note .timeline-entry-inner {
.timeline-icon { .timeline-icon {
......
...@@ -7584,7 +7584,7 @@ msgstr "" ...@@ -7584,7 +7584,7 @@ msgstr ""
msgid "ClusterAgents|All" msgid "ClusterAgents|All"
msgstr "" msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents" msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr "" msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent" msgid "ClusterAgents|An error occurred while loading your agent"
...@@ -7671,6 +7671,9 @@ msgstr "" ...@@ -7671,6 +7671,9 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes" msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr "" msgstr ""
msgid "ClusterAgents|Give feedback"
msgstr ""
msgid "ClusterAgents|Go to the repository files" msgid "ClusterAgents|Go to the repository files"
msgstr "" msgstr ""
...@@ -7755,7 +7758,7 @@ msgstr "" ...@@ -7755,7 +7758,7 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab" msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr "" msgstr ""
msgid "ClusterAgents|Tell us your experience with the GitLab Agent %{linkStart}in this feedback issue%{linkEnd}." msgid "ClusterAgents|Tell us what you think"
msgstr "" msgstr ""
msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}" msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
...@@ -7799,6 +7802,9 @@ msgstr "" ...@@ -7799,6 +7802,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters" msgid "ClusterAgents|View all %{number} clusters"
msgstr "" msgstr ""
msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
msgstr ""
msgid "ClusterAgents|What is GitLab Agent activity?" msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr "" msgstr ""
......
import { GlAlert, GlKeysetPagination, GlLoadingIcon, GlSprintf, GlLink } from '@gitlab/ui'; import { GlAlert, GlKeysetPagination, GlLoadingIcon, GlBanner } from '@gitlab/ui';
import { createLocalVue, shallowMount } from '@vue/test-utils'; import { createLocalVue, shallowMount } from '@vue/test-utils';
import VueApollo from 'vue-apollo'; import VueApollo from 'vue-apollo';
import { nextTick } from 'vue'; import { nextTick } from 'vue';
import AgentEmptyState from '~/clusters_list/components/agent_empty_state.vue'; import AgentEmptyState from '~/clusters_list/components/agent_empty_state.vue';
import AgentTable from '~/clusters_list/components/agent_table.vue'; import AgentTable from '~/clusters_list/components/agent_table.vue';
import Agents from '~/clusters_list/components/agents.vue'; import Agents from '~/clusters_list/components/agents.vue';
import { ACTIVE_CONNECTION_TIME, AGENT_FEEDBACK_ISSUE } from '~/clusters_list/constants'; import {
ACTIVE_CONNECTION_TIME,
AGENT_FEEDBACK_KEY,
AGENT_FEEDBACK_ISSUE,
} from '~/clusters_list/constants';
import getAgentsQuery from '~/clusters_list/graphql/queries/get_agents.query.graphql'; import getAgentsQuery from '~/clusters_list/graphql/queries/get_agents.query.graphql';
import createMockApollo from 'helpers/mock_apollo_helper'; import createMockApollo from 'helpers/mock_apollo_helper';
import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
const localVue = createLocalVue(); const localVue = createLocalVue();
localVue.use(VueApollo); localVue.use(VueApollo);
...@@ -57,7 +62,8 @@ describe('Agents', () => { ...@@ -57,7 +62,8 @@ describe('Agents', () => {
glFeatures, glFeatures,
}, },
stubs: { stubs: {
GlSprintf, GlBanner,
LocalStorageSync,
}, },
}); });
...@@ -68,12 +74,12 @@ describe('Agents', () => { ...@@ -68,12 +74,12 @@ describe('Agents', () => {
const findEmptyState = () => wrapper.findComponent(AgentEmptyState); const findEmptyState = () => wrapper.findComponent(AgentEmptyState);
const findPaginationButtons = () => wrapper.findComponent(GlKeysetPagination); const findPaginationButtons = () => wrapper.findComponent(GlKeysetPagination);
const findAlert = () => wrapper.findComponent(GlAlert); const findAlert = () => wrapper.findComponent(GlAlert);
const findLink = () => wrapper.findComponent(GlLink); const findBanner = () => wrapper.findComponent(GlBanner);
afterEach(() => { afterEach(() => {
if (wrapper) {
wrapper.destroy(); wrapper.destroy();
}
localStorage.removeItem(AGENT_FEEDBACK_KEY);
}); });
describe('when there is a list of agents', () => { describe('when there is a list of agents', () => {
...@@ -159,26 +165,46 @@ describe('Agents', () => { ...@@ -159,26 +165,46 @@ describe('Agents', () => {
expect(wrapper.emitted().onAgentsLoad).toEqual([[count]]); expect(wrapper.emitted().onAgentsLoad).toEqual([[count]]);
}); });
describe('when the agent feedback feature flag is enabled', () => { describe.each`
featureFlagEnabled | localStorageItemExists | bannerShown
${true} | ${false} | ${true}
${true} | ${true} | ${false}
${false} | ${true} | ${false}
${false} | ${false} | ${false}
`(
'when the feature flag enabled is $featureFlagEnabled and dismissed localStorage item exists is $localStorageItemExists',
({ featureFlagEnabled, localStorageItemExists, bannerShown }) => {
const glFeatures = { const glFeatures = {
showGitlabAgentFeedback: true, showGitlabAgentFeedback: featureFlagEnabled,
}; };
beforeEach(() => { beforeEach(() => {
if (localStorageItemExists) {
localStorage.setItem(AGENT_FEEDBACK_KEY, true);
}
return createWrapper({ glFeatures, agents, count, trees }); return createWrapper({ glFeatures, agents, count, trees });
}); });
it('should show agent feedback alert', () => { it(`should ${bannerShown ? 'show' : 'hide'} the feedback banner`, () => {
expect(findAlert().exists()).toBe(true); expect(findBanner().exists()).toBe(bannerShown);
}); });
},
);
it('should render the correct issue link', () => { describe('when the agent feedback banner is present', () => {
expect(findLink().attributes('href')).toBe(AGENT_FEEDBACK_ISSUE); const glFeatures = {
showGitlabAgentFeedback: true,
};
beforeEach(() => {
return createWrapper({ glFeatures, agents, count, trees });
}); });
it('should render the correct title', () => {
expect(findBanner().props('title')).toBe('Tell us what you think');
}); });
describe('when the agent feedback feature flag is disabled', () => { it('should render the correct issue link', () => {
it('should not show agent feedback alert', () => { expect(findBanner().props('buttonLink')).toBe(AGENT_FEEDBACK_ISSUE);
expect(findAlert().exists()).toBe(false);
}); });
}); });
...@@ -267,7 +293,7 @@ describe('Agents', () => { ...@@ -267,7 +293,7 @@ describe('Agents', () => {
}); });
it('displays an alert message', () => { it('displays an alert message', () => {
expect(findAlert().text()).toBe('An error occurred while loading your GitLab Agents'); expect(findAlert().text()).toBe('An error occurred while loading your Agents');
}); });
}); });
......
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