Skip to content

Commit 159221d

Browse files
author
Ives van Hoorne
committed
Add shortcut for creating sandboxes
1 parent dcfb335 commit 159221d

File tree

5 files changed

+153
-31
lines changed

5 files changed

+153
-31
lines changed

packages/app/src/app/pages/Dashboard/Content/CreateNewSandbox/elements.js

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,59 @@
11
import styled, { css } from 'styled-components';
2+
import { Link } from 'react-router-dom';
23
import { animated } from 'react-spring';
34

5+
export const ButtonsContainer = styled.div`
6+
display: flex;
7+
flex-direction: column;
8+
height: calc(100% - 1.75rem);
9+
box-sizing: border-box;
10+
`;
11+
412
export const Container = styled.div`
513
transition: 0.3s ease background-color;
6-
14+
box-sizing: border-box;
715
display: flex;
816
align-items: center;
917
justify-content: center;
10-
font-weight: 300;
11-
color: rgba(255, 255, 255, 0.6);
18+
font-weight: 600;
19+
color: rgba(255, 255, 255, 1);
1220
font-size: 1.125rem;
1321
border-radius: 4px;
1422
width: calc(100% - 2rem);
15-
height: calc(100% - 2rem);
16-
border: 2px solid ${props => props.theme.secondary.clearer(0.2)};
17-
background-color: ${props => props.theme.secondary.clearer(0.9)};
23+
height: 100%;
24+
border: 2px solid
25+
${props => (props.color || props.theme.secondary).clearer(0.2)};
26+
background-color: ${props =>
27+
(props.color || props.theme.secondary).clearer(0.9)};
1828
border-style: dashed;
1929
overflow: hidden;
2030
outline: none;
2131
2232
cursor: pointer;
2333
user-select: none;
34+
text-decoration: none;
2435
2536
${props => props.hide && 'opacity: 0'};
2637
38+
&:first-child {
39+
border-bottom: 0;
40+
}
41+
42+
&:last-child {
43+
border-bottom: 2px solid
44+
${props => (props.color || props.theme.secondary).clearer(0.2)};
45+
border-style: dashed;
46+
}
47+
2748
&:hover,
2849
&:focus {
29-
background-color: ${props => props.theme.secondary.clearer(0.8)};
50+
background-color: ${props =>
51+
(props.color || props.theme.secondary).clearer(0.8)};
3052
}
3153
`;
3254

