Skip to content

Commit c136e42

Browse files
committed
Moved all project management functionality to the right panel
1 parent 9fdcd9a commit c136e42

File tree

13 files changed

+497
-684
lines changed

13 files changed

+497
-684
lines changed

app/src/components/left/ComponentPanel.tsx

Lines changed: 2 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,8 @@ import ComponentPanelRoutingItem from './ComponentPanelRoutingItem';
66
import TextField from '@material-ui/core/TextField';
77
import Button from '@material-ui/core/Button';
88
import FormControlLabel from '@material-ui/core/FormControlLabel';
9-
import FormControl from '@material-ui/core/FormControl';
109
import Checkbox from '@material-ui/core/Checkbox';
1110
import MenuItem from '@material-ui/core/MenuItem';
12-
import Select from '@material-ui/core/Select';
1311

1412
import { makeStyles } from '@material-ui/core/styles';
1513

@@ -92,35 +90,13 @@ const ComponentPanel = (): JSX.Element => {
9290
resetError();
9391
};
9492

95-
// Allows users to toggle project between "next.js" and "Classic React"
96-
// When a user changes the project type, the code of all components is rerendered
97-
const handleProjectChange = event => {
98-
const projectType = event.target.value;
99-
dispatch({ type: 'CHANGE PROJECT TYPE', payload: { projectType } });
100-
};
10193

10294
const isFocus = (targetId: Number) => {
10395
return state.canvasFocus.componentId === targetId ? true : false;
10496
};
10597

