Skip to content

Commit 0ece60a

Browse files
authored
subscription changes (#8436)
* feat: deprecate draft limits * fix: remove draft limits from create box form * feat: disable make private when reach limit * feat: new move to folder modal * fix: move to folder fixes * fix: update error messages * fix: error message * ts fixes * fix * fix: draft privacy null * linting fixes * fix: remove filter non-pro from workspace select * fix: disable unlisted when reach limit * fix: make draft part of the privacy selection * privacy label * fix: move to folder toast * fix: update types * fix * fix: stripe message
1 parent aed183f commit 0ece60a

File tree

20 files changed

+346
-275
lines changed

20 files changed

+346
-275
lines changed

packages/app/src/app/components/Create/CreateBox/CreateBoxForm.tsx

Lines changed: 41 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,12 @@ import {
88
Icon,
99
Select,
1010
} from '@codesandbox/components';
11-
import { dashboard } from '@codesandbox/common/lib/utils/url-generator';
1211

1312
import { useActions, useAppState, useEffects } from 'app/overmind';
1413
import { useWorkspaceSubscription } from 'app/hooks/useWorkspaceSubscription';
1514
import { useGlobalPersistedState } from 'app/hooks/usePersistedState';
1615
import { PATHED_SANDBOXES_FOLDER_QUERY } from 'app/pages/Dashboard/queries';
1716
import { useWorkspaceLimits } from 'app/hooks/useWorkspaceLimits';
18-
import { useWorkspaceAuthorization } from 'app/hooks/useWorkspaceAuthorization';
19-
import { Link } from 'react-router-dom';
2017
import { VMTier } from 'app/overmind/effects/api/types';
2118
import { useQuery } from '@apollo/react-hooks';
2219
import {
@@ -49,20 +46,15 @@ export const CreateBoxForm: React.FC<CreateBoxFormProps> = ({
4946
const { activeTeamInfo, activeTeam, hasLogIn } = useAppState();
5047
const { signInClicked } = useActions();
5148
const {
52-
hasReachedSandboxLimit,
53-
hasReachedDraftLimit,
49+
hasReachedPrivateSandboxLimit,
5450
highestAllowedVMTier,
51+
privateSandboxLimit,
5552
} = useWorkspaceLimits();
56-
const { isAdmin } = useWorkspaceAuthorization();
5753
const [name, setName] = useState<string>();
5854
const effects = useEffects();
5955
const nameInputRef = useRef<HTMLInputElement>(null);
6056
const { isFree } = useWorkspaceSubscription();
6157
const isDraft = collectionId === undefined;
62-
const canCreateDraft = !hasReachedDraftLimit;
63-
const canCreateInFolders = type === 'devbox' || !hasReachedSandboxLimit;
64-
const canCreate =
65-
(isDraft && canCreateDraft) || (!isDraft && canCreateInFolders);
6658

6759
const minimumPrivacy = Math.max(
6860
initialPrivacy ?? 2,
@@ -78,6 +70,8 @@ export const CreateBoxForm: React.FC<CreateBoxFormProps> = ({
7870
const defaultTier = isFree ? 1 : 2;
7971
const [selectedTier, setSelectedTier] = useState<number>(defaultTier);
8072
const [allVmTiers, setAllVmTiers] = useState<VMTier[]>([]);
73+
const canCreate =
74+
isDraft || !(permission === 2 && hasReachedPrivateSandboxLimit);
8175

8276
useEffect(() => {
8377
if (type === 'devbox') {
@@ -147,10 +141,16 @@ export const CreateBoxForm: React.FC<CreateBoxFormProps> = ({
147141
}}
148142
onSubmit={e => {
149143
e.preventDefault();
144+
145+
let privacy = permission;
146+
if (isDraft) {
147+
privacy = 2;
148+
}
149+
150150
onSubmit({
151151
name,
152152
createAs: type,
153-
permission,
153+
permission: privacy,
154154
editor: type === 'sandbox' ? 'csb' : editor, // ensure 'csb' is always passed when creating a sandbox
155155
customVMTier:
156156
// Only pass customVMTier if user selects something else than the default
@@ -191,37 +191,6 @@ export const CreateBoxForm: React.FC<CreateBoxFormProps> = ({
191191
{hasLogIn && (
192192
<Stack gap={2} direction="vertical">
193193
<Stack gap={2}>
194-
<Stack style={{ flex: 1 }} direction="vertical" gap={2}>
195-
<Text size={3} as="label">
196-
Folder
197-
</Text>
198-
199-
<Select
200-
icon={() => (
201-
<Icon name={isDraft ? 'file' : 'folder'} size={12} />
202-
)}
203-
value={isDraft ? '$CSBDRAFTS' : collectionId}
204-
onChange={({ target: { value } }) => {
205-
if (value === '$CSBDRAFTS') {
206-
setCollectionId(undefined);
207-
setPermission(2);
208-
} else {
209-
setCollectionId(value);
210-
}
211-
}}
212-
>
213-
<option value="$CSBDRAFTS">Drafts</option>
214-
215-
{collectionsData?.me?.collections?.map(collection => (
216-
<option value={collection.id}>
217-
{collection.path === '/'
218-
? 'Root folder (/)'
219-
: collection.path}
220-
</option>
221-
))}
222-
</Select>
223-
</Stack>
224-
225194
<Stack style={{ flex: 2 }} direction="vertical" gap={2}>
226195
<Text size={3} as="label">
227196
Visibility
@@ -254,9 +223,35 @@ export const CreateBoxForm: React.FC<CreateBoxFormProps> = ({
254223
</Select>
255224
</Stack>
256225
</Stack>
226+
227+
{!isDraft && (
228+
<Stack style={{ flex: 1 }} direction="vertical" gap={2}>
229+
<Text size={3} as="label">
230+
Folder
231+
</Text>
232+
233+
<Select
234+
icon={() => (
235+
<Icon name={isDraft ? 'file' : 'folder'} size={12} />
236+
)}
237+
value={collectionId}
238+
onChange={({ target: { value } }) => {
239+
setCollectionId(value);
240+
}}
241+
>
242+
{collectionsData?.me?.collections?.map(collection => (
243+
<option value={collection.id}>
244+
{collection.path === '/'
245+
? 'Root folder (/)'
246+
: collection.path}
247+
</option>
248+
))}
249+
</Select>
250+
</Stack>
251+
)}
257252
</Stack>
258253

259-
{isDraft && canCreateDraft && (
254+
{isDraft && (
260255
<Stack gap={1} css={{ color: '#A8BFFA' }}>
261256
<Icon name="circleBang" />
262257
<Text size={3}>
@@ -265,47 +260,12 @@ export const CreateBoxForm: React.FC<CreateBoxFormProps> = ({
265260
</Stack>
266261
)}
267262

268-
{isDraft && !canCreateDraft && (
269-
<Stack gap={1} css={{ color: '#F5A8A8' }}>
270-
<Icon name="circleBang" />
271-
<Text size={3}>
272-
Your{' '}
273-
<Link
274-
css={{ color: 'inherit' }}
275-
onClick={onClose}
276-
to={dashboard.drafts(activeTeam)}
277-
>
278-
Drafts folder
279-
</Link>{' '}
280-
is full. Delete unneeded drafts, or{' '}
281-
{isAdmin ? (
282-
<>
283-
<Link
284-
css={{ color: 'inherit' }}
285-
to={dashboard.upgradeUrl({
286-
workspaceId: activeTeam,
287-
source: 'create_draft_limit',
288-
})}
289-
onClick={onClose}
290-
>
291-
upgrade to Pro
292-
</Link>{' '}
293-
for unlimited drafts
294-
</>
295-
) : (
296-
'ask an admin to upgrade to Pro for unlimited drafts'
297-
)}
298-
.
299-
</Text>
300-
</Stack>
301-
)}
302-
303-
{!isDraft && !canCreateInFolders && (
263+
{!isDraft && !canCreate && (
304264
<Stack gap={1} css={{ color: '#F5A8A8' }}>
305265
<Icon name="circleBang" />
306266
<Text size={3}>
307-
You reached the maximum amount of shareable Sandboxes in this
308-
workspace.
267+
You have reached the free limit of {privateSandboxLimit}{' '}
268+
private {label}.
309269
</Text>
310270
</Stack>
311271
)}

packages/app/src/app/components/Modal/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ class ModalComponent extends React.Component {
116116
border: '1px solid',
117117
borderColor: 'sideBar.border',
118118
borderRadius: fullWidth ? 0 : '8px',
119-
backgroundColor: 'sideBar.background',
119+
backgroundColor: '#151515',
120120
boxShadow: 2,
121121
color: 'sideBar.foreground',
122122
lineHeight: 1.2,

packages/app/src/app/components/StripeMessages/DraftsLimit.tsx

Lines changed: 0 additions & 43 deletions
This file was deleted.

packages/app/src/app/components/StripeMessages/RestrictedSandboxes.tsx

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@ import { useWorkspaceAuthorization } from 'app/hooks/useWorkspaceAuthorization';
55
import { upgradeUrl } from '@codesandbox/common/lib/utils/url-generator/dashboard';
66
import { useWorkspaceSubscription } from 'app/hooks/useWorkspaceSubscription';
77
import track from '@codesandbox/common/lib/utils/analytics';
8+
import { useWorkspaceLimits } from 'app/hooks/useWorkspaceLimits';
89

910
export const RestrictedSandboxes = () => {
1011
const { activeTeam } = useAppState();
1112
const { isAdmin } = useWorkspaceAuthorization();
1213
const { isPro, isFree } = useWorkspaceSubscription();
14+
const { privateSandboxLimit } = useWorkspaceLimits();
1315

1416
useEffect(() => {
1517
track('Dashboard Sandbox Limit Reached - Display', { isFree, isAdmin });
@@ -18,8 +20,10 @@ export const RestrictedSandboxes = () => {
1820
if (isAdmin && isPro) {
1921
return (
2022
<MessageStripe variant="warning" justify="space-between">
21-
You reached the maximum amount of shareable Sandboxes in this workspace.
22-
Contact us to increase your limit.
23+
<>
24+
You have reached the free limit of {privateSandboxLimit} private
25+
Sandboxes. Contact us to increase your limit.
26+
</>
2327
<MessageStripe.Action
2428
as="a"
2529
href="mailto:support@codesandbox.io?subject=Sandbox limit on Pro plan"
@@ -36,8 +40,10 @@ export const RestrictedSandboxes = () => {
3640
if (isAdmin && isFree) {
3741
return (
3842
<MessageStripe variant="warning" justify="space-between">
39-
You reached the maximum amount of shareable Sandboxes in this workspace.
40-
Upgrade to Pro to create more shareable Sandboxes.
43+
<>
44+
You have reached the free limit of {privateSandboxLimit} private
45+
Sandboxes. Upgrade to Pro to create more private Sandboxes.
46+
</>
4147
<MessageStripe.Action
4248
as="a"
4349
href={upgradeUrl({
@@ -57,17 +63,22 @@ export const RestrictedSandboxes = () => {
5763
if (!isAdmin && isPro) {
5864
return (
5965
<MessageStripe variant="warning" justify="space-between">
60-
You reached the maximum amount of shareable Sandboxes in this workspace.
61-
Ask your administrator to increase the limit.
66+
<>
67+
You have reached the free limit of {privateSandboxLimit} private
68+
Sandboxes. Ask your administrator to increase the limit.
69+
</>
6270
</MessageStripe>
6371
);
6472
}
6573

6674
if (!isAdmin && isFree) {
6775
return (
6876
<MessageStripe variant="warning" justify="space-between">
69-
You reached the maximum amount of shareable Sandboxes in this workspace.
70-
To increase the limit, ask your administrator to upgrade to Pro.
77+
<>
78+
You have reached the free limit of {privateSandboxLimit} private
79+
Sandboxes. To increase the limit, ask your administrator to upgrade to
80+
Pro.
81+
</>
7182
</MessageStripe>
7283
);
7384
}

packages/app/src/app/components/WorkspaceSelect/WorkspaceSelect.tsx

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,10 @@ interface WorkspaceSelectProps {
1212
disabled?: boolean;
1313
onSelect: (teamId: string) => void;
1414
selectedTeamId: string;
15-
filterNonPro?: boolean;
1615
}
1716

1817
export const WorkspaceSelect: React.FC<WorkspaceSelectProps> = React.memo(
19-
({ disabled, onSelect, selectedTeamId, filterNonPro }) => {
18+
({ disabled, onSelect, selectedTeamId }) => {
2019
const state = useAppState();
2120
const history = useHistory();
2221
const { dashboard } = state;
@@ -111,13 +110,6 @@ export const WorkspaceSelect: React.FC<WorkspaceSelectProps> = React.memo(
111110
const isProWorkspace =
112111
team.subscription?.status === SubscriptionStatus.Active;
113112

114-
const moveNotAllowed =
115-
filterNonPro && !isProWorkspace && !team.featureFlags.friendOfCsb;
116-
117-
if (team.id !== state.activeTeam && moveNotAllowed) {
118-
return null;
119-
}
120-
121113
return (
122114
<Stack
123115
as={Menu.Item}

0 commit comments

Comments
 (0)