55+
export const ContainerLink = Container.withComponent(Link);
56+
3357
export const AnimatedModalContainer = styled(animated.div)`
3458
${props =>
3559
props.forking &&

packages/app/src/app/pages/Dashboard/Content/CreateNewSandbox/index.js

Lines changed: 67 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,18 @@ import React from 'react';
22
import { Spring } from 'react-spring';
33
import { inject } from 'mobx-react';
44
import { ThemeProvider } from 'styled-components';
5+
import history from 'app/utils/history';
56

67
import theme from 'common/theme';
8+
import { sandboxUrl } from 'common/utils/url-generator';
79
import Portal from 'app/components/Portal';
8-
import { Container, AnimatedModalContainer } from './elements';
10+
11+
import {
12+
ButtonsContainer,
13+
Container,
14+
AnimatedModalContainer,
15+
ContainerLink,
16+
} from './elements';
917

1018
import Modal from './Modal';
1119

@@ -27,6 +35,11 @@ class CreateNewSandbox extends React.PureComponent {
2735
}
2836

2937
createSandbox = template => {
38+
if (!this.props.collectionId) {
39+
history.push(sandboxUrl({ id: template.shortid }));
40+
return;
41+
}
42+
3043
this.setState({ forking: true }, () => {
3144
this.props.signals.dashboard.createSandboxClicked({
3245
sandboxId: template.shortid,
@@ -64,7 +77,7 @@ class CreateNewSandbox extends React.PureComponent {
6477
};
6578

6679
render() {
67-
const { style } = this.props;
80+
const { style, collectionId, mostUsedSandboxTemplate } = this.props;
6881

6982
const fromRects = this.ref ? this.ref.getBoundingClientRect() : {};
7083
const toRects = this.toRef ? this.toRef.getBoundingClientRect() : {};
@@ -82,8 +95,8 @@ class CreateNewSandbox extends React.PureComponent {
8295
position: 'fixed',
8396
left: fromRects.x,
8497
top: fromRects.y,
85-
width: fromRects.width,
86-
height: fromRects.height,
98+
width: fromRects.width + 32,
99+
height: fromRects.height + 32,
87100
overflow: 'hidden',
88101
},
89102
];
@@ -92,6 +105,36 @@ class CreateNewSandbox extends React.PureComponent {
92105
usedRects = usedRects.reverse();
93106
}
94107

108+
let mostUsedSandboxComponent;
109+
110+
if (mostUsedSandboxTemplate) {
111+
const buttonName = `Create ${mostUsedSandboxTemplate.niceName} Sandbox`;
112+
if (collectionId) {
113+
mostUsedSandboxComponent = (
114+
<Container
115+
innerRef={node => {
116+
this.ref = node;
117+
}}
118+
onClick={() => this.createSandbox(mostUsedSandboxTemplate)}
119+
color={mostUsedSandboxTemplate.color}
120+
tabIndex="0"
121+
role="button"
122+
>
123+
{buttonName}
124+
</Container>
125+
);
126+
} else {
127+
mostUsedSandboxComponent = (
128+
<ContainerLink
129+
to={sandboxUrl({ id: mostUsedSandboxTemplate.shortid })}
130+
color={mostUsedSandboxTemplate.color}
131+
>
132+
{buttonName}
133+
</ContainerLink>
134+
);
135+
}
136+
}
137+
95138
return (
96139
<React.Fragment>
97140
{this.state.creating && (
@@ -129,25 +172,26 @@ class CreateNewSandbox extends React.PureComponent {
129172
</Portal>
130173
)}
131174

132-
<div
133-
ref={node => {
134-
this.ref = node;
135-
}}
136-
style={style}
137-
>
138-
<Container
139-
onClick={this.handleClick}
140-
tabIndex="0"
141-
role="button"
142-
hide={this.state.creating}
143-
onKeyDown={e => {
144-
if (e.keyCode === 13) {
145-
this.handleClick();
146-
}
147-
}}
148-
>
149-
Create Sandbox
150-
</Container>
175+
<div style={style}>
176+
<ButtonsContainer>
177+
<Container
178+
innerRef={node => {
179+
this.ref = node;
180+
}}
181+
onClick={this.handleClick}
182+
tabIndex="0"
183+
role="button"
184+
hide={this.state.creating}
185+
onKeyDown={e => {
186+
if (e.keyCode === 13) {
187+
this.handleClick();
188+
}
189+
}}
190+
>
191+
Create Sandbox
192+
</Container>
193+
{mostUsedSandboxComponent}
194+
</ButtonsContainer>
151195
<Portal>
152196
<div
153197
style={{

packages/app/src/app/pages/Dashboard/Content/routes/PathedSandboxes/index.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { basename } from 'path';
88
import Sandboxes from '../../Sandboxes';
99
import Navigation from './Navigation';
1010
import CreateNewSandbox from '../../CreateNewSandbox';
11+
import getMostUsedTemplate from '../utils/getMostUsedTemplate';
1112

1213
import { PATHED_SANDBOXES_CONTENT_QUERY } from '../../../queries';
1314

@@ -40,6 +41,15 @@ const PathedSandboxes = props => {
4041
sandboxes
4142
);
4243

44+
let mostUsedTemplate = null;
45+
if (!loading) {
46+
try {
47+
mostUsedTemplate = getMostUsedTemplate(sandboxes);
48+
} catch (e) {
49+
// Not critical
50+
}
51+
}
52+
4353
return (
4454
<Sandboxes
4555
ExtraElement={({ style }) => (
@@ -50,6 +60,7 @@ const PathedSandboxes = props => {
5060
data.me.collection &&
5161
data.me.collection.id
5262
}
63+
mostUsedSandboxTemplate={mostUsedTemplate}
5364
style={style}
5465
/>
5566
)}

packages/app/src/app/pages/Dashboard/Content/routes/RecentSandboxes/index.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
import React from 'react';
22
import { observer, inject } from 'mobx-react';
3+
34
import { Query } from 'react-apollo';
45

6+
import getMostUsedTemplate from '../utils/getMostUsedTemplate';
7+
58
import Sandboxes from '../../Sandboxes';
69

710
import CreateNewSandbox from '../../CreateNewSandbox';
@@ -22,11 +25,25 @@ const RecentSandboxes = ({ store }) => {
2225
return <div>Error!</div>;
2326
}
2427

28+
let mostUsedTemplate = null;
29+
if (!loading) {
30+
try {
31+
mostUsedTemplate = getMostUsedTemplate(data.me.sandboxes);
32+
} catch (e) {
33+
// Not critical
34+
}
35+
}
36+
2537
return (
2638
<Sandboxes
2739
isLoading={loading}
2840
Header="Recent Sandboxes"
29-
ExtraElement={({ style }) => <CreateNewSandbox style={style} />}
41+
ExtraElement={({ style }) => (
42+
<CreateNewSandbox
43+
mostUsedSandboxTemplate={mostUsedTemplate}
44+
style={style}
45+
/>
46+
)}
3047
hideFilters
3148
sandboxes={loading ? [] : data.me.sandboxes}
3249
page="recent"
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { countBy } from 'lodash-es';
2+
import getTemplate from 'common/templates';
3+
4+
export default function getMostUsedTemplate(sandboxes) {
5+
const countedByTemplates = countBy(sandboxes, s => s.source.template);
6+
const mostUsedTemplateInfo = Object.keys(countedByTemplates).reduce(
7+
(prev, template) => {
8+
const count = countedByTemplates[template];
9+
if (count > prev.count) {
10+
return {
11+
count,
12+
template,
13+
};
14+
}
15+
16+
return prev;
17+
},
18+
{ count: 0, template: '' }
19+
);
20+
21+
if (mostUsedTemplateInfo.count > 0) {
22+
return getTemplate(mostUsedTemplateInfo.template);
23+
}
24+
25+
return null;
26+
}

0 commit comments

Comments
 (0)