Skip to content

Commit

Permalink
feat(ui): Add click through announcement feature
Browse files Browse the repository at this point in the history
  • Loading branch information
mavarius committed Oct 18, 2023
1 parent da2a963 commit 4a9d79c
Show file tree
Hide file tree
Showing 7 changed files with 291 additions and 32 deletions.
74 changes: 43 additions & 31 deletions src/billing/components/PayAsYouGo/PayAsYouGo.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
// Libraries
import React, {FC} from 'react'
import {useSelector} from 'react-redux'

// Components
import {
AlignItems,
ComponentSize,
Expand All @@ -7,8 +11,6 @@ import {
Panel,
ResourceList,
} from '@influxdata/clockface'

// Components
import PlanTypePanel from 'src/billing/components/PayAsYouGo/PlanTypePanel'
import PaymentPanel from 'src/billing/components/PaymentInfo/PaymentPanel'
import BillingContactInfo from 'src/billing/components/BillingContactInfo'
Expand All @@ -17,35 +19,45 @@ import CancellationPanel from 'src/billing/components/PayAsYouGo/CancellationPan
import NotificationPanel from 'src/billing/components/PayAsYouGo/NotificationPanel'
import InvoiceLoadingWrapper from 'src/billing/components/AssetLoading/InvoiceWrapper'
import BillingInfoWrapper from 'src/billing/components/AssetLoading/BillingInfoWrapper'
import {PricingAlert} from 'src/billing/components/PayAsYouGo/PricingAlert'

// Utils
import {selectCurrentIdentity} from 'src/identity/selectors'

const BillingPayAsYouGo: FC = () => {
const {account} = useSelector(selectCurrentIdentity)
const directSignup = account.billingProvider === 'zuora'

const BillingPayAsYouGo: FC = () => (
<FlexBox
direction={FlexDirection.Column}
alignItems={AlignItems.Stretch}
margin={ComponentSize.Small}
>
<BillingInfoWrapper>
<>
<PlanTypePanel />
<Panel>
<Panel.Header testID="past-invoices--header">
<h4>Past Invoices</h4>
</Panel.Header>
<Panel.Body>
<ResourceList>
<InvoiceLoadingWrapper>
<InvoiceHistory />
</InvoiceLoadingWrapper>
</ResourceList>
</Panel.Body>
</Panel>
<PaymentPanel />
<BillingContactInfo />
</>
</BillingInfoWrapper>
<NotificationPanel />
<CancellationPanel />
</FlexBox>
)
return (
<FlexBox
direction={FlexDirection.Column}
alignItems={AlignItems.Stretch}
margin={ComponentSize.Small}
>
<BillingInfoWrapper>
<>
{directSignup && <PricingAlert />}
<PlanTypePanel />
<Panel>
<Panel.Header testID="past-invoices--header">
<h4>Past Invoices</h4>
</Panel.Header>
<Panel.Body>
<ResourceList>
<InvoiceLoadingWrapper>
<InvoiceHistory />
</InvoiceLoadingWrapper>
</ResourceList>
</Panel.Body>
</Panel>
<PaymentPanel />
<BillingContactInfo />
</>
</BillingInfoWrapper>
<NotificationPanel />
<CancellationPanel />
</FlexBox>
)
}

export default BillingPayAsYouGo
66 changes: 66 additions & 0 deletions src/billing/components/PayAsYouGo/PricingAlert.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Libraries
import React, {useEffect} from 'react'
import {useSelector} from 'react-redux'

// Components
import {
Alert,
FlexBox,
IconFont,
ComponentColor,
ComponentSize,
} from '@influxdata/clockface'
import {SafeBlankLink} from 'src/utils/SafeBlankLink'

// Utils
import {event} from 'src/cloud/utils/reporting'

// Selectors
import {selectCurrentOrg, selectUser} from 'src/identity/selectors'

export const PricingAlert: React.FC = () => {
useEffect(() => {
event(`pricingAnnouncementBanner.displayed`)
}, [])

const org = useSelector(selectCurrentOrg)
const user = useSelector(selectUser)

const handleContactUsClick = () => {
event(`pricingAnnouncementBanner.contactUs.clicked`)
}

const handlePricingAnnouncementClick = () => {
event(`pricingAnnouncementBanner.details.clicked`)
}

return (
<Alert icon={IconFont.AlertTriangle} color={ComponentColor.Primary}>
<FlexBox margin={ComponentSize.Medium}>
<FlexBox.Child grow={1} shrink={0}>
Starting on <b>December 1, 2023</b> there will be an increase in to
your usage-based pricing. Please feel free to{' '}
<SafeBlankLink
href={`mailto:[email protected]?
&subject=PAYG%20price%20change%20inquiry
&body=User%20ID:%20${user.email}%0D%0AOrg%20ID:%20${org.id}%0D%0A%0D%0APlease%20describe%20your%20inquiry%20here.`}
onClick={handleContactUsClick}
>
contact us
</SafeBlankLink>{' '}
with questions or refer to our website for additional information.
</FlexBox.Child>
<FlexBox.Child grow={0} shrink={0}>
<SafeBlankLink
href="https://www.influxdata.com/influxdb-pricing"
onClick={handlePricingAnnouncementClick}
>
<div className="cf-button cf-button-xs cf-button-primary">
<span className="cf-button-label">View Pricing Changes</span>
</div>
</SafeBlankLink>
</FlexBox.Child>
</FlexBox>
</Alert>
)
}
67 changes: 67 additions & 0 deletions src/homepageExperience/ClickThroughAnnouncementHandler.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Libraries
import {FC, useEffect} from 'react'
import {useSelector, useDispatch} from 'react-redux'
import {useLocalStorageState} from 'use-local-storage-state'

// Selectors
import {selectCurrentIdentity} from 'src/identity/selectors'

// Utils
import {showOverlay, dismissOverlay} from 'src/overlays/actions/overlays'

// Constants
import {CLOUD} from 'src/shared/constants'

export const ClickThroughAnnouncementHandler: FC = () => {
const dispatch = useDispatch()
const {account} = useSelector(selectCurrentIdentity)

const [announcementState, setAnnouncementState] = useLocalStorageState(
'clickThroughAnnouncement',
{
announcementID: '',
display: true,
}
)

const setCurrentAnnouncement = (announcementID: string): void => {
if (announcementState['announcementID'] !== announcementID) {
setAnnouncementState({
announcementID: announcementID,
display: true,
})
}
}

const handleDismissAnnouncement = (): void => {
setAnnouncementState(prevState => ({
...prevState,
display: false,
}))
dismissOverlay()
}

useEffect(() => {
// Current Announcement: PAYG Pricing Increase
// Audience: Cloud, Pay As You Go, Direct Signups
const paygAccount = account.type === 'pay_as_you_go'
const directSignup = account.billingProvider === 'zuora'
const audience = CLOUD && paygAccount && directSignup

if (audience) {
setCurrentAnnouncement('payg-pricing-increase-announcement')

if (announcementState['display']) {
dispatch(
showOverlay(
'click-through-announcement',
null,
handleDismissAnnouncement
)
)
}
}
}, [announcementState])

return null
}
8 changes: 7 additions & 1 deletion src/homepageExperience/containers/HomepageContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {useSelector} from 'react-redux'
// Components
import {HomepageContents} from 'src/homepageExperience/containers/HomepageContents'
import {HomepageContentsTSM} from 'src/homepageExperience/containers/HomepageContentsTSM'
import {ClickThroughAnnouncementHandler} from 'src/homepageExperience/ClickThroughAnnouncementHandler'

// Utils
import {isOrgIOx} from 'src/organizations/selectors'
Expand All @@ -16,5 +17,10 @@ export const HomepageContainer: FC = () => {
<HomepageContentsTSM />
)

return <>{homepageContents}</>
return (
<>
{homepageContents}
<ClickThroughAnnouncementHandler />
</>
)
}
101 changes: 101 additions & 0 deletions src/me/components/ClickThroughAnnouncementOverlay.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// Libraries
import React, {useEffect} from 'react'
import {useSelector} from 'react-redux'

