@@ -25,7 +25,7 @@ import { AcceptInviteBanner } from '../invites/AcceptInviteBanner'
25
25
import { InviteUsers } from '../invites/InviteUsers'
26
26
import { isCodyEnabled } from '../isCodyEnabled'
27
27
import { USER_CODY_PLAN , USER_CODY_USAGE } from '../subscription/queries'
28
- import { getManageSubscriptionPageURL } from '../util'
28
+ import { getManageSubscriptionPageURL , isEmbeddedCodyProUIEnabled } from '../util'
29
29
30
30
import { useSubscriptionSummary } from './api/react-query/subscriptions'
31
31
import { SubscriptionStats } from './SubscriptionStats'
@@ -70,7 +70,6 @@ export const CodyManagementPage: React.FunctionComponent<CodyManagementPageProps
70
70
)
71
71
72
72
const subscriptionSummaryQueryResult = useSubscriptionSummary ( )
73
- const isAdmin = subscriptionSummaryQueryResult ?. data ?. userRole === 'admin'
74
73
75
74
const subscription = data ?. currentUser ?. codySubscription
76
75
@@ -80,26 +79,6 @@ export const CodyManagementPage: React.FunctionComponent<CodyManagementPageProps
80
79
}
81
80
} , [ data , navigate ] )
82
81
83
- const getTeamInviteButton = ( ) : JSX . Element | null => {
84
- const isSoloUser = subscriptionSummaryQueryResult ?. data ?. teamMaxMembers === 1
85
- const hasFreeSeats = subscriptionSummaryQueryResult ?. data
86
- ? subscriptionSummaryQueryResult . data . teamMaxMembers >
87
- subscriptionSummaryQueryResult . data . teamCurrentMembers
88
- : false
89
- const targetUrl = hasFreeSeats ? CodyProRoutes . ManageTeam : `${ CodyProRoutes . NewProSubscription } ?addSeats=1`
90
- const label = isSoloUser || hasFreeSeats ? 'Invite co-workers' : 'Add seats'
91
-
92
- if ( ! subscriptionSummaryQueryResult ?. data ) {
93
- return null
94
- }
95
-
96
- return (
97
- < Button as = { Link } to = { targetUrl } variant = "success" className = "text-nowrap" >
98
- < Icon aria-hidden = { true } svgPath = { mdiPlusThick } /> { label }
99
- </ Button >
100
- )
101
- }
102
-
103
82
const onClickUpgradeToProCTA = useCallback ( ( ) => {
104
83
telemetryRecorder . recordEvent ( 'cody.management.upgradeToProCTA' , 'click' )
105
84
} , [ telemetryRecorder ] )
@@ -116,12 +95,80 @@ export const CodyManagementPage: React.FunctionComponent<CodyManagementPageProps
116
95
return null
117
96
}
118
97
119
- const isUserOnProTier = subscription . plan === CodySubscriptionPlan . PRO
98
+ // Generate invite-related widgets for the page.
99
+ // The returned widgets depend on the user's role and subscription status.
100
+ // Only applicable when embedded Cody Pro UI is enabled.
101
+ const inviteWidgets = ( ( ) : {
102
+ banner ?: React . ReactElement
103
+ link ?: React . ReactElement
104
+ form ?: React . ReactElement
105
+ } => {
106
+ // Invites flow is supported only for embedded Cody UI.
107
+ if ( ! isEmbeddedCodyProUIEnabled ( ) ) {
108
+ return { }
109
+ }
110
+
111
+ const banner = < AcceptInviteBanner onSuccess = { refetch } />
112
+
113
+ const subscriptionSummary = subscriptionSummaryQueryResult . data
114
+ // User is not admin: only banner widget is available from the invite flow (user with any role may get an invite).
115
+ if ( ! subscriptionSummary || subscriptionSummary . userRole !== 'admin' ) {
116
+ return { banner }
117
+ }
118
+
119
+ // User is admin: define link and form widgets.
120
+
121
+ const form = < InviteUsers telemetryRecorder = { telemetryRecorder } subscriptionSummary = { subscriptionSummary } />
122
+
123
+ const isSoloUser = subscriptionSummary . teamMaxMembers === 1
124
+ const hasFreeSeats = subscriptionSummary . teamMaxMembers > subscriptionSummary . teamCurrentMembers
125
+ const targetUrl = hasFreeSeats ? CodyProRoutes . ManageTeam : `${ CodyProRoutes . NewProSubscription } ?addSeats=1`
126
+ const label = isSoloUser || hasFreeSeats ? 'Invite co-workers' : 'Add seats'
127
+ const link = (
128
+ < Button as = { Link } to = { targetUrl } variant = "success" className = "text-nowrap" >
129
+ < Icon aria-hidden = { true } svgPath = { mdiPlusThick } /> { label }
130
+ </ Button >
131
+ )
132
+
133
+ return { banner, link, form }
134
+ } ) ( )
135
+
136
+ const pageHeaderLink : React . ReactNode = ( ( ) => {
137
+ // If invites link widget is defined, render it.
138
+ if ( inviteWidgets . link ) {
139
+ return inviteWidgets . link
140
+ }
141
+
142
+ // User already has a Pro subscription - render a link to the manage subscription page.
143
+ if ( subscription . plan === CodySubscriptionPlan . PRO ) {
144
+ return (
145
+ < ButtonLink
146
+ variant = "primary"
147
+ to = { getManageSubscriptionPageURL ( ) }
148
+ onClick = { ( ) => {
149
+ telemetryRecorder . recordEvent ( 'cody.manageSubscription' , 'click' )
150
+ } }
151
+ >
152
+ < Icon svgPath = { mdiCreditCardOutline } className = "mr-1" aria-hidden = { true } />
153
+ Manage subscription
154
+ </ ButtonLink >
155
+ )
156
+ }
157
+
158
+ // User is on a free plan. Render a link to the subscriptions page.
159
+ return (
160
+ < ButtonLink to = { CodyProRoutes . Subscription } variant = "primary" onClick = { onClickUpgradeToProCTA } >
161
+ Upgrade plan
162
+ </ ButtonLink >
163
+ )
164
+ } ) ( )
120
165
121
166
return (
122
167
< Page className = { classNames ( 'd-flex flex-column' ) } >
123
168
< PageTitle title = "Dashboard" />
124
- < AcceptInviteBanner onSuccess = { refetch } />
169
+
170
+ { inviteWidgets . banner }
171
+
125
172
{ welcomeToPro && (
126
173
< CodyAlert variant = "greenCodyPro" >
127
174
< H2 className = "mt-4" > Welcome to Cody Pro</ H2 >
@@ -134,29 +181,12 @@ export const CodyManagementPage: React.FunctionComponent<CodyManagementPageProps
134
181
className = "my-4 d-inline-flex align-items-center"
135
182
actions = {
136
183
< div className = "d-flex flex-column flex-gap-2" >
137
- { isAdmin ? (
138
- getTeamInviteButton ( )
139
- ) : isUserOnProTier ? (
140
- < ButtonLink
141
- variant = "primary"
142
- to = { getManageSubscriptionPageURL ( ) }
143
- onClick = { ( ) => {
144
- telemetryRecorder . recordEvent ( 'cody.manageSubscription' , 'click' )
145
- } }
146
- >
147
- < Icon svgPath = { mdiCreditCardOutline } className = "mr-1" aria-hidden = { true } />
148
- Manage subscription
149
- </ ButtonLink >
150
- ) : (
151
- < ButtonLink to = "/cody/subscription" variant = "primary" onClick = { onClickUpgradeToProCTA } >
152
- Upgrade plan
153
- </ ButtonLink >
154
- ) }
184
+ { pageHeaderLink }
155
185
< Link
156
186
to = "https://help.sourcegraph.com"
157
187
target = "_blank"
158
188
rel = "noreferrer"
159
- className = "text-muted text-sm"
189
+ className = "text-muted text-center text- sm"
160
190
>
161
191
< Icon svgPath = { mdiHelpCircleOutline } className = "mr-1" aria-hidden = { true } />
162
192
Help & community
@@ -170,12 +200,7 @@ export const CodyManagementPage: React.FunctionComponent<CodyManagementPageProps
170
200
</ PageHeader . Heading >
171
201
</ PageHeader >
172
202
173
- { isAdmin && ! ! subscriptionSummaryQueryResult . data && (
174
- < InviteUsers
175
- telemetryRecorder = { telemetryRecorder }
176
- subscriptionSummary = { subscriptionSummaryQueryResult . data }
177
- />
178
- ) }
203
+ { inviteWidgets . form }
179
204
180
205
< div className = { classNames ( 'border bg-1 mb-2' , styles . container ) } >
181
206
< SubscriptionStats
0 commit comments