Skip to content

Commit

Permalink
Merge pull request #13591 from artsy/DIA-460-logged-in-user-who-has-n…
Browse files Browse the repository at this point in the history
…ever-followed-a-gallery-sees-follow-gallery-popover

Progressive onboarding follow partner popover
  • Loading branch information
dzucconi committed Mar 13, 2024
2 parents 7e681f2 + ab1c952 commit cd54c46
Show file tree
Hide file tree
Showing 32 changed files with 633 additions and 204 deletions.
31 changes: 15 additions & 16 deletions src/Apps/Partner/Components/PartnerHeader/index.tsx
Expand Up @@ -19,6 +19,7 @@ import { themeGet } from "@styled-system/theme-get"
import { Jump } from "Utils/Hooks/useJump"
import { formatFollowerCount } from "Utils/formatFollowerCount"
import { FollowButtonInlineCount } from "Components/FollowButton/Button"
import { ProgressiveOnboardingFollowPartner } from "Components/ProgressiveOnboarding/ProgressiveOnboardingFollowPartner"

export interface PartnerHeaderProps {
partner: PartnerHeader_partner$data
Expand Down Expand Up @@ -84,24 +85,22 @@ export const PartnerHeader: React.FC<PartnerHeaderProps> = ({ partner }) => {

{canFollow && (
<Column span={[12, 2]}>
<FollowProfileButtonQueryRenderer
id={partner.profile.internalID}
contextModule={ContextModule.partnerHeader}
width="100%"
>
{label => (
<Stack gap={0.5} flexDirection="row" alignItems="center">
<Box>{label}</Box>
<Stack gap={0.5} flexDirection="row" alignItems="center">
<ProgressiveOnboardingFollowPartner>
<FollowProfileButtonQueryRenderer
id={partner.profile.internalID}
contextModule={ContextModule.partnerHeader}
width="100%"
/>
</ProgressiveOnboardingFollowPartner>

{!!partner?.profile?.counts?.follows && (
<FollowButtonInlineCount display={["block", "none"]}>
{hasFollows &&
formatFollowerCount(partner.profile.counts.follows)}
</FollowButtonInlineCount>
)}
</Stack>
{!!partner?.profile?.counts?.follows && (
<FollowButtonInlineCount display={["block", "none"]}>
{hasFollows &&
formatFollowerCount(partner.profile.counts.follows)}
</FollowButtonInlineCount>
)}
</FollowProfileButtonQueryRenderer>
</Stack>

{hasFollows && (
<Text
Expand Down
3 changes: 0 additions & 3 deletions src/Apps/Partner/__tests__/PartnerApp.jest.tsx
Expand Up @@ -7,9 +7,6 @@ import { HeadProvider } from "react-head"

jest.unmock("react-relay")
jest.mock("react-tracking")
jest.mock("System/Analytics/AnalyticsContext", () => ({
Analytics: ({ children }) => children,
}))
jest.mock("System/Router/useRouter", () => ({
useRouter: () => ({
match: {
Expand Down
45 changes: 42 additions & 3 deletions src/Components/FollowButton/FollowProfileButton.tsx
Expand Up @@ -3,6 +3,7 @@ import { createFragmentContainer, graphql } from "react-relay"
import { useSystemContext } from "System/useSystemContext"
import { FollowButton, FollowButtonRenderProps } from "./Button"
import { FollowProfileButton_profile$data } from "__generated__/FollowProfileButton_profile.graphql"
import { FollowProfileButton_me$data } from "__generated__/FollowProfileButton_me.graphql"
import { ButtonProps } from "@artsy/palette"
import {
Intent,
Expand All @@ -18,15 +19,17 @@ import { useAuthDialog } from "Components/AuthDialog"

interface FollowProfileButtonProps extends Omit<ButtonProps, "variant"> {
children?: FollowButtonRenderProps
profile: FollowProfileButton_profile$data
me: FollowProfileButton_me$data | null | undefined
contextModule?: AuthContextModule
onFollow?: (followed: boolean) => void
profile: FollowProfileButton_profile$data
}

const FollowProfileButton: React.FC<FollowProfileButtonProps> = ({
profile,
contextModule = ContextModule.partnerHeader,
me,
onFollow,
profile,
...rest
}) => {
const { isLoggedIn } = useSystemContext()
Expand All @@ -38,22 +41,43 @@ const FollowProfileButton: React.FC<FollowProfileButtonProps> = ({
contextModule,
})

const profileCount = profile.counts?.follows ?? 0
const meCount = me?.counts?.followedProfiles ?? 0

const { submitMutation } = useMutation({
mutation: graphql`
mutation FollowProfileButtonMutation($input: FollowProfileInput!) {
followProfile(input: $input) {
me {
id
counts {
followedProfiles
}
}
profile {
id
isFollowed
counts {
follows
}
}
}
}
`,
optimisticResponse: {
followProfile: {
me: {
id: me?.id ?? "logged-out",
counts: {
followedProfiles: profile.isFollowed ? meCount - 1 : meCount + 1,
},
},
profile: {
id: profile.id,
isFollowed: !profile.isFollowed,
counts: {
follows: profile.isFollowed ? profileCount - 1 : profileCount + 1,
},
},
},
},
Expand Down Expand Up @@ -119,20 +143,31 @@ const FollowProfileButton: React.FC<FollowProfileButtonProps> = ({
export const FollowProfileButtonFragmentContainer = createFragmentContainer(
FollowProfileButton,
{
me: graphql`
fragment FollowProfileButton_me on Me {
id
counts {
followedProfiles
}
}
`,
profile: graphql`
fragment FollowProfileButton_profile on Profile {
id
slug
name
internalID
isFollowed
counts {
follows
}
}
`,
}
)

interface FollowProfileButtonQueryRendererProps
extends Omit<FollowProfileButtonProps, "profile"> {
extends Omit<FollowProfileButtonProps, "profile" | "me"> {
id: string
}

Expand All @@ -145,6 +180,9 @@ export const FollowProfileButtonQueryRenderer: React.FC<FollowProfileButtonQuery
lazyLoad
query={graphql`
query FollowProfileButtonQuery($id: String!) {
me {
...FollowProfileButton_me
}
profile(id: $id) {
...FollowProfileButton_profile
}
Expand All @@ -160,6 +198,7 @@ export const FollowProfileButtonQueryRenderer: React.FC<FollowProfileButtonQuery
return (
<FollowProfileButtonFragmentContainer
{...rest}
me={props.me}
profile={props.profile}
/>
)
Expand Down
Expand Up @@ -23,12 +23,16 @@ const { renderWithRelay } = setupTestWrapperTL<FollowProfileButton_Test_Query>({
return (
<FollowProfileButtonFragmentContainer
profile={props.partner!.profile!}
me={props.me!}
onFollow={onFollow}
/>
)
},
query: graphql`
query FollowProfileButton_Test_Query @relay_test_operation {
me {
...FollowProfileButton_me
}
partner(id: "example") {
profile {
...FollowProfileButton_profile
Expand Down
Expand Up @@ -17,11 +17,11 @@ import {
import { useSystemContext } from "System/SystemContext"
import { useDismissibleContext } from "@artsy/dismissible"
import {
PROGRESSIVE_ONBOARDING_ALERTS,
PROGRESSIVE_ONBOARDING,
PROGRESSIVE_ONBOARDING_ALERT_CHAIN,
} from "Components/ProgressiveOnboarding/progressiveOnboardingAlerts"
} from "Components/ProgressiveOnboarding/progressiveOnboardingKeys"

const ALERT_ID = PROGRESSIVE_ONBOARDING_ALERTS.alertCreate
const KEY = PROGRESSIVE_ONBOARDING.alertCreate

interface ProgressiveOnboardingAlertCreateProps
extends WithProgressiveOnboardingCountsProps {
Expand All @@ -38,7 +38,7 @@ export const __ProgressiveOnboardingAlertCreate__: FC<ProgressiveOnboardingAlert

const isDisplayable =
isLoggedIn &&
!isDismissed(ALERT_ID).status &&
!isDismissed(KEY).status &&
counts.isReady &&
counts.savedSearches === 0

Expand All @@ -49,11 +49,11 @@ export const __ProgressiveOnboardingAlertCreate__: FC<ProgressiveOnboardingAlert
}

const handleNext = () => {
dismiss(ALERT_ID)
dismiss(KEY)
}

const handleClose = () => {
dismiss(ALERT_ID)
dismiss(KEY)
}

if (!isDisplayable) {
Expand All @@ -62,7 +62,7 @@ export const __ProgressiveOnboardingAlertCreate__: FC<ProgressiveOnboardingAlert

return (
<ProgressiveOnboardingPopover
name={ALERT_ID}
name={KEY}
ignoreClickOutside
onClose={handleClose}
variant="defaultLight"
Expand Down
Expand Up @@ -7,9 +7,9 @@ import {
} from "Components/ProgressiveOnboarding/withProgressiveOnboardingCounts"
import { useSystemContext } from "System/SystemContext"
import { useDismissibleContext } from "@artsy/dismissible"
import { PROGRESSIVE_ONBOARDING_ALERTS } from "Components/ProgressiveOnboarding/progressiveOnboardingAlerts"
import { PROGRESSIVE_ONBOARDING } from "Components/ProgressiveOnboarding/progressiveOnboardingKeys"

const ALERT_ID = PROGRESSIVE_ONBOARDING_ALERTS.alertCreate
const KEY = PROGRESSIVE_ONBOARDING.alertCreate

interface ProgressiveOnboardingAlertCreateSimpleProps
extends WithProgressiveOnboardingCountsProps {}
Expand All @@ -24,12 +24,12 @@ export const __ProgressiveOnboardingAlertCreateSimple__: FC<ProgressiveOnboardin

const isDisplayable =
isLoggedIn &&
!isDismissed(ALERT_ID).status &&
!isDismissed(KEY).status &&
counts.isReady &&
counts.savedSearches === 0

const handleClose = () => {
dismiss(ALERT_ID)
dismiss(KEY)
}

if (!isDisplayable) {
Expand All @@ -38,7 +38,7 @@ export const __ProgressiveOnboardingAlertCreateSimple__: FC<ProgressiveOnboardin

return (
<ProgressiveOnboardingPopover
name={ALERT_ID}
name={KEY}
ignoreClickOutside
placement="left"
onClose={handleClose}
Expand Down
Expand Up @@ -7,9 +7,9 @@ import {
import { ProgressiveOnboardingPopover } from "Components/ProgressiveOnboarding/ProgressiveOnboardingPopover"
import { FC } from "react"
import { useDismissibleContext } from "@artsy/dismissible"
import { PROGRESSIVE_ONBOARDING_ALERTS } from "Components/ProgressiveOnboarding/progressiveOnboardingAlerts"
import { PROGRESSIVE_ONBOARDING } from "Components/ProgressiveOnboarding/progressiveOnboardingKeys"

const ALERT_ID = PROGRESSIVE_ONBOARDING_ALERTS.alertFind
const KEY = PROGRESSIVE_ONBOARDING.alertFind

interface ProgressiveOnboardingAlertFindProps
extends WithProgressiveOnboardingCountsProps {}
Expand All @@ -20,11 +20,10 @@ export const __ProgressiveOnboardingAlertFind__: FC<ProgressiveOnboardingAlertFi
}) => {
const { dismiss, isDismissed } = useDismissibleContext()

const isDisplayable =
counts.savedSearches === 1 && !isDismissed(ALERT_ID).status
const isDisplayable = counts.savedSearches === 1 && !isDismissed(KEY).status

const handleClose = () => {
dismiss(ALERT_ID)
dismiss(KEY)
}

const handleDismiss = () => {
Expand All @@ -37,7 +36,7 @@ export const __ProgressiveOnboardingAlertFind__: FC<ProgressiveOnboardingAlertFi

return (
<ProgressiveOnboardingPopover
name={ALERT_ID}
name={KEY}
placement="bottom-end"
onClose={handleClose}
onDismiss={handleDismiss}
Expand Down
Expand Up @@ -3,7 +3,7 @@ import {
ProgressiveOnboardingHighlight,
ProgressiveOnboardingHighlightPosition,
} from "Components/ProgressiveOnboarding/ProgressiveOnboardingHighlight"
import { PROGRESSIVE_ONBOARDING_ALERTS } from "Components/ProgressiveOnboarding/progressiveOnboardingAlerts"
import { PROGRESSIVE_ONBOARDING } from "Components/ProgressiveOnboarding/progressiveOnboardingKeys"
import { FC, useEffect } from "react"

interface ProgressiveOnboardingAlertHighlightProps {
Expand All @@ -18,18 +18,18 @@ export const ProgressiveOnboardingAlertHighlight: FC<ProgressiveOnboardingAlertH

const isDisplayable =
// You haven't already dismissed this
!isDismissed(PROGRESSIVE_ONBOARDING_ALERTS.alertHighlight).status &&
!isDismissed(PROGRESSIVE_ONBOARDING.alertHighlight).status &&
// And you've previously dismissed the previous onboarding tip
isDismissed(PROGRESSIVE_ONBOARDING_ALERTS.alertFind).status &&
isDismissed(PROGRESSIVE_ONBOARDING.alertFind).status &&
// And you've dismissed the previous step within the last 20 seconds
isDismissed(PROGRESSIVE_ONBOARDING_ALERTS.alertFind).timestamp >
isDismissed(PROGRESSIVE_ONBOARDING.alertFind).timestamp >
Date.now() - 20 * 1000

useEffect(() => {
if (!isDisplayable) return

const handleClick = () => {
dismiss(PROGRESSIVE_ONBOARDING_ALERTS.alertHighlight)
dismiss(PROGRESSIVE_ONBOARDING.alertHighlight)
}

document.addEventListener("click", handleClick, { once: true })
Expand All @@ -46,7 +46,7 @@ export const ProgressiveOnboardingAlertHighlight: FC<ProgressiveOnboardingAlertH
return (
<ProgressiveOnboardingHighlight
position={position}
name={PROGRESSIVE_ONBOARDING_ALERTS.alertHighlight}
name={PROGRESSIVE_ONBOARDING.alertHighlight}
>
{children}
</ProgressiveOnboardingHighlight>
Expand Down
@@ -1,7 +1,7 @@
import { ProgressiveOnboardingPopover } from "Components/ProgressiveOnboarding/ProgressiveOnboardingPopover"
import { FC, ReactNode } from "react"
import { Text } from "@artsy/palette"
import { PROGRESSIVE_ONBOARDING_ALERTS } from "Components/ProgressiveOnboarding/progressiveOnboardingAlerts"
import { PROGRESSIVE_ONBOARDING } from "Components/ProgressiveOnboarding/progressiveOnboardingKeys"
import { useDismissibleContext } from "@artsy/dismissible"

interface ProgressiveOnboardingAlertReadyProps {
Expand All @@ -14,14 +14,14 @@ export const ProgressiveOnboardingAlertReady: FC<ProgressiveOnboardingAlertReady
const { dismiss, isDismissed } = useDismissibleContext()

const isDisplayable =
isDismissed(PROGRESSIVE_ONBOARDING_ALERTS.alertSelectFilter).status &&
isDismissed(PROGRESSIVE_ONBOARDING_ALERTS.alertCreate).status &&
!isDismissed(PROGRESSIVE_ONBOARDING_ALERTS.alertReady).status
isDismissed(PROGRESSIVE_ONBOARDING.alertSelectFilter).status &&
isDismissed(PROGRESSIVE_ONBOARDING.alertCreate).status &&
!isDismissed(PROGRESSIVE_ONBOARDING.alertReady).status

const handleClose = () => {
dismiss(PROGRESSIVE_ONBOARDING_ALERTS.alertCreate)
dismiss(PROGRESSIVE_ONBOARDING_ALERTS.alertSelectFilter)
dismiss(PROGRESSIVE_ONBOARDING_ALERTS.alertReady)
dismiss(PROGRESSIVE_ONBOARDING.alertCreate)
dismiss(PROGRESSIVE_ONBOARDING.alertSelectFilter)
dismiss(PROGRESSIVE_ONBOARDING.alertReady)
}

if (!isDisplayable) {
Expand All @@ -30,7 +30,7 @@ export const ProgressiveOnboardingAlertReady: FC<ProgressiveOnboardingAlertReady

return (
<ProgressiveOnboardingPopover
name={PROGRESSIVE_ONBOARDING_ALERTS.alertReady}
name={PROGRESSIVE_ONBOARDING.alertReady}
placement="bottom"
onClose={handleClose}
popover={<Text variant="xs">When you’re ready, click Create Alert.</Text>}
Expand Down

0 comments on commit cd54c46

Please sign in to comment.