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

fix(plg): ensure invite flow is enabled only for embedded UI#63466

Merged
taras-yemets merged 7 commits into
mainfrom
ty/gate-invite-flow
Jun 25, 2024
Merged

fix(plg): ensure invite flow is enabled only for embedded UI#63466
taras-yemets merged 7 commits into
mainfrom
ty/gate-invite-flow

Conversation

@taras-yemets

@taras-yemets taras-yemets commented Jun 25, 2024

Copy link
Copy Markdown
Contributor

Makes the invite flow on "/cody/manage" page dependent on the dotcom.codyProConfig.useEmbeddedUI site config param.

Previously we didn't have a check for this site config param on this page (to be precise, it's predecessor, see https://github.com/sourcegraph/sourcegraph/pull/63442).

useEmbeddedUI Plan Role Screenshot
false admin Pro Screenshot 2024-06-25 at 13 02 18
false member Pro Screenshot 2024-06-25 at 13 14 17
false n/a Free Screenshot 2024-06-25 at 13 17 15
true admin Pro Screenshot 2024-06-25 at 13 30 03
true member Pro Screenshot 2024-06-25 at 13 25 24
true n/a Free Screenshot 2024-06-25 at 13 31 41

Test plan

  • Tested manually (screenshots attached):
    • Run Sourcegraph instance in dotcom mode
    • Tweak dotcom.codyProConfig.useEmbeddedUI site config param, log in with users with different team roles (member/admin) and check results with the table above.

@cla-bot cla-bot Bot added the cla-signed label Jun 25, 2024
@taras-yemets taras-yemets requested a review from a team June 25, 2024 10:52

@chrsmith chrsmith left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Some nitpicks and design suggestions, but overall I think this is a big improvement in terms of readability. Although we can continue to improve things. (As the Cody Management page is definitely more complicated than you would think.)

Comment thread client/web/src/cody/management/CodyManagementPage.tsx Outdated

const isUserOnProTier = subscription.plan === CodySubscriptionPlan.PRO
const inviteNodes: InviteNodes = ((): InviteNodes => {
const nodes: InviteNodes = { banner: null, link: null, form: null }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

As a way to make this code easier to understand, what do you think about the following:

Don't introduce a nodes object that is mutated during the execution of the function. (Since that "temporarily couples" things, and the sequence of code blocks is important.) For example, there are three places where we return nodes but all of them have a different meaning.

Instead, consider creating immutable values, and then returning an object literal. That way it is explicit what is being returned from each code path. e.g.

 // Invites flow is supported only for embedded Cody UI.
if (!isEmbeddedCodyProUIEnabled()) {
    return { }   // All fields of InviteNodes left undefined.
}
...
const banner = ...

// Only admins can invite users and manage team.
const subscriptionSummary = subscriptionSummaryQueryResult.data
if (!subscriptionSummary || subscriptionSummary.userRole !== 'admin') {
    return { banner }
}

...

return { banner, form, link }

I wouldn't say this is "clearly" better, but it does have the benefit of making it much more explicit about what fields on the returned object should be set depending on the code path.

})()

const pageHeaderLink: React.ReactNode = (() => {
// User is admin and can manage team and subscription - render corresponding link.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This logic is a little dangerous. All this code snippet has is an inviteNodes.link that is non-null. We are assuming that the user is an admin and can manage the team/subscription. (Which might not always be the case as the code evolves.)

I think we would still want to keep the code as-is (if (inviteNodes.link) return inviteNodes.link) but I would praise the comment differently:

"We determined that we should have a link on the inviteNodes, so we will show it. i.e. pageHeaderLink isn't responsible for keeping track of user state and roles or what not. Instead, we make that entirely the responsibility of whatever is building the inviteNodes object. Does that make sense?

  • Some things need to have our business logic and figure out "what to do"
  • Other things, just take that data and do what is instructed (e.g. showing links/buttons, etc.)

We cannot always make such a clear cut division like this. (e.g. the need for checking on the subscription.plan value below.) But the meta point is that as we break down the UI into smaller components, functions, etc. I would argue that a good design would be to find ways where we can remove the "coupling" between the specific of user stage from just "building the DOM elements as described by object XXX".

@chrsmith

Copy link
Copy Markdown
Contributor

Also, since we want to get this fix in soon, I don't want to harp on this. But it would be really nice if we could have some unit tests or a Storybook page to sanity check this component and these permutations of user state, subscription status, etc. in the future.

@taras-yemets

Copy link
Copy Markdown
Contributor Author

Thanks for a thorough review, @chrsmith!
Addressed you comments in https://github.com/sourcegraph/sourcegraph/pull/63466/commits/84eb23f788ff2d24737d5585008a8a53a78b5a34.

@taras-yemets taras-yemets enabled auto-merge (squash) June 25, 2024 15:25
@taras-yemets taras-yemets merged commit dbc8d5b into main Jun 25, 2024
@taras-yemets taras-yemets deleted the ty/gate-invite-flow branch June 25, 2024 15:33
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants