Skip to content

Commit 4327b03

Browse files
authored
feat: create sandbox from standalone modal (#8403)
1 parent 896454e commit 4327b03

File tree

9 files changed

+341
-140
lines changed

9 files changed

+341
-140
lines changed

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

Lines changed: 68 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -37,23 +37,42 @@ import { useTeamTemplates } from './hooks/useTeamTemplates';
3737
import { CreateParams, SandboxToFork } from './utils/types';
3838
import { SearchBox } from './SearchBox';
3939
import { ImportTemplate } from './ImportTemplate';
40-
import { CreateBoxForm } from './CreateBox/CreateBoxForm';
40+
import { CreateBoxForm, PrivacyLevel } from './CreateBox/CreateBoxForm';
4141
import { TemplateInfo } from './CreateBox/TemplateInfo';
4242
import { useFeaturedTemplates } from './hooks/useFeaturedTemplates';
4343
import { useAllTemplates } from './hooks/useAllTemplates';
4444
import { mapSandboxGQLResponseToSandboxToFork } from './utils/api';
45+
import { WorkspaceSelect } from '../WorkspaceSelect';
4546

4647
type CreateBoxProps = ModalContentProps & {
4748
collectionId?: string;
4849
type?: 'devbox' | 'sandbox';
4950
sandboxIdToFork?: string;
51+
isStandalone?: boolean;
5052
};
5153

54+
function parsePrivacy(privacy: string | undefined): PrivacyLevel | undefined {
55+
if (privacy === 'public') {
56+
return 0;
57+
}
58+
59+
if (privacy === 'unlisted') {
60+
return 1;
61+
}
62+
63+
if (privacy === 'private') {
64+
return 2;
65+
}
66+
67+
return undefined;
68+
}
69+
5270
export const CreateBox: React.FC<CreateBoxProps> = ({
5371
collectionId: initialCollectionId,
5472
sandboxIdToFork,
5573
type = 'devbox',
5674
closeModal,
75+
isStandalone,
5776
}) => {
5877
const { hasLogIn, activeTeam } = useAppState();
5978
const effects = useEffects();
@@ -63,6 +82,9 @@ export const CreateBox: React.FC<CreateBoxProps> = ({
6382
initialCollectionId
6483
);
6584

85+
const parsedUrl = new URL(window.location.href);
86+
const initialPrivacy = parsePrivacy(parsedUrl.searchParams.get('privacy'));
87+
6688
const mediaQuery = window.matchMedia('screen and (max-width: 950px)');
6789
const mobileScreenSize = mediaQuery.matches;
6890

@@ -162,22 +184,41 @@ export const CreateBox: React.FC<CreateBoxProps> = ({
162184
...(customVMTier ? { vm_tier: customVMTier } : {}),
163185
});
164186

165-
actions.editor.forkExternalSandbox({
166-
sandboxId: sandbox.id,
167-
openInNewWindow: false,
168-
openInVSCode,
169-
autoLaunchVSCode,
170-
hasBetaEditorExperiment,
171-
customVMTier,
172-
body: {
173-
title: name,
174-
collectionId,
175-
privacy: permission,
176-
v2: createAs === 'devbox',
177-
},
178-
});
187+
actions.editor
188+
.forkExternalSandbox({
189+
sandboxId: sandbox.id,
190+
openInNewWindow: false,
191+
openInVSCode,
192+
autoLaunchVSCode,
193+
hasBetaEditorExperiment,
194+
customVMTier,
195+
redirectAfterFork: !isStandalone,
196+
body: {
197+
title: name,
198+
collectionId,
199+
privacy: permission,
200+
v2: createAs === 'devbox',
201+
},
202+
})
203+
.then(forkedSandbox => {
204+
if (forkedSandbox && isStandalone) {
205+
window.parent.postMessage(
206+
{
207+
type: 'sandbox-created',
208+
data: {
209+
id: forkedSandbox.id,
210+
alias: forkedSandbox.alias,
211+
url: sandboxUrl(forkedSandbox, hasBetaEditorExperiment),
212+
},
213+
},
214+
'*'
215+
);
216+
}
217+
});
179218

180-
closeModal();
219+
if (closeModal) {
220+
closeModal();
221+
}
181222
};
182223

183224
const selectTemplate = (sandbox: SandboxToFork, trackingSource: string) => {
@@ -509,13 +550,24 @@ export const CreateBox: React.FC<CreateBoxProps> = ({
509550
<>
510551
<ModalSidebar>
511552
<TemplateInfo template={selectedTemplate} />
553+
554+
{hasLogIn && (
555+
<WorkspaceSelect
556+
selectedTeamId={activeTeam}
557+
onSelect={teamId => {
558+
actions.setActiveTeam({ id: teamId });
559+
setCollectionId(undefined);
560+
}}
561+
/>
562+
)}
512563
</ModalSidebar>
513564

514565
<ModalContent>
515566
<CreateBoxForm
516567
type={type}
517568
collectionId={collectionId}
518569
setCollectionId={setCollectionId}
570+
initialPrivacy={initialPrivacy}
519571
onCancel={() => {
520572
setViewState('select');
521573
}}

0 commit comments

Comments
 (0)