Skip to content

Commit 9b23dca

Browse files
committed
[Pricing] Allow 1 free column
1 parent bd386f6 commit 9b23dca

8 files changed

Lines changed: 47 additions & 42 deletions

File tree

landing/src/components/sections/pricing/PricingPlanBlock.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,9 @@ export function PricingPlanBlock(props: PricingPlanBlockProps) {
176176
</div>
177177

178178
<div className="mb-2 text-sm text-muted-65 whitespace-pre-line">
179-
{localizedPlan.description}
179+
{totalNumberOfVisiblePlans === 1
180+
? localizedPlan.description.trim()
181+
: localizedPlan.description}
180182
</div>
181183

182184
<div className="text-5xl leading-snug font-bold text-default">

packages/components/src/components/context/UnreadCountContext.tsx

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
getColumnOption,
88
getFilteredItems,
99
getItemDate,
10+
getItemNodeIdOrId,
1011
ItemPushNotification,
1112
} from '@devhub/core'
1213
import { PixelRatio } from 'react-native'
@@ -55,7 +56,11 @@ export function UnreadCountProvider(props: UnreadCountProviderProps) {
5556
[],
5657
)
5758

58-
const columns = loggedUsername && !isPlanExpired ? _columns : []
59+
const columns = loggedUsername
60+
? isPlanExpired
61+
? _columns.slice(0, (freePlan && freePlan.featureFlags.columnsLimit) || 0)
62+
: _columns
63+
: []
5964

6065
const unreadIds = new Set<string>([])
6166
const pushNotifications = new Set<CardPushNotification>([])
@@ -137,10 +142,11 @@ export function UnreadCountProvider(props: UnreadCountProviderProps) {
137142
)
138143

