Commit 9667a0aa authored by Jose Ivan Vargas's avatar Jose Ivan Vargas

Merge branch '342697-ask-for-feedback-on-the-agent-listing-page' into 'master'

Ask for feedback on the Agent listing page

See merge request gitlab-org/gitlab!78567
parents 42fbc7c1 7257b683
<script>
import { GlAlert, GlKeysetPagination, GlLoadingIcon } from '@gitlab/ui';
import { MAX_LIST_COUNT, ACTIVE_CONNECTION_TIME } from '../constants';
import { GlAlert, GlKeysetPagination, GlLoadingIcon, GlBanner } from '@gitlab/ui';
import { s__ } from '~/locale';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
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 AgentEmptyState from './agent_empty_state.vue';
import AgentTable from './agent_table.vue';
export default {
i18n: {
feedbackBannerTitle: s__('ClusterAgents|Tell us what you think'),
feedbackBannerText: s__(
'ClusterAgents|We would love to learn more about your experience with the GitLab Agent.',
),
feedbackBannerButton: s__('ClusterAgents|Give feedback'),
error: s__('ClusterAgents|An error occurred while loading your Agents'),
},
AGENT_FEEDBACK_ISSUE,
AGENT_FEEDBACK_KEY,
apollo: {
agents: {
query: getAgentsQuery,
......@@ -31,7 +49,10 @@ export default {
GlAlert,
GlKeysetPagination,
GlLoadingIcon,
GlBanner,
LocalStorageSync,
},
mixins: [glFeatureFlagMixin()],
inject: ['projectPath'],
props: {
defaultBranchName: {
......@@ -57,6 +78,7 @@ export default {
last: null,
},
folderList: {},
feedbackBannerDismissed: false,
};
},
computed: {
......@@ -86,6 +108,12 @@ export default {
treePageInfo() {
return this.agents?.project?.repository?.tree?.trees?.pageInfo || {};
},
feedbackBannerEnabled() {
return this.glFeatures.showGitlabAgentFeedback;
},
feedbackBannerClasses() {
return this.isChildComponent ? 'gl-my-2' : 'gl-mb-4';
},
},
methods: {
reloadAgents() {
......@@ -142,6 +170,9 @@ export default {
const count = this.agents?.project?.clusterAgents?.count;
this.$emit('onAgentsLoad', count);
},
handleBannerClose() {
this.feedbackBannerDismissed = true;
},
},
};
</script>
......@@ -151,6 +182,24 @@ export default {
<section v-else-if="agentList">
<div v-if="agentList.length">
<local-storage-sync
v-if="feedbackBannerEnabled"
v-model="feedbackBannerDismissed"
:storage-key="$options.AGENT_FEEDBACK_KEY"
>
<gl-banner
v-if="!feedbackBannerDismissed"
variant="introduction"
:class="feedbackBannerClasses"
:title="$options.i18n.feedbackBannerTitle"
: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
:agents="agentList"
:default-branch-name="defaultBranchName"
......@@ -166,6 +215,6 @@ export default {
</section>
<gl-alert v-else variant="danger" :dismissible="false">
{{ s__('ClusterAgents|An error occurred while loading your GitLab Agents') }}
{{ $options.i18n.error }}
</gl-alert>
</template>
......@@ -123,7 +123,7 @@ export default {
<div v-show="!isLoading" data-testid="clusters-cards-container">
<gl-card
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"
>
<template #header>
......@@ -198,7 +198,7 @@ export default {
<gl-card
class="gl-mt-6"
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"
>
<template #header>
......
......@@ -267,3 +267,6 @@ export const MODAL_TYPE_EMPTY = 'empty_state';
export const MODAL_TYPE_REGISTER = 'agent_registration';
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_KEY = 'agent_feedback_banner';
......@@ -7,13 +7,6 @@
}
}
.gl-card-body {
@include media-breakpoint-up(sm) {
@include gl-pt-2;
min-height: 372px;
}
}
@include media-breakpoint-down(xs) {
.nav-controls {
@include gl-w-full;
......@@ -27,6 +20,13 @@
}
}
.cluster-card-item {
@include media-breakpoint-up(sm) {
@include gl-pt-2;
min-height: 372px;
}
}
.agent-activity-list {
.system-note .timeline-entry-inner {
.timeline-icon {
......
......@@ -6,6 +6,7 @@ class Projects::ClustersController < Clusters::ClustersController
before_action do
push_frontend_feature_flag(:prometheus_computed_alerts)
push_frontend_feature_flag(:show_gitlab_agent_feedback, type: :ops, default_enabled: :yaml)
end
layout 'project'
......
---
name: show_gitlab_agent_feedback
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78567
rollout_issue_url:
milestone: '14.8'
type: ops
group: group::configure
default_enabled: true
......@@ -7587,7 +7587,7 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
msgid "ClusterAgents|An error occurred while loading your Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
......@@ -7674,6 +7674,9 @@ msgstr ""
msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
msgid "ClusterAgents|Give feedback"
msgstr ""
msgid "ClusterAgents|Go to the repository files"
msgstr ""
......@@ -7758,6 +7761,9 @@ msgstr ""
msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
msgid "ClusterAgents|Tell us what you think"
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}"
msgstr ""
......@@ -7799,6 +7805,9 @@ msgstr ""
msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
msgid "ClusterAgents|We would love to learn more about your experience with the GitLab Agent."
msgstr ""
msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
......
import { GlAlert, GlKeysetPagination, GlLoadingIcon } from '@gitlab/ui';
import { GlAlert, GlKeysetPagination, GlLoadingIcon, GlBanner } from '@gitlab/ui';
import { createLocalVue, shallowMount } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
import { nextTick } from 'vue';
import AgentEmptyState from '~/clusters_list/components/agent_empty_state.vue';
import AgentTable from '~/clusters_list/components/agent_table.vue';
import Agents from '~/clusters_list/components/agents.vue';
import { ACTIVE_CONNECTION_TIME } 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 createMockApollo from 'helpers/mock_apollo_helper';
import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
const localVue = createLocalVue();
localVue.use(VueApollo);
......@@ -24,6 +29,7 @@ describe('Agents', () => {
const createWrapper = async ({
props = {},
glFeatures = {},
agents = [],
pageInfo = null,
trees = [],
......@@ -51,20 +57,29 @@ describe('Agents', () => {
...defaultProps,
...props,
},
provide: provideData,
provide: {
...provideData,
glFeatures,
},
stubs: {
GlBanner,
LocalStorageSync,
},
});
await nextTick();
};
const findAgentTable = () => wrapper.find(AgentTable);
const findEmptyState = () => wrapper.find(AgentEmptyState);
const findPaginationButtons = () => wrapper.find(GlKeysetPagination);
const findAgentTable = () => wrapper.findComponent(AgentTable);
const findEmptyState = () => wrapper.findComponent(AgentEmptyState);
const findPaginationButtons = () => wrapper.findComponent(GlKeysetPagination);
const findAlert = () => wrapper.findComponent(GlAlert);
const findBanner = () => wrapper.findComponent(GlBanner);
afterEach(() => {
if (wrapper) {
wrapper.destroy();
}
localStorage.removeItem(AGENT_FEEDBACK_KEY);
});
describe('when there is a list of agents', () => {
......@@ -150,6 +165,49 @@ describe('Agents', () => {
expect(wrapper.emitted().onAgentsLoad).toEqual([[count]]);
});
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 = {
showGitlabAgentFeedback: featureFlagEnabled,
};
beforeEach(() => {
if (localStorageItemExists) {
localStorage.setItem(AGENT_FEEDBACK_KEY, true);
}
return createWrapper({ glFeatures, agents, count, trees });
});
it(`should ${bannerShown ? 'show' : 'hide'} the feedback banner`, () => {
expect(findBanner().exists()).toBe(bannerShown);
});
},
);
describe('when the agent feedback banner is present', () => {
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');
});
it('should render the correct issue link', () => {
expect(findBanner().props('buttonLink')).toBe(AGENT_FEEDBACK_ISSUE);
});
});
describe('when the agent has recently connected tokens', () => {
it('should set agent status to active', () => {
expect(findAgentTable().props('agents')).toMatchObject(expectedAgentsList);
......@@ -223,6 +281,10 @@ describe('Agents', () => {
expect(findAgentTable().exists()).toBe(false);
expect(findEmptyState().exists()).toBe(true);
});
it('should not show agent feedback alert', () => {
expect(findAlert().exists()).toBe(false);
});
});
describe('when agents query has errored', () => {
......@@ -231,7 +293,7 @@ describe('Agents', () => {
});
it('displays an alert message', () => {
expect(wrapper.find(GlAlert).exists()).toBe(true);
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