Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 41 additions & 81 deletions packages/app/src/app/components/Create/CreateBox/CreateBoxForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,12 @@ import {
Icon,
Select,
} from '@codesandbox/components';
import { dashboard } from '@codesandbox/common/lib/utils/url-generator';

import { useActions, useAppState, useEffects } from 'app/overmind';
import { useWorkspaceSubscription } from 'app/hooks/useWorkspaceSubscription';
import { useGlobalPersistedState } from 'app/hooks/usePersistedState';
import { PATHED_SANDBOXES_FOLDER_QUERY } from 'app/pages/Dashboard/queries';
import { useWorkspaceLimits } from 'app/hooks/useWorkspaceLimits';
import { useWorkspaceAuthorization } from 'app/hooks/useWorkspaceAuthorization';
import { Link } from 'react-router-dom';
import { VMTier } from 'app/overmind/effects/api/types';
import { useQuery } from '@apollo/react-hooks';
import {
Expand Down Expand Up @@ -49,20 +46,15 @@ export const CreateBoxForm: React.FC<CreateBoxFormProps> = ({
const { activeTeamInfo, activeTeam, hasLogIn } = useAppState();
const { signInClicked } = useActions();
const {
hasReachedSandboxLimit,
hasReachedDraftLimit,
hasReachedPrivateSandboxLimit,
highestAllowedVMTier,
privateSandboxLimit,
} = useWorkspaceLimits();
const { isAdmin } = useWorkspaceAuthorization();
const [name, setName] = useState<string>();
const effects = useEffects();
const nameInputRef = useRef<HTMLInputElement>(null);
const { isFree } = useWorkspaceSubscription();
const isDraft = collectionId === undefined;
const canCreateDraft = !hasReachedDraftLimit;
const canCreateInFolders = type === 'devbox' || !hasReachedSandboxLimit;
const canCreate =
(isDraft && canCreateDraft) || (!isDraft && canCreateInFolders);

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

useEffect(() => {
if (type === 'devbox') {
Expand Down Expand Up @@ -147,10 +141,16 @@ export const CreateBoxForm: React.FC<CreateBoxFormProps> = ({
}}
onSubmit={e => {
e.preventDefault();

let privacy = permission;
if (isDraft) {
privacy = 2;
}

onSubmit({
name,
createAs: type,
permission,
permission: privacy,
editor: type === 'sandbox' ? 'csb' : editor, // ensure 'csb' is always passed when creating a sandbox
customVMTier:
// Only pass customVMTier if user selects something else than the default
Expand Down Expand Up @@ -191,37 +191,6 @@ export const CreateBoxForm: React.FC<CreateBoxFormProps> = ({
{hasLogIn && (
<Stack gap={2} direction="vertical">
<Stack gap={2}>
<Stack style={{ flex: 1 }} direction="vertical" gap={2}>
<Text size={3} as="label">
Folder
</Text>

<Select
icon={() => (
<Icon name={isDraft ? 'file' : 'folder'} size={12} />
)}
value={isDraft ? '$CSBDRAFTS' : collectionId}
onChange={({ target: { value } }) => {
if (value === '$CSBDRAFTS') {
setCollectionId(undefined);
setPermission(2);
} else {
setCollectionId(value);
}
}}
>
<option value="$CSBDRAFTS">Drafts</option>

{collectionsData?.me?.collections?.map(collection => (
<option value={collection.id}>
{collection.path === '/'
? 'Root folder (/)'
: collection.path}
</option>
))}
</Select>
</Stack>

<Stack style={{ flex: 2 }} direction="vertical" gap={2}>
<Text size={3} as="label">
Visibility
Expand Down Expand Up @@ -254,9 +223,35 @@ export const CreateBoxForm: React.FC<CreateBoxFormProps> = ({
</Select>
</Stack>
</Stack>

{!isDraft && (
<Stack style={{ flex: 1 }} direction="vertical" gap={2}>
<Text size={3} as="label">
Folder
</Text>

<Select
icon={() => (
<Icon name={isDraft ? 'file' : 'folder'} size={12} />
)}
value={collectionId}
onChange={({ target: { value } }) => {
setCollectionId(value);
}}
>
{collectionsData?.me?.collections?.map(collection => (
<option value={collection.id}>
{collection.path === '/'
? 'Root folder (/)'
: collection.path}
</option>
))}
</Select>
</Stack>
)}
</Stack>

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

{isDraft && !canCreateDraft && (
<Stack gap={1} css={{ color: '#F5A8A8' }}>
<Icon name="circleBang" />
<Text size={3}>
Your{' '}
<Link
css={{ color: 'inherit' }}
onClick={onClose}
to={dashboard.drafts(activeTeam)}
>
Drafts folder
</Link>{' '}
is full. Delete unneeded drafts, or{' '}
{isAdmin ? (
<>
<Link
css={{ color: 'inherit' }}
to={dashboard.upgradeUrl({
workspaceId: activeTeam,
source: 'create_draft_limit',
})}
onClick={onClose}
>
upgrade to Pro
</Link>{' '}
for unlimited drafts
</>
) : (
'ask an admin to upgrade to Pro for unlimited drafts'
)}
.
</Text>
</Stack>
)}

{!isDraft && !canCreateInFolders && (
{!isDraft && !canCreate && (
<Stack gap={1} css={{ color: '#F5A8A8' }}>
<Icon name="circleBang" />
<Text size={3}>
You reached the maximum amount of shareable Sandboxes in this
workspace.
You have reached the free limit of {privateSandboxLimit}{' '}
private {label}.
</Text>
</Stack>
)}
Expand Down
2 changes: 1 addition & 1 deletion packages/app/src/app/components/Modal/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ class ModalComponent extends React.Component {
border: '1px solid',
borderColor: 'sideBar.border',
borderRadius: fullWidth ? 0 : '8px',
backgroundColor: 'sideBar.background',
backgroundColor: '#151515',
boxShadow: 2,
color: 'sideBar.foreground',
lineHeight: 1.2,
Expand Down
43 changes: 0 additions & 43 deletions packages/app/src/app/components/StripeMessages/DraftsLimit.tsx

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ import { useWorkspaceAuthorization } from 'app/hooks/useWorkspaceAuthorization';
import { upgradeUrl } from '@codesandbox/common/lib/utils/url-generator/dashboard';
import { useWorkspaceSubscription } from 'app/hooks/useWorkspaceSubscription';
import track from '@codesandbox/common/lib/utils/analytics';
import { useWorkspaceLimits } from 'app/hooks/useWorkspaceLimits';

export const RestrictedSandboxes = () => {
const { activeTeam } = useAppState();
const { isAdmin } = useWorkspaceAuthorization();
const { isPro, isFree } = useWorkspaceSubscription();
const { privateSandboxLimit } = useWorkspaceLimits();

useEffect(() => {
track('Dashboard Sandbox Limit Reached - Display', { isFree, isAdmin });
Expand All @@ -18,8 +20,10 @@ export const RestrictedSandboxes = () => {
if (isAdmin && isPro) {
return (
<MessageStripe variant="warning" justify="space-between">
You reached the maximum amount of shareable Sandboxes in this workspace.
Contact us to increase your limit.
<>
You have reached the free limit of {privateSandboxLimit} private
Sandboxes. Contact us to increase your limit.
</>
<MessageStripe.Action
as="a"
href="mailto:support@codesandbox.io?subject=Sandbox limit on Pro plan"
Expand All @@ -36,8 +40,10 @@ export const RestrictedSandboxes = () => {
if (isAdmin && isFree) {
return (
<MessageStripe variant="warning" justify="space-between">
You reached the maximum amount of shareable Sandboxes in this workspace.
Upgrade to Pro to create more shareable Sandboxes.
<>
You have reached the free limit of {privateSandboxLimit} private
Sandboxes. Upgrade to Pro to create more private Sandboxes.
</>
<MessageStripe.Action
as="a"
href={upgradeUrl({
Expand All @@ -57,17 +63,22 @@ export const RestrictedSandboxes = () => {
if (!isAdmin && isPro) {
return (
<MessageStripe variant="warning" justify="space-between">
You reached the maximum amount of shareable Sandboxes in this workspace.
Ask your administrator to increase the limit.
<>
You have reached the free limit of {privateSandboxLimit} private
Sandboxes. Ask your administrator to increase the limit.
</>
</MessageStripe>
);
}

if (!isAdmin && isFree) {
return (
<MessageStripe variant="warning" justify="space-between">
You reached the maximum amount of shareable Sandboxes in this workspace.
To increase the limit, ask your administrator to upgrade to Pro.
<>
You have reached the free limit of {privateSandboxLimit} private
Sandboxes. To increase the limit, ask your administrator to upgrade to
Pro.
</>
</MessageStripe>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,10 @@ interface WorkspaceSelectProps {
disabled?: boolean;
onSelect: (teamId: string) => void;
selectedTeamId: string;
filterNonPro?: boolean;
}

export const WorkspaceSelect: React.FC<WorkspaceSelectProps> = React.memo(
({ disabled, onSelect, selectedTeamId, filterNonPro }) => {
({ disabled, onSelect, selectedTeamId }) => {
const state = useAppState();
const history = useHistory();
const { dashboard } = state;
Expand Down Expand Up @@ -111,13 +110,6 @@ export const WorkspaceSelect: React.FC<WorkspaceSelectProps> = React.memo(
const isProWorkspace =
team.subscription?.status === SubscriptionStatus.Active;

const moveNotAllowed =
filterNonPro && !isProWorkspace && !team.featureFlags.friendOfCsb;

if (team.id !== state.activeTeam && moveNotAllowed) {
return null;
}

return (
<Stack
as={Menu.Item}
Expand Down
Loading