Skip to content
This repository has been archived by the owner on Sep 30, 2024. It is now read-only.

feat(plg): remove seats from subscription #63408

Merged
merged 4 commits into from
Jun 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions client/web/src/cody/components/CodyAlert.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -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,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 31 25'><path fill='%23319E44' d='M27 .4a3.4 3.4 0 0 0-2.4 1.1L12 15.6 7 9.3a3.4 3.4 0 0 0-5-.6 3.4 3.4 0 0 0-.5 4.9L9.2 23a3.4 3.4 0 0 0 5.3.1l15.2-17a3.4 3.4 0 0 0-.3-4.9 3.4 3.4 0 0 0-2.5-.8Z'/></svg>");
background-repeat: no-repeat;
}
}

Expand Down
46 changes: 39 additions & 7 deletions client/web/src/cody/invites/InviteUsers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -39,6 +39,7 @@ export const InviteUsers: React.FunctionComponent<InviteUsersProps> = ({ telemet
const [emailAddressErrorMessage, setEmailAddressErrorMessage] = useState<string | null>(null)

const sendInviteMutation = useSendInvite()
const updateSubscriptionMutation = useUpdateCurrentSubscription()

const verifyEmailList = useCallback((): Error | void => {
if (emailAddresses.length === 0) {
Expand Down Expand Up @@ -104,10 +105,23 @@ export const InviteUsers: React.FunctionComponent<InviteUsersProps> = ({ telemet
})
}, [emailAddresses, sendInviteMutation.mutateAsync, teamId, telemetryRecorder, verifyEmailList])

if (!isAdmin || !remainingInviteCount) {
if (updateSubscriptionMutation.isSuccess) {
return (
<CodyAlert variant="greenSuccess">
<H1 as="p" className="mb-2">
Remaining invites removed from plan
</H1>
<Text className="mb-0">You can add more seats at any time with the "Add seats" button.</Text>
</CodyAlert>
)
}

if (!isAdmin || !remainingInviteCount || !subscriptionQueryResult.data) {
return null
}

const { maxSeats } = subscriptionQueryResult.data

return (
<>
{sendInviteMutation.status === 'success' && (
Expand Down Expand Up @@ -153,15 +167,33 @@ export const InviteUsers: React.FunctionComponent<InviteUsersProps> = ({ telemet
isValid={emailAddressErrorMessage ? false : undefined}
/>
{emailAddressErrorMessage ? (
<Text className="text-danger mb-2">{emailAddressErrorMessage}</Text>
<Text className="text-danger">{emailAddressErrorMessage}</Text>
) : (
<Text className="text-muted mb-2">Enter email addresses separated by a comma.</Text>
<Text className="text-muted">Enter email addresses separated by a comma.</Text>
)}

<div>
<ButtonLink variant="success" size="sm" onSelect={onSendInvitesClicked}>
<Button
disabled={updateSubscriptionMutation.isPending || sendInviteMutation.isPending}
variant="success"
onClick={onSendInvitesClicked}
className="mr-2"
>
Send
</ButtonLink>
</Button>
<Button
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to confirm, if there are "no unfilled seats" this element won't be visible at all right? (Since, it wouldn't make sense to offer the user to send invites to fill seats that don't exist?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

variant="link"
disabled={updateSubscriptionMutation.isPending || sendInviteMutation.isPending}
onClick={() =>
updateSubscriptionMutation.mutate({
subscriptionUpdate: {
newSeatCount: maxSeats - remainingInviteCount,
},
})
}
>
Remove invites from plan
</Button>
</div>
</div>
</div>
Expand Down
Loading