10698
return (
10799
<div className={classes.panelWrapper}>
108-
{/* Choose project type */}
109-
<div className={classes.projectTypeWrapper}>
110-
<FormControl>
111-
<Select
112-
variant="outlined"
113-
labelId="project-type-label"
114-
id="demo-simple-select"
115-
className={classes.projectSelector}
116-
value={state.projectType}
117-
onChange={handleProjectChange}
118-
>
119-
<MenuItem value={'Next.js'}>Next.js</MenuItem>
120-
<MenuItem value={'Classic React'}>Classic React</MenuItem>
121-
</Select>
122-
</FormControl>
123-
</div>
124100
{/* Add a new component*/}
125101
<div className={classes.addComponentWrapper}>
126102
<div>
@@ -232,25 +208,14 @@ const useStyles = makeStyles({
232208
rootCheckBoxLabel: {
233209
color: 'white'
234210
},
235-
projectTypeWrapper: {
236-
paddingLeft: '20px',
237-
paddingRight: '20px',
238-
marginBottom: '15px',
239-
width: '100%'
240-
},
241-
projectSelector: {
242-
backgroundColor: 'rgba(255,255,255,0.15)',
243-
width: '317px',
244-
color: '#fff'
245-
},
246211
panelWrapper: {
247212
width: '100%',
248213
marginTop: '15px'
249214
},
250215
panelWrapperList: {
251-
maxHeight: '400px',
216+
// maxHeight: '400px',
252217
minHeight: '120px',
253-
overflowY: 'auto',
218+
// overflowY: 'auto',
254219
marginLeft: '-15px',
255220
marginRight: '-15px'
256221
},
Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
import React, { useState, useContext } from 'react';
2+
import { stateContext } from '../../context/context';
3+
4+
import { makeStyles } from '@material-ui/core/styles';
5+
import ExitToAppIcon from '@material-ui/icons/ExitToApp';
6+
import List from '@material-ui/core/List';
7+
import ListItem from '@material-ui/core/ListItem';
8+
import ListItemText from '@material-ui/core/ListItemText';
9+
import SaveIcon from '@material-ui/icons/Save';
10+
import PublishIcon from '@material-ui/icons/Publish';
11+
import Button from '@material-ui/core/Button';
12+
import Checkbox from '@material-ui/core/Checkbox';
13+
import MenuItem from '@material-ui/core/MenuItem';
14+
import Select from '@material-ui/core/Select';
15+
import FormControl from '@material-ui/core/FormControl';
16+
17+
import exportProject from '../../utils/exportProject.util';
18+
import { saveProject } from '../../helperFunctions/projectGetSave';
19+
20+
import ProjectsFolder from './ProjectsFolder';
21+
import createModal from './createModal';
22+
import LoginButton from './LoginButton';
23+
import SaveProjectButton from './SaveProjectButton';
24+
25+
const ProjectManager = () => {
26+
// state to keep track of whether a modal should display
27+
const [modal, setModal] = useState(null);
28+
const [state, dispatch] = useContext(stateContext);
29+
30+
const classes = useStyles();
31+
32+
// Allows users to toggle project between "next.js" and "Classic React"
33+
// When a user changes the project type, the code of all components is rerendered
34+
const handleProjectChange = event => {
35+
const projectType = event.target.value;
36+
dispatch({ type: 'CHANGE PROJECT TYPE', payload: { projectType } });
37+
};
38+
39+
const handleLogout = (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
40+
e.preventDefault();
41+
console.log('Logout clicked, destroying cookie, redirect to login');
42+
// destroys "cookie" by clearing localStorage if guest
43+
window.localStorage.clear();
44+
// destroy cookie on production when not seen by chromium browser using ipcrenderer
45+
window.api.delCookie();
46+
// destroys cookie if user by backdating cookie expiration date
47+
document.cookie = 'ssid=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
48+
// uses useHistory to return to the login page
49+
props.history.push('/login');
50+
};
51+
52+
// state to keep track of how the user wants their components to be exported
53+
// genOption = 0 --> export only components
54+
// genOption = 1 --> export an entire project w/ webpack, server, etc.
55+
const genOptions: string[] = [
56+
'Export components',
57+
'Export components with application files'
58+
];
59+
let genOption = 0;
60+
61+
// closes out the open modal
62+
const closeModal = () => setModal('');
63+
64+
// creates modal that asks if user wants to clear workspace
65+
// if user clears their workspace, then their components are removed from state and the modal is closed
66+
const clearWorkspace = () => {
67+
// Reset state for project to initial state
68+
const resetState = () => {
69+
dispatch({ type: 'RESET STATE', payload: {} });
70+
};
71+
72+
// set modal options
73+
const children = (
74+
<List className="export-preference">
75+
<ListItem
76+
key={'clear'}
77+
button
78+
onClick={resetState}
79+
style={{
80+
border: '1px solid #3f51b5',
81+
marginBottom: '2%',
82+
marginTop: '5%'
83+
}}
84+
>
85+
<ListItemText
86+
primary={'Yes, delete all project data'}
87+
style={{ textAlign: 'center' }}
88+
/>
89+
</ListItem>
90+
</List>
91+
);
92+
93+
// create modal
94+
setModal(
95+
createModal({
96+
closeModal,
97+
children,
98+
message: 'Are you sure want to delete all data?',
99+
primBtnLabel: null,
100+
primBtnAction: null,
101+
secBtnAction: null,
102+
secBtnLabel: null,
103+
open: true
104+
})
105+
);
106+
};
107+
108+
const showGenerateAppModal = () => {
109+
const children = (
110+
<List className="export-preference">
111+
{genOptions.map((option: string, i: number) => (
112+
<ListItem
113+
key={i}
114+
button
115+
onClick={() => chooseGenOptions(i)}
116+
style={{
117+
border: '1px solid #3f51b5',
118+
marginBottom: '2%',
119+
marginTop: '5%'
120+
}}
121+
>
122+
<ListItemText primary={option} style={{ textAlign: 'center' }} />
123+
</ListItem>
124+
))}
125+
</List>
126+
);
127+
128+
// helper function called by showGenerateAppModal
129+
// this function will prompt the user to choose an app directory once they've chosen their export option
130+
const chooseGenOptions = (genOpt: number) => {
131+
// set export option: 0 --> export only components, 1 --> export full project
132+
genOption = genOpt;
133+
window.api.chooseAppDir();
134+
closeModal();
135+
};
136+
137+
// removes all listeners for the app_dir_selected event
138+
// this is important because otherwise listeners will pile up and events will trigger multiple events
139+
window.api.removeAllAppDirChosenListeners();
140+
141+
// add listener for when an app directory is chosen
142+
// when a directory is chosen, the callback will export the project to the chosen folder
143+
// Note: this listener is imported from the main process via preload.js
144+
window.api.addAppDirChosenListener(path => {
145+
exportProject(
146+
path,
147+
'NEW PROJECT',
148+
genOption,
149+
state.projectType,
150+
state.components,
151+
state.rootComponents
152+
);
153+
});
154+
155+
setModal(
156+
createModal({
157+
closeModal,
158+
children,
159+
message: 'Choose export preference:',
160+
primBtnLabel: null,
161+
primBtnAction: null,
162+
secBtnAction: null,
163+
secBtnLabel: null,
164+
open: true
165+
})
166+
);
167+
};
168+
169+
return (
170+
// <div className={classes.logoutButton}>
171+
<div className={classes.projectManagerWrapper}>
172+
<div className={classes.panelWrapper}>
173+
<FormControl>
174+
<Select
175+
variant="outlined"
176+
labelId="project-type-label"
177+
id="demo-simple-select"
178+
className={classes.projectSelector}
179+
value={state.projectType}
180+
onChange={handleProjectChange}
181+
>
182+
<MenuItem value={'Next.js'}>Next.js</MenuItem>
183+
<MenuItem value={'Classic React'}>Classic React</MenuItem>
184+
</Select>
185+
</FormControl>
186+
</div>
187+
<SaveProjectButton />
188+
<ProjectsFolder />
189+
<LoginButton />
190+
{/* <div className={classes.btnGroup}> */}
191+
<Button
192+
className={classes.exportBtn}
193+
variant="outlined"
194+
color="primary"
195+
onClick={showGenerateAppModal}
196+
endIcon={<PublishIcon />}
197+
>
198+
EXPORT PROJECT
199+
</Button>
200+
<Button onClick={clearWorkspace} className={classes.clearBtn}>
201+
CLEAR WORKSPACE
202+
</Button>
203+
{/* </div> */}
204+
{modal}
205+
</div>
206+
);
207+
};
208+
209+
const useStyles = makeStyles({
210+
projectManagerWrapper: {
211+
border: '1px solid rgba(70,131,83)',
212+
padding: '20px',
213+
margin: '20px'
214+
},
215+
216+
logoutButton: {
217+
position: 'absolute',
218+
bottom: '50px',
219+
right: '150px'
220+
},
221+
btnGroup: {
222+
display: 'flex',
223+
flexDirection: 'column',
224+
alignItems: 'center',
225+
justifyContent: 'center',
226+
width: '100%',
227+
position: 'absolute',
228+
bottom: '40px',
229+
left: '0px'
230+
},
231+
232+
exportBtn: {
233+
width: '55%',
234+
backgroundColor: 'rgba(1,212,109,0.1)',
235+
fontSize: '1em'
236+
},
237+
clearBtn: {
238+
width: '55%',
239+
fontSize: '1em',
240+
marginTop: '15px',
241+
color: 'red'
242+
},
243+
projectTypeWrapper: {
244+
paddingLeft: '20px',
245+
paddingRight: '20px',
246+
marginBottom: '15px',
247+
width: '100%'
248+
},
249+
projectSelector: {
250+
backgroundColor: 'rgba(255,255,255,0.15)',
251+
width: '317px',
252+
color: '#fff'
253+
}
254+
});
255+
256+
export default ProjectManager;

0 commit comments

Comments
 (0)