From 2c2ec726ef1c02186b96e00de95285d6f5adaf3e Mon Sep 17 00:00:00 2001 From: Taras Yemets Date: Fri, 21 Jun 2024 02:35:58 +0300 Subject: [PATCH] feat(plg): remove seats from subscription (#63408) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes https://github.com/sourcegraph/sourcegraph/issues/63234 [Design](https://www.figma.com/design/FMSdn1oKccJRHQPgf7053o/Cody-PLG-GA?node-id=5556-13856&t=f13ek1ZSgoUdrH6z-0) Adds a button to remove the remaining invites from a subscription. https://github.com/sourcegraph/sourcegraph/assets/25318659/679e19dd-0e0e-4561-8ac1-af1b6979ee73 **Known deviation from design (cc: @rrhyne)** The “Remove User” success message and the “Remove Seats from Subscription” alerts are positioned differently than in the design. The “Remove User” banner, along with other user and invite list alerts, is placed above the users list, below the page title or the invites textbox if rendered. The “Remove Seats from Subscription” banner, along with other invite textbox alerts, is located above the invites textbox instead of above the page title and all the page content. These issues will be addressed in follow-up PRs, as we need to refactor the existing Team Members page layout. Created an issue to address it: - https://github.com/sourcegraph/sourcegraph/issues/63411 ## Test plan - Run a Sourcegraph instance in dotcom mode - Sign in as a team admin - Ensure there are free seats on your team (invites remaining) - Ensure "Remove invites from plan" button is rendered - Check the number of invites remaining - Click the button - Ensure the subscription has been updated and now the max seats reduced by the number of remaining invites - Ensure the success banner is rendered ## Changelog --- .../src/cody/components/CodyAlert.module.scss | 7 +++ client/web/src/cody/invites/InviteUsers.tsx | 46 ++++++++++++++++--- 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/client/web/src/cody/components/CodyAlert.module.scss b/client/web/src/cody/components/CodyAlert.module.scss index 4437c4ce85569..8b6ed5c1a84c5 100644 --- a/client/web/src/cody/components/CodyAlert.module.scss +++ b/client/web/src/cody/components/CodyAlert.module.scss @@ -41,8 +41,15 @@ background-color: #51cf66; } &::after { + top: calc(50% - 16px); + left: 1.5rem; + /* stylelint-disable-next-line declaration-property-unit-allowed-list */ + width: 32px; + /* stylelint-disable-next-line declaration-property-unit-allowed-list */ + height: 32px; // Green checkmark SVG background-image: url("data:image/svg+xml,"); + background-repeat: no-repeat; } } diff --git a/client/web/src/cody/invites/InviteUsers.tsx b/client/web/src/cody/invites/InviteUsers.tsx index e3cf2c5e5dc10..74a47b45ffec1 100644 --- a/client/web/src/cody/invites/InviteUsers.tsx +++ b/client/web/src/cody/invites/InviteUsers.tsx @@ -2,13 +2,13 @@ import React, { useState, useCallback, useMemo } from 'react' import { pluralize } from '@sourcegraph/common' import type { TelemetryV2Props } from '@sourcegraph/shared/src/telemetry' -import { ButtonLink, H2, Link, Text, H3, TextArea } from '@sourcegraph/wildcard' +import { H2, Link, Text, H3, TextArea, Button, H1 } from '@sourcegraph/wildcard' import { CodyAlert } from '../components/CodyAlert' import { CodyContainer } from '../components/CodyContainer' import { CodyProBadgeDeck } from '../components/CodyProBadgeDeck' import { useSendInvite, useTeamInvites } from '../management/api/react-query/invites' -import { useCurrentSubscription } from '../management/api/react-query/subscriptions' +import { useCurrentSubscription, useUpdateCurrentSubscription } from '../management/api/react-query/subscriptions' import { useTeamMembers } from '../management/api/react-query/teams' import type { SubscriptionSummary } from '../management/api/teamSubscriptions' import { isValidEmailAddress } from '../util' @@ -39,6 +39,7 @@ export const InviteUsers: React.FunctionComponent = ({ telemet const [emailAddressErrorMessage, setEmailAddressErrorMessage] = useState(null) const sendInviteMutation = useSendInvite() + const updateSubscriptionMutation = useUpdateCurrentSubscription() const verifyEmailList = useCallback((): Error | void => { if (emailAddresses.length === 0) { @@ -104,10 +105,23 @@ export const InviteUsers: React.FunctionComponent = ({ telemet }) }, [emailAddresses, sendInviteMutation.mutateAsync, teamId, telemetryRecorder, verifyEmailList]) - if (!isAdmin || !remainingInviteCount) { + if (updateSubscriptionMutation.isSuccess) { + return ( + +

+ Remaining invites removed from plan +

+ You can add more seats at any time with the "Add seats" button. +
+ ) + } + + if (!isAdmin || !remainingInviteCount || !subscriptionQueryResult.data) { return null } + const { maxSeats } = subscriptionQueryResult.data + return ( <> {sendInviteMutation.status === 'success' && ( @@ -153,15 +167,33 @@ export const InviteUsers: React.FunctionComponent = ({ telemet isValid={emailAddressErrorMessage ? false : undefined} /> {emailAddressErrorMessage ? ( - {emailAddressErrorMessage} + {emailAddressErrorMessage} ) : ( - Enter email addresses separated by a comma. + Enter email addresses separated by a comma. )}
- + +