Skip to content

Commit 9c2caac

Browse files
committed
bring back things used in embed?!
1 parent 6c8ea7c commit 9c2caac

File tree

19 files changed

+1499
-0
lines changed

19 files changed

+1499
-0
lines changed
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import { Directory, Module } from '@codesandbox/common/lib/types';
2+
import { useOvermind } from 'app/overmind';
3+
// eslint-disable-next-line import/extensions
4+
import getType from 'app/utils/get-type.ts';
5+
import React from 'react';
6+
7+
import Entry from '../Entry';
8+
9+
interface IModuleEntryProps {
10+
module: Module;
11+
setCurrentModule?: (id: string) => void;
12+
store?: any;
13+
signals?: any;
14+
markTabsNotDirty?: () => void;
15+
depth?: number;
16+
renameModule?: (title: string, moduleShortid: string) => void;
17+
deleteEntry?: (shortid: string, title: string) => void;
18+
discardModuleChanges?: (shortid: string, title: string) => void;
19+
getModulePath?: (
20+
modules: Module[],
21+
directories: Directory[],
22+
id: string
23+
) => string;
24+
renameValidator?: (id: string, title: string) => string | false | null;
25+
}
26+
27+
const ModuleEntry: React.FC<IModuleEntryProps> = ({
28+
module,
29+
setCurrentModule,
30+
markTabsNotDirty,
31+
depth,
32+
renameModule,
33+
deleteEntry,
34+
discardModuleChanges,
35+
getModulePath,
36+
renameValidator,
37+
}) => {
38+
const {
39+
state: {
40+
editor: { mainModule, currentModuleShortid },
41+
live,
42+
},
43+
} = useOvermind();
44+
const isActive = module.shortid === currentModuleShortid;
45+
const isMainModule = module.id === mainModule.id;
46+
const type = getType(module.title);
47+
const hasError = module.errors.length > 0;
48+
const liveUsers = live.liveUsersByModule[module.shortid] || [];
49+
50+
const isNotSynced = module.savedCode && module.code !== module.savedCode;
51+
52+
return (
53+
// @ts-ignore
54+
<Entry
55+
id={module.id}
56+
shortid={module.shortid}
57+
title={module.title}
58+
rightColors={liveUsers.map(([a, b, c]) => `rgb(${a}, ${b}, ${c})`)}
59+
depth={depth + 1}
60+
active={isActive}
61+
type={type || 'function'}
62+
rename={renameModule}
63+
deleteEntry={deleteEntry}
64+
isNotSynced={isNotSynced}
65+
renameValidator={renameValidator}
66+
setCurrentModule={setCurrentModule}
67+
isMainModule={isMainModule}
68+
moduleHasError={hasError}
69+
markTabsNotDirty={markTabsNotDirty}
70+
discardModuleChanges={discardModuleChanges}
71+
getModulePath={getModulePath}
72+
/>
73+
);
74+
};
75+
76+
export default ModuleEntry;
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import { HIDDEN_DIRECTORIES } from '@codesandbox/common/lib/templates/constants/files';
2+
import { Directory, Module } from '@codesandbox/common/lib/types';
3+
import { useOvermind } from 'app/overmind';
4+
import { sortBy } from 'lodash-es';
5+
import * as React from 'react';
6+
7+
import ModuleEntry from './ModuleEntry';
8+
import DirectoryEntry from '..';
9+
10+
interface IDirectoryChildrenProps {
11+
depth?: number;
12+
renameModule?: (title: string, moduleShortid: string) => void;
13+
setCurrentModule?: (id: string) => void;
14+
parentShortid?: string;
15+
deleteEntry?: (shortid: string, title: string) => void;
16+
isInProjectView?: boolean;
17+
markTabsNotDirty?: () => void;
18+
discardModuleChanges?: (shortid: string, title: string) => void;
19+
getModulePath?: (
20+
modules: Module[],
21+
directories: Directory[],
22+
id: string
23+
) => string;
24+
renameValidator?: (id: string, title: string) => string | false | null;
25+
}
26+
27+
const DirectoryChildren: React.FC<IDirectoryChildrenProps> = ({
28+
depth = 0,
29+
renameModule,
30+
setCurrentModule,
31+
parentShortid,
32+
deleteEntry,
33+
isInProjectView,
34+
markTabsNotDirty,
35+
discardModuleChanges,
36+
getModulePath,
37+
renameValidator,
38+
}) => {
39+
const {
40+
state: { isLoggedIn, editor: editorState },
41+
actions: { files, editor },
42+
} = useOvermind();
43+
const { currentSandbox, mainModule, currentModuleShortid } = editorState;
44+
45+
const {
46+
id: sandboxId,
47+
modules,
48+
directories,
49+
template: sandboxTemplate,
50+
} = currentSandbox;
51+
52+
return (
53+
<div>
54+
{sortBy(directories, 'title')
55+
.filter(x => x.directoryShortid === parentShortid)
56+
.filter(
57+
x =>
58+
!(
59+
x.directoryShortid == null && HIDDEN_DIRECTORIES.includes(x.title)
60+
)
61+
)
62+
.map(dir => (
63+
<DirectoryEntry
64+
key={dir.id}
65+
siblings={[...directories, ...modules]}
66+
depth={depth + 1}
67+
signals={{ files, editor }}
68+
store={{ editor: editorState, isLoggedIn }}
69+
id={dir.id}
70+
shortid={dir.shortid}
71+
title={dir.title}
72+
sandboxId={sandboxId}
73+
sandboxTemplate={sandboxTemplate}
74+
mainModuleId={mainModule.id}
75+
modules={modules}
76+
directories={directories}
77+
currentModuleShortid={currentModuleShortid}
78+
isInProjectView={isInProjectView}
79+
markTabsNotDirty={markTabsNotDirty}
80+
getModulePath={getModulePath}
81+
/>
82+
))}
83+
{sortBy(
84+
modules.filter(x => x.directoryShortid === parentShortid),
85+
'title'
86+
).map(m => (
87+
<ModuleEntry
88+
key={m.id}
89+
module={m}
90+
depth={depth}
91+
setCurrentModule={setCurrentModule}
92+
markTabsNotDirty={markTabsNotDirty}
93+
renameModule={renameModule}
94+
deleteEntry={deleteEntry}
95+
discardModuleChanges={discardModuleChanges}
96+
getModulePath={getModulePath}
97+
renameValidator={renameValidator}
98+
/>
99+
))}
100+
</div>
101+
);
102+
};
103+
104+
export default DirectoryChildren;
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import React from 'react';
2+
import { Alert } from 'app/pages/common/Modals/Common/Alert';
3+
import Modal from 'app/components/Modal';
4+
5+
interface DirectoryEntryModalProps {
6+
body: React.ReactNode;
7+
isOpen: boolean;
8+
onClose: () => void;
9+
onConfirm: () => void;
10+
title: string;
11+
primaryMessage?: string;
12+
}
13+
14+
const DirectoryEntryModal = ({
15+
body,
16+
isOpen,
17+
onClose,
18+
onConfirm,
19+
primaryMessage,
20+
title,
21+
}: DirectoryEntryModalProps) => (
22+
<Modal isOpen={isOpen} onClose={onClose} width={400}>
23+
<Alert
24+
title={title}
25+
description={body}
26+
onCancel={onClose}
27+
onPrimaryAction={onConfirm}
28+
type="danger"
29+
confirmMessage={primaryMessage || 'Delete'}
30+
/>
31+
</Modal>
32+
);
33+
34+
export default DirectoryEntryModal;
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import styled from 'styled-components';
2+
import fadeIn from '@codesandbox/common/lib/utils/animation/fade-in';
3+
4+
export const Container = styled.div`
5+
display: flex;
6+
${fadeIn(0)};
7+
vertical-align: middle;
8+
line-height: 1;
9+
align-items: center;
10+
`;
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import React from 'react';
2+
3+
import CrossIcon from 'react-icons/lib/md/clear';
4+
import EditIcon from 'react-icons/lib/go/pencil';
5+
import AddFileIcon from 'react-icons/lib/md/insert-drive-file';
6+
import AddDirectoryIcon from 'react-icons/lib/md/create-new-folder';
7+
import UploadFileIcon from 'react-icons/lib/md/file-upload';
8+
import DownloadIcon from 'react-icons/lib/md/file-download';
9+
import UndoIcon from 'react-icons/lib/md/undo';
10+
11+
import Tooltip, {
12+
SingletonTooltip,
13+
} from '@codesandbox/common/lib/components/Tooltip';
14+
15+
import { Icon } from '../../../../elements';
16+
import { Container } from './elements';
17+
18+
const handleClick = func => e => {
19+
e.preventDefault();
20+
e.stopPropagation();
21+
func();
22+
};
23+
24+
function EditIcons({
25+
className = undefined,
26+
hovering,
27+
onDelete,
28+
onDiscardChanges,
29+
onEdit,
30+
onCreateFile,
31+
onCreateDirectory,
32+
active,
33+
onUploadFile,
34+
onDownload = undefined,
35+
forceShow,
36+
}) {
37+
// Phones need double click if we show elements on click, that's why we only want
38+
// to show these edit icons when the user clicks and hasn't activated the module
39+
if (window.__isTouch && !active && !forceShow) {
40+
return null;
41+
}
42+
43+
return (
44+
<div className={className}>
45+
{(hovering || (window.__isTouch && active) || forceShow) && (
46+
<Container>
47+
<SingletonTooltip>
48+
{singleton => (
49+
<>
50+
{onDownload && (
51+
<Tooltip content="Export to ZIP" singleton={singleton}>
52+
<Icon onClick={handleClick(onDownload)}>
53+
<DownloadIcon />
54+
</Icon>
55+
</Tooltip>
56+
)}
57+
{onUploadFile && (
58+
<Tooltip content="Upload Files" singleton={singleton}>
59+
<Icon onClick={handleClick(onUploadFile)}>
60+
<UploadFileIcon />
61+
</Icon>
62+
</Tooltip>
63+
)}
64+
{onDiscardChanges && (
65+
<Tooltip content="Discard Changes">
66+
<Icon onClick={handleClick(onDiscardChanges)}>
67+
<UndoIcon />
68+
</Icon>
69+
</Tooltip>
70+
)}
71+
{onEdit && (
72+
<Tooltip content="Rename" singleton={singleton}>
73+
<Icon onClick={handleClick(onEdit)}>
74+
<EditIcon />
75+
</Icon>
76+
</Tooltip>
77+
)}
78+
{onCreateFile && (
79+
<Tooltip content="New File" singleton={singleton}>
80+
<Icon onClick={handleClick(onCreateFile)}>
81+
<AddFileIcon />
82+
</Icon>
83+
</Tooltip>
84+
)}
85+
{onCreateDirectory && (
86+
<Tooltip content="New Directory" singleton={singleton}>
87+
<Icon onClick={handleClick(onCreateDirectory)}>
88+
<AddDirectoryIcon />
89+
</Icon>
90+
</Tooltip>
91+
)}
92+
{onDelete && (
93+
<Tooltip content="Delete" singleton={singleton}>
94+
<Icon onClick={handleClick(onDelete)}>
95+
<CrossIcon />
96+
</Icon>
97+
</Tooltip>
98+
)}
99+
</>
100+
)}
101+
</SingletonTooltip>
102+
</Container>
103+
)}
104+
</div>
105+
);
106+
}
107+
108+
export default EditIcons;
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import styled, { css } from 'styled-components';
2+
3+
export const Container = styled.div`
4+
display: inline-block;
5+
vertical-align: middle;
6+
`;
7+
8+
export const RedIcon = styled.span<{ height: number; width: number }>`
9+
${({ height, theme, width }) => css`
10+
color: ${theme.red};
11+
width: ${width}px;
12+
height: ${height}px;
13+
`};
14+
`;
15+
16+
export const SVGIcon = styled.span<{
17+
height: number;
18+
url: string;
19+
width: number;
20+
}>`
21+
${({ height, url, width }) => css`
22+
background-image: url(${url});
23+
background-size: ${width}px;
24+
background-position: 0;
25+
background-repeat: no-repeat;
26+
width: ${width}px;
27+
height: ${height}px;
28+
display: inline-block;
29+
-webkit-font-smoothing: antialiased;
30+
vertical-align: top;
31+
flex-shrink: 0;
32+
`};
33+
`;

0 commit comments

Comments
 (0)