139144
unreadColumnItems.forEach(item => {
140-
if (!(item && item.id)) return
145+
const itemNodeIdOrId = getItemNodeIdOrId(item)
146+
if (!itemNodeIdOrId) return
141147

142-
if (showAppIconUnreadIndicator && !unreadIds.has(`${item.id}`)) {
143-
unreadIds.add(`${item.id}`)
148+
if (showAppIconUnreadIndicator && !unreadIds.has(`${itemNodeIdOrId}`)) {
149+
unreadIds.add(`${itemNodeIdOrId}`)
144150
}
145151

146152
const itemDate = getItemDate(item)
@@ -195,7 +201,9 @@ export function UnreadCountProvider(props: UnreadCountProviderProps) {
195201
<UnreadCountContext.Provider
196202
value={
197203
unreadIds.size ||
198-
(isPlanExpired && !(freePlan && !freePlan.trialPeriodDays) ? 1 : 0)
204+
(isPlanExpired && !(freePlan && freePlan.featureFlags.columnsLimit)
205+
? 1
206+
: 0)
199207
}
200208
>
201209
{props.children}

packages/components/src/components/modals/PricingModal.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,6 @@ export function PricingModal(props: PricingModalProps) {
155155
: (plan && plan.banner) || false
156156
}
157157
highlightFeature={highlightFeature}
158-
isPartOfAList={plansToShow.length > 1}
159158
isSelected={selectedPlanId === plan.id}
160159
onSelect={() => {
161160
setSelectedPlanId(plan.id)
@@ -164,13 +163,13 @@ export function PricingModal(props: PricingModalProps) {
164163
plan={plan}
165164
showCurrentPlanDetails={!showUserPlanAtTheTop}
166165
showFeatures
166+
totalNumberOfVisiblePlans={plansToShow.length}
167167
/>
168168
) : (
169169
<PricingPlanBlock
170170
key={`pricing-plan-${plan.cannonicalId}`}
171171
banner
172172
highlightFeature={highlightFeature}
173-
isPartOfAList={plansToShow.length > 1}
174173
isSelected={selectedPlanId === plan.id}
175174
onSelect={() => {
176175
setSelectedPlanId(plan.id)
@@ -179,6 +178,7 @@ export function PricingModal(props: PricingModalProps) {
179178
plan={plan}
180179
showCurrentPlanDetails={!showUserPlanAtTheTop}
181180
showFeatures
181+
totalNumberOfVisiblePlans={plansToShow.length}
182182
/>
183183
),
184184
[
@@ -310,9 +310,9 @@ export function PricingModal(props: PricingModalProps) {
310310
<PricingPlanBlock
311311
key="pricing-current-plan"
312312
banner={false}
313-
isPartOfAList={false}
314313
plan={userPlanDetails!}
315314
showCurrentPlanDetails
315+
totalNumberOfVisiblePlans={1}
316316
width="100%"
317317
/>
318318
</View>

packages/components/src/components/modals/partials/PricingPlanBlock.tsx

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,25 +28,25 @@ export const defaultPricingBlockWidth = 230
2828
export interface PricingPlanBlockProps {
2929
banner?: string | boolean
3030
highlightFeature?: keyof Plan['featureFlags']
31-
isPartOfAList: boolean
3231
isSelected?: boolean | undefined
3332
onSelect?: (() => void) | undefined
3433
plan: Plan
3534
showCurrentPlanDetails: boolean
3635
showFeatures?: boolean
36+
totalNumberOfVisiblePlans: number
3737
width?: string | number
3838
}
3939

4040
export function PricingPlanBlock(props: PricingPlanBlockProps) {
4141
const {
4242
banner: _banner,
4343
highlightFeature,
44-
isPartOfAList,
4544
isSelected,
4645
onSelect,
4746
plan,
4847
showCurrentPlanDetails,
4948
showFeatures,
49+
totalNumberOfVisiblePlans,
5050
width = defaultPricingBlockWidth,
5151
} = props
5252

@@ -55,7 +55,7 @@ export function PricingPlanBlock(props: PricingPlanBlockProps) {
5555

5656
const isMyPlan = userPlan && userPlan.id && userPlan!.id === plan.id
5757
const banner =
58-
isMyPlan && isPartOfAList
58+
isMyPlan && totalNumberOfVisiblePlans > 1
5959
? plan.interval
6060
? 'Current plan'
6161
: 'You bought this'
@@ -240,7 +240,9 @@ export function PricingPlanBlock(props: PricingPlanBlockProps) {
240240
color="foregroundColorMuted65"
241241
style={[sharedStyles.textCenter, { fontSize: smallTextSize }]}
242242
>
243-
{plan.description}
243+
{totalNumberOfVisiblePlans === 1
244+
? plan.description.trim()
245+
: plan.description}
244246
</ThemedText>
245247

246248
<Spacer height={contentPadding / 2} />
@@ -267,7 +269,7 @@ export function PricingPlanBlock(props: PricingPlanBlockProps) {
267269
)}
268270
</ThemedText>
269271

270-
{!!(plan.amount || isPartOfAList) && (
272+
{!!(plan.amount || totalNumberOfVisiblePlans > 1) && (
271273
<>
272274
<ThemedText
273275
color="foregroundColorMuted65"
@@ -303,7 +305,7 @@ export function PricingPlanBlock(props: PricingPlanBlockProps) {
303305

304306
<Spacer height={contentPadding} />
305307

306-
{!!(footerText || isPartOfAList) && (
308+
{!!(footerText || totalNumberOfVisiblePlans > 1) && (
307309
<>
308310
<IntervalRefresh interval={1000}>
309311
{() => (

packages/components/src/containers/EventCardsContainer.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ export const EventCardsContainer = React.memo(
4747
const appToken = useReduxState(selectors.appTokenSelector)
4848
const githubAppToken = useReduxState(selectors.githubAppTokenSelector)
4949
const githubToken = useReduxState(selectors.githubTokenSelector)
50-
const { column } = useColumn(columnId)
50+
const { column, hasCrossedColumnsLimit } = useColumn(columnId)
5151

5252
// TODO: Support multiple subscriptions per column.
5353
const mainSubscription = useReduxState(
@@ -142,7 +142,7 @@ export const EventCardsContainer = React.memo(
142142
return <NoTokenView githubAppType={githubAppToken ? 'oauth' : 'both'} />
143143
}
144144

145-
if (maybePrivate) {
145+
if (maybePrivate && !hasCrossedColumnsLimit) {
146146
if (!githubAppToken) return <NoTokenView githubAppType="app" />
147147

148148
if (ownerResponse.loadingState === 'loading') {

packages/components/src/containers/IssueOrPullRequestCardsContainer.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ export const IssueOrPullRequestCardsContainer = React.memo(
4747
(props: IssueOrPullRequestCardsContainerProps) => {
4848
const { columnId, ...otherProps } = props
4949

50-
const { column } = useColumn(columnId)
50+
const { column, hasCrossedColumnsLimit } = useColumn(columnId)
5151

5252
const appToken = useReduxState(selectors.appTokenSelector)
5353
const githubAppToken = useReduxState(selectors.githubAppTokenSelector)
@@ -139,7 +139,7 @@ export const IssueOrPullRequestCardsContainer = React.memo(
139139
return <NoTokenView githubAppType={githubAppToken ? 'oauth' : 'both'} />
140140
}
141141

142-
if (maybePrivate) {
142+
if (maybePrivate && !hasCrossedColumnsLimit) {
143143
if (!githubAppToken) return <NoTokenView githubAppType="app" />
144144

145145
if (ownerResponse.loadingState === 'loading') {

packages/components/src/hooks/use-cards-props.tsx

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ export function useCardsProps<ItemT extends EnhancedItem>({
352352
}>(() => {
353353
if (!(column && column.id)) return { Component: undefined, overlay: false }
354354

355-
if (isPlanExpired) {
355+
if (isPlanExpired && !(plan && plan.featureFlags.columnsLimit)) {
356356
return {
357357
Component: () => (
358358
<EmptyCards
@@ -414,26 +414,18 @@ export function useCardsProps<ItemT extends EnhancedItem>({
414414
columnId={column.id}
415415
emoji="rocket"
416416
errorButtonView={
417-
<Button
417+
<ButtonLink
418418
analyticsLabel="unlock_more_columns_button"
419-
children="Unlock more columns"
420-
onPress={() => {
421-
const nextPlan = activePlans.find(
422-
p => p.featureFlags.columnsLimit > columnIndex + 1,
423-
)
424-
dispatch(
425-
actions.pushModal({
426-
name: 'PRICING',
427-
params: {
428-
highlightFeature: 'columnsLimit',
429-
initialSelectedPlanId: nextPlan && nextPlan.id,
430-
},
431-
}),
432-
)
433-
}}
419+
children="Unlock more columns ↗"
420+
href={`${constants.DEVHUB_LINKS.PRICING_PAGE}?appToken=${appToken}`}
421+
openOnNewTab
434422
/>
435423
}
436-
errorMessage={`You have exceeded the limit of ${plan.featureFlags.columnsLimit} columns.`}
424+
errorMessage={`You have exceeded the limit of ${
425+
plan.featureFlags.columnsLimit
426+
}${plan.amount ? '' : ' free'} ${
427+
plan.featureFlags.columnsLimit === 1 ? 'column' : 'columns'
428+
}.`}
437429
errorTitle="Limit exceeded"
438430
fetchNextPage={undefined}
439431
loadState="error"
@@ -513,6 +505,7 @@ export function useCardsProps<ItemT extends EnhancedItem>({
513505
isPlanExpired,
514506
appToken,
515507
!!(plan && plan.amount),
508+
!!(plan && plan.featureFlags.columnsLimit),
516509
isPlanStatusValid(plan),
517510
])
518511

packages/core/src/utils/plans.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,11 @@ const _freePlan: Plan & { id: 'free' } = {
7474
],
7575

7676
featureFlags: {
77-
columnsLimit: 0,
78-
enableFilters: false,
79-
enableSync: false,
80-
enablePrivateRepositories: false,
81-
enablePushNotifications: false,
77+
columnsLimit: 1,
78+
enableFilters: true,
79+
enableSync: true,
80+
enablePrivateRepositories: true,
81+
enablePushNotifications: true,
8282
},
8383
}
8484

0 commit comments

Comments
 (0)