// Components
import {Overlay, Button, ComponentColor} from '@influxdata/clockface'
import {SafeBlankLink} from 'src/utils/SafeBlankLink'

// Utils
import {event} from 'src/cloud/utils/reporting'

// Selectors
import {selectCurrentOrg, selectUser} from 'src/identity/selectors'

interface ClickThroughAnnouncementOverlayProps {
onClose: () => void
}

export const ClickThroughAnnouncementOverlay: React.FC<
ClickThroughAnnouncementOverlayProps
> = ({onClose}) => {
useEffect(() => {
event(`pricingClickThroughAnnouncement.displayed`)
}, [])

const org = useSelector(selectCurrentOrg)
const user = useSelector(selectUser)

const handlePricingAnnouncementClick = () => {
event(`pricingClickThroughAnnouncement.details.clicked`)
}

const handleContactUsClick = () => {
event(`pricingClickThroughAnnouncement.contactUs.clicked`)
}

const handleAcknowledgeClick = () => {
event(`pricingClickThroughAnnouncement.acknowledge.clicked`)
onClose()
}

return (
<Overlay visible={true}>
<Overlay.Container>
<Overlay.Header title="Notice: Your Plan Pricing is Changing" />
<Overlay.Body>
<p>
Starting on <strong>December 1, 2023</strong> there will be an
increase in to your usage-based pricing.
</p>
<p>
Your monthly charges will continue to be based on your actual
consumption of the four billable usage vectors: Data In, Query
Count, Storage and Data Out. This is unchanged. However, unit
pricing for two of these vectors will be increased beginning{' '}
<strong>December 1, 2023</strong>:
</p>
<ul>
<li>
Data In will increase from $0.002 to $0.0025 per MB ingested
</li>
<li>
Query Count will increase from $0.01 to $0.012 per 100 executed
</li>
</ul>
<p>
This increase to your total monthly charges will depend on the
specific distribution of your workload across the billable vectors.
Most customers will experience an increase between 14% - 24%.
</p>
<p>
Please feel free to{' '}
<SafeBlankLink
href={`mailto:[email protected]?
&subject=PAYG%20price%20change%20inquiry
&body=User%20ID:%20${user.email}%0D%0AOrg%20ID:%20${org.id}%0D%0A%0D%0APlease%20describe%20your%20inquiry%20here.`}
onClick={handleContactUsClick}
>
contact us
</SafeBlankLink>{' '}
with questions or refer to our website for{' '}
<SafeBlankLink
href="https://www.influxdata.com/influxdb-pricing"
onClick={handlePricingAnnouncementClick}
>
additional information
</SafeBlankLink>
.
</p>
</Overlay.Body>
<Overlay.Footer>
<Button
text="Acknowledge"
color={ComponentColor.Primary}
onClick={handleAcknowledgeClick}
/>
</Overlay.Footer>
</Overlay.Container>
</Overlay>
)
}
6 changes: 6 additions & 0 deletions src/overlays/components/OverlayController.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import {MarketoAccountUpgradeOverlay} from 'src/identity/components/MarketoAccou
import {SuspendPaidOrgOverlay} from 'src/organizations/components/OrgProfileTab/SuspendPaidOrgOverlay'
import {ReplaceCertificateOverlay} from 'src/writeData/subscriptions/components/CertificateInput'
import {RemoveMemberOverlay} from 'src/users/components/RemoveMemberOverlay'
import {ClickThroughAnnouncementOverlay} from 'src/me/components/ClickThroughAnnouncementOverlay'

// Actions
import {dismissOverlay} from 'src/overlays/actions/overlays'
Expand Down Expand Up @@ -189,6 +190,11 @@ export const OverlayController: FunctionComponent = () => {
case 'remove-member':
activeOverlay.current = <RemoveMemberOverlay />
break
case 'click-through-announcement':
activeOverlay.current = (
<ClickThroughAnnouncementOverlay onClose={onClose} />
)
break
default:
activeOverlay.current = null
break
Expand Down
1 change: 1 addition & 0 deletions src/overlays/reducers/overlays.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export type OverlayID =
| 'marketo-upgrade-account-overlay'
| 'suspend-org-in-paid-account'
| 'remove-member'
| 'click-through-announcement'

export interface OverlayState {
id: OverlayID | null
Expand Down

0 comments on commit 4a9d79c

Please sign in to comment.