From ff0ae785236e53b2c386ca3ca61209c68ee4b87c Mon Sep 17 00:00:00 2001 From: Andrew Fontaine <afontaine@gitlab.com> Date: Tue, 26 Mar 2024 10:07:56 -0400 Subject: [PATCH] Add feedback banner about deployment details page We are not sure what we should fill the page with, so let's ask for feedback! We save if the user has dismissed the callout. --- .../components/details_feedback.vue | 35 ++++++++++++ .../components/show_deployment.vue | 3 ++ app/models/users/callout.rb | 3 +- doc/api/graphql/reference/index.md | 1 + locale/gitlab.pot | 9 ++++ .../components/details_feedback_spec.js | 53 +++++++++++++++++++ .../components/show_deployment_spec.js | 5 ++ 7 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 app/assets/javascripts/deployments/components/details_feedback.vue create mode 100644 spec/frontend/deployments/components/details_feedback_spec.js diff --git a/app/assets/javascripts/deployments/components/details_feedback.vue b/app/assets/javascripts/deployments/components/details_feedback.vue new file mode 100644 index 0000000000000..ff98457e1fa6e --- /dev/null +++ b/app/assets/javascripts/deployments/components/details_feedback.vue @@ -0,0 +1,35 @@ +<script> +import { GlAlert } from '@gitlab/ui'; +import UserCalloutDismisser from '~/vue_shared/components/user_callout_dismisser.vue'; +import { s__ } from '~/locale'; + +export default { + components: { + GlAlert, + UserCalloutDismisser, + }, + i18n: { + header: s__('Deployment|What would you like to see here?'), + body: s__( + "Deployment|We know this page is a bit empty at the moment, but we're working hard to bring you a great experience! In the meantime, we'd love to hear your feedback.", + ), + action: s__('Deployment|Leave feedback'), + }, + FEEDBACK_ISSUE_LINK: 'https://gitlab.com/gitlab-org/gitlab/-/issues/450700', +}; +</script> +<template> + <user-callout-dismisser feature-name="deployment_details_feedback"> + <template #default="{ dismiss, shouldShowCallout }"> + <gl-alert + v-if="shouldShowCallout" + :title="$options.i18n.header" + :primary-button-text="$options.i18n.action" + :primary-button-link="$options.FEEDBACK_ISSUE_LINK" + @dismiss="dismiss" + > + {{ $options.i18n.body }} + </gl-alert> + </template> + </user-callout-dismisser> +</template> diff --git a/app/assets/javascripts/deployments/components/show_deployment.vue b/app/assets/javascripts/deployments/components/show_deployment.vue index 6e62925ced133..b5abfe241e54a 100644 --- a/app/assets/javascripts/deployments/components/show_deployment.vue +++ b/app/assets/javascripts/deployments/components/show_deployment.vue @@ -8,6 +8,7 @@ import environmentQuery from '../graphql/queries/environment.query.graphql'; import DeploymentHeader from './deployment_header.vue'; import DeploymentAside from './deployment_aside.vue'; import DeploymentDeployBlock from './deployment_deploy_block.vue'; +import DetailsFeedback from './details_feedback.vue'; const DEPLOYMENT_QUERY_POLLING_INTERVAL = 3000; @@ -18,6 +19,7 @@ export default { DeploymentHeader, DeploymentAside, DeploymentDeployBlock, + DetailsFeedback, DeploymentApprovals: () => import('ee_component/deployments/components/deployment_approvals.vue'), DeploymentTimeline: () => import('ee_component/deployments/components/deployment_timeline.vue'), @@ -99,6 +101,7 @@ export default { :environment="environment" :loading="$apollo.queries.deployment.loading" /> + <details-feedback class="gl-mt-6 gl-w-90p" /> <deployment-approvals v-if="hasApprovalSummary" :approval-summary="deployment.approvalSummary" diff --git a/app/models/users/callout.rb b/app/models/users/callout.rb index 5c472d4c344f0..140339e1bb09f 100644 --- a/app/models/users/callout.rb +++ b/app/models/users/callout.rb @@ -85,7 +85,8 @@ class Callout < MainClusterwide::ApplicationRecord joining_a_project_alert: 83, # EE-only transition_to_jihu_callout: 84, summarize_code_changes: 85, # EE-only - duo_pro_trial_alert: 86 # EE-only + duo_pro_trial_alert: 86, # EE-only + deployment_details_feedback: 87 } validates :feature_name, diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index 7a763e8d64a84..3d887aa978774 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -33242,6 +33242,7 @@ Name of the feature that the callout is for. | <a id="usercalloutfeaturenameenumci_deprecation_warning_for_types_keyword"></a>`CI_DEPRECATION_WARNING_FOR_TYPES_KEYWORD` | Callout feature name for ci_deprecation_warning_for_types_keyword. | | <a id="usercalloutfeaturenameenumcloud_licensing_subscription_activation_banner"></a>`CLOUD_LICENSING_SUBSCRIPTION_ACTIVATION_BANNER` | Callout feature name for cloud_licensing_subscription_activation_banner. | | <a id="usercalloutfeaturenameenumcluster_security_warning"></a>`CLUSTER_SECURITY_WARNING` | Callout feature name for cluster_security_warning. | +| <a id="usercalloutfeaturenameenumdeployment_details_feedback"></a>`DEPLOYMENT_DETAILS_FEEDBACK` | Callout feature name for deployment_details_feedback. | | <a id="usercalloutfeaturenameenumduo_chat_callout"></a>`DUO_CHAT_CALLOUT` | Callout feature name for duo_chat_callout. | | <a id="usercalloutfeaturenameenumduo_pro_trial_alert"></a>`DUO_PRO_TRIAL_ALERT` | Callout feature name for duo_pro_trial_alert. | | <a id="usercalloutfeaturenameenumfeature_flags_new_version"></a>`FEATURE_FLAGS_NEW_VERSION` | Callout feature name for feature_flags_new_version. | diff --git a/locale/gitlab.pot b/locale/gitlab.pot index d43a57ae4967e..828c07b0030ab 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -17662,6 +17662,9 @@ msgstr "" msgid "Deployment|Latest Deployed" msgstr "" +msgid "Deployment|Leave feedback" +msgstr "" + msgid "Deployment|Needs Approval" msgstr "" @@ -17727,6 +17730,12 @@ msgstr "" msgid "Deployment|Waiting to be deployed." msgstr "" +msgid "Deployment|We know this page is a bit empty at the moment, but we're working hard to bring you a great experience! In the meantime, we'd love to hear your feedback." +msgstr "" + +msgid "Deployment|What would you like to see here?" +msgstr "" + msgid "Deprecated API rate limits" msgstr "" diff --git a/spec/frontend/deployments/components/details_feedback_spec.js b/spec/frontend/deployments/components/details_feedback_spec.js new file mode 100644 index 0000000000000..6b4627ab86fe7 --- /dev/null +++ b/spec/frontend/deployments/components/details_feedback_spec.js @@ -0,0 +1,53 @@ +import { shallowMount } from '@vue/test-utils'; +import { GlAlert } from '@gitlab/ui'; +import DetailsFeedback from '~/deployments/components/details_feedback.vue'; +import { makeMockUserCalloutDismisser } from 'helpers/mock_user_callout_dismisser'; + +jest.mock('~/sentry/sentry_browser_wrapper'); +jest.mock('~/graphql_shared/utils'); + +describe('~/deployments/components/details_feedback.vue', () => { + let wrapper; + let dismiss; + let dismisserComponent; + + const createComponent = ({ shouldShowCallout = true } = {}) => { + dismiss = jest.fn(); + dismisserComponent = makeMockUserCalloutDismisser({ + dismiss, + shouldShowCallout, + }); + wrapper = shallowMount(DetailsFeedback, { + stubs: { + UserCalloutDismisser: dismisserComponent, + }, + }); + }; + + const findAlert = () => wrapper.findComponent(GlAlert); + + it('shows an alert', () => { + createComponent(); + expect(findAlert().exists()).toBe(true); + }); + + it('calls dismiss when the alert is dismissed', () => { + createComponent(); + findAlert().vm.$emit('dismiss'); + expect(dismiss).toHaveBeenCalled(); + }); + + it('links to the feedback issue', () => { + createComponent(); + expect(findAlert().props()).toMatchObject({ + title: 'What would you like to see here?', + primaryButtonText: 'Leave feedback', + primaryButtonLink: 'https://gitlab.com/gitlab-org/gitlab/-/issues/450700', + }); + }); + + it('hides the alert if already dismissed', () => { + createComponent({ shouldShowCallout: false }); + expect(findAlert().exists()).toBe(false); + }); +}); diff --git a/spec/frontend/deployments/components/show_deployment_spec.js b/spec/frontend/deployments/components/show_deployment_spec.js index f76967a5027b3..bd92e620ca8a8 100644 --- a/spec/frontend/deployments/components/show_deployment_spec.js +++ b/spec/frontend/deployments/components/show_deployment_spec.js @@ -9,6 +9,7 @@ import { toggleQueryPollingByVisibility } from '~/graphql_shared/utils'; import ShowDeployment from '~/deployments/components/show_deployment.vue'; import DeploymentHeader from '~/deployments/components/deployment_header.vue'; import DeploymentDeployBlock from '~/deployments/components/deployment_deploy_block.vue'; +import DetailsFeedback from '~/deployments/components/details_feedback.vue'; import deploymentQuery from '~/deployments/graphql/queries/deployment.query.graphql'; import environmentQuery from '~/deployments/graphql/queries/environment.query.graphql'; import waitForPromises from 'helpers/wait_for_promises'; @@ -106,6 +107,10 @@ describe('~/deployments/components/show_deployment.vue', () => { }); }); + it('shows an alert asking for feedback', () => { + expect(wrapper.findComponent(DetailsFeedback).exists()).toBe(true); + }); + it('shows the deployment block if the deployment job is manual', () => { expect(wrapper.findComponent(DeploymentDeployBlock).props()).toEqual({ deployment: mockDeploymentFixture.data.project.deployment, -- GitLab