Skip to content

Commit 9812f4c

Browse files
committed
Added README and resolved merge conflicts.
2 parents 42c6f96 + 6cd2b6a commit 9812f4c

File tree

11 files changed

+246
-43
lines changed

11 files changed

+246
-43
lines changed

__tests__/componentReducer.test.ts

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import reducer from '../app/src/reducers/componentReducer';
2+
import { State, Action, Component, ChildElement } from '../app/src/interfaces/InterfacesNew';
3+
4+
import initialState from '../app/src/context/initialState';
5+
6+
7+
describe('Testing componentReducer functionality', function () {
8+
let state: State = initialState;
9+
10+
11+
// TEST 'ADD COMPONENT'
12+
describe('ADD COMPONENT reducer', () => {
13+
it('should add new reuseable component to state', () => {
14+
const action = {
15+
type: 'ADD COMPONENT',
16+
payload: {
17+
componentName: "TestRegular",
18+
root: false
19+
}
20+
}
21+
state = reducer(state, action);
22+
// expect state.components array to have length 2
23+
const length = state.components.length;
24+
expect(length).toEqual(2);
25+
// expect new component name to match name of last elem in state.components array
26+
expect(state.components[length - 1].name).toEqual(action.payload.componentName);
27+
})
28+
})
29+
30+
// TEST 'ADD CHILD'
31+
describe('ADD CHILD reducer', () => {
32+
it('should add child component to top-level component', () => {
33+
const action = {
34+
type: 'ADD CHILD',
35+
payload: {
36+
type: 'Component',
37+
typeId: 2,
38+
childId: null
39+
}
40+
}
41+
// switch focus to very first root component
42+
state.canvasFocus = { componentId: 1, childId: null };
43+
console.log(state);
44+
state = reducer(state, action);
45+
const newParent = state.components[0];
46+
// expect new parent's children array to have length 1
47+
expect(newParent.children.length).toEqual(1);
48+
// expect new child to have type 'Component'
49+
console.log('new child ', newParent.children[0]);
50+
expect(newParent.children[0].type).toEqual('Component');
51+
const addedChild = state.components.find(comp => comp.id === newParent.children[0].typeId);
52+
// expect new child typeId to correspond to component with name 'TestRegular'
53+
expect(addedChild.name).toEqual('TestRegular');
54+
})
55+
})
56+
57+
// TEST 'CHANGE FOCUS'
58+
describe('CHANGE FOCUS reducer', () => {
59+
it('should change focus to specified component', () => {
60+
const action = {
61+
type: 'CHANGE FOCUS',
62+
payload: {
63+
componentId: 2,
64+
childId: null
65+
}
66+
}
67+
console.log('before change focus ', state.canvasFocus);
68+
state = reducer(state, action);
69+
console.log('after change focus ', state.canvasFocus);
70+
expect(state.canvasFocus.componentId).toEqual(2);
71+
expect(state.canvasFocus.childId).toEqual(null);
72+
})
73+
})
74+
75+
// TEST 'UPDATE CSS'
76+
describe('UPDATE CSS reducer', () => {
77+
it('should update background color of focused component', () => {
78+
79+
})
80+
})
81+
82+
// TEST 'RESET STATE'
83+
84+
})

app/electron/main.js

Lines changed: 65 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,22 @@ const {
1010
// The splash screen is what appears while the app is loading
1111
const { initSplashScreen, OfficeTemplate } = require('electron-splashscreen');
1212
const { resolve } = require('app-root-path');
13-
const Protocol = require('./protocol');
14-
const MenuBuilder = require('./menu');
15-
const path = require('path');
1613

1714
const {
1815
default: installExtension,
1916
REACT_DEVELOPER_TOOLS
2017
} = require('electron-devtools-installer');
2118
const debug = require('electron-debug');
2219

23-
const isDev = process.env.NODE_ENV === 'development';
20+
const Protocol = require('./protocol');
21+
// menu from another file to modularize the code
22+
const MenuBuilder = require('./menu');
23+
24+
const path = require('path');
25+
// const fs = require('fs');
26+
27+
console.log('NODE ENV is ', process.env.NODE_ENV);
28+
const isDev = process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test' ;
2429
const port = 8080;
2530
const selfHost = `http://localhost:${port}`;
2631

@@ -58,8 +63,8 @@ async function createWindow() {
5863
// icon: path.join(__dirname, '../src/public/icons/png/256x256.png'),
5964
webPreferences: {
6065
zoomFactor: 0.7,
61-
// enable devtools
62-
devTools: true,
66+
// enable devtools when in development mode
67+
devTools: isDev,
6368
// crucial security feature - blocks rendering process from having access to node moduels
6469
nodeIntegration: false,
6570
// web workers will not have access to node
@@ -189,11 +194,12 @@ app.on('ready', createWindow);
189194
app.on('window-all-closed', () => {
190195
// On macOS it is common for applications and their menu bar
191196
// to stay active until the user quits explicitly with Cmd + Q
192-
if (process.platform !== 'darwin') {
193-
app.quit();
194-
} else {
195-
ContextMenu.clearMainBindings(ipcMain);
196-
}
197+
// if (process.platform !== 'darwin') {
198+
// app.quit();
199+
// } else {
200+
// ContextMenu.clearMainBindings(ipcMain);
201+
// }
202+
app.quit();
197203
});
198204

199205
app.on('activate', () => {
@@ -214,8 +220,8 @@ app.on('web-contents-created', (event, contents) => {
214220
const parsedUrl = new URL(navigationUrl);
215221
const validOrigins = [
216222
selfHost,
217-
'http://localhost:8081',
218-
'http://reactype.heroku.com',
223+
'http://localhost:5000',
224+
'https://reactype.herokuapp.com',
219225
'https://github.com/'
220226
];
221227
// Log and prevent the app from navigating to a new page if that page's origin is not whitelisted
@@ -235,9 +241,8 @@ app.on('web-contents-created', (event, contents) => {
235241
//console.log('parsedUrl.origin is', parsedUrl.origin);
236242
const validOrigins = [
237243
selfHost,
238-
'http://localhost:8081',
239244
'http://localhost:5000',
240-
'http://reactype.heroku.com',
245+
'https://reactype.herokuapp.com',
241246
'https://github.com',
242247
'app://rse/'
243248
];
@@ -323,10 +328,16 @@ ipcMain.on('choose_app_dir', event => {
323328
.catch(err => console.log('ERROR on "choose_app_dir" event: ', err));
324329
});
325330

331+
// define serverURL for cookie and auth purposes based on environment
332+
let serverUrl = 'https://reactype.herokuapp.com';
333+
if (isDev) {
334+
serverUrl = 'http://localhost:5000';
335+
}
336+
326337
// for github oauth login in production, since cookies are not accessible through document.cookie on local filesystem, we need electron to grab the cookie that is set from oauth, this listens for an set cookie event from the renderer process then sends back the cookie
327338
ipcMain.on('set_cookie', event => {
328339
session.defaultSession.cookies
329-
.get({ url: 'https://reactype.heroku.com' })
340+
.get({ url: serverUrl })
330341
.then(cookie => {
331342
console.log(cookie);
332343
event.reply('give_cookie', cookie);
@@ -339,12 +350,47 @@ ipcMain.on('set_cookie', event => {
339350
// again for production, document.cookie is not accessible so we need this listener on main to delete the cookie on logout
340351
ipcMain.on('delete_cookie', event => {
341352
session.defaultSession.cookies
342-
.remove('https://reactype.heroku.com', 'ssid')
353+
.remove(serverUrl, 'ssid')
343354
.then(removed => {
344355
console.log('Cookies deleted', removed);
345356
})
346357
.catch(err => console.log('Error deleting cookie:', err));
347358
});
348359

349-
// bypass ssl certification validation error
350-
// app.commandLine.appendSwitch('ignore-certificate-errors', 'true');
360+
// opens new window for github oauth when button on signin page is clicked
361+
ipcMain.on('github', event => {
362+
// create new browserwindow object with size, title, security options
363+
const github = new BrowserWindow({
364+
width: 800,
365+
height: 600,
366+
title: 'Github Oauth',
367+
webPreferences: {
368+
nodeIntegration: false,
369+
nodeIntegrationInWorker: false,
370+
nodeIntegrationInSubFrames: false,
371+
contextIsolation: true,
372+
enableRemoteModule: false,
373+
zoomFactor: 1.0
374+
}
375+
});
376+
// redirects to relevant server endpoint
377+
github.loadURL(`${serverUrl}/github`);
378+
// show window
379+
github.show();
380+
// if final callback is reached and we get a redirect from server back to our app, close oauth window
381+
github.webContents.on('will-redirect', (e, callbackUrl) => {
382+
let redirectUrl = 'app://rse/';
383+
if (isDev) {
384+
redirectUrl = 'http://localhost:8080/';
385+
}
386+
if (callbackUrl === redirectUrl) {
387+
dialog.showMessageBox({
388+
type: 'info',
389+
title: 'ReacType',
390+
icon: resolve('app/src/public/icons/png/256x256.png'),
391+
message: 'Github Oauth Successful!'
392+
});
393+
github.close();
394+
}
395+
});
396+
});

app/electron/preload.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ const {
1111
setCookie,
1212
getCookie,
1313
delCookie,
14-
reload
14+
github
1515
} = require('./preloadFunctions/cookies');
1616

1717
// Expose protected methods that allow the renderer process to use select node methods
@@ -33,5 +33,6 @@ contextBridge.exposeInMainWorld('api', {
3333
writeFile,
3434
setCookie,
3535
getCookie,
36-
delCookie
36+
delCookie,
37+
github
3738
});

app/electron/preloadFunctions/cookies.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,8 @@ const delCookie = () => {
1414
return ipcRenderer.send('delete_cookie');
1515
};
1616

17-
module.exports = { setCookie, getCookie, delCookie };
17+
const github = () => {
18+
return ipcRenderer.send('github');
19+
};
20+
21+
module.exports = { setCookie, getCookie, delCookie, github };

app/src/components/login/SignIn.tsx

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,24 @@ const SignIn: React.FC<LoginInt & RouteComponentProps> = props => {
8080
const [invalidUser, setInvalidUser] = useState(false);
8181
const [invalidPass, setInvalidPass] = useState(false);
8282

83+
// this useEffect will check for cookies and set an item in localstorage for github Oauth session validation
84+
useEffect(() => {
85+
const githubCookie = setInterval(() => {
86+
window.api.setCookie();
87+
window.api.getCookie(cookie => {
88+
// if a cookie exists, set localstorage item with cookie data, clear interval, go back to '/' route to load app
89+
if (cookie[0]) {
90+
window.localStorage.setItem('ssid', cookie[0].value);
91+
clearInterval(githubCookie);
92+
props.history.push('/');
93+
// if an item is already set in localstorage (guest option or normal login) clear interval needs to be run or else this will constantly run
94+
} else if (window.localStorage.getItem('ssid')) {
95+
clearInterval(githubCookie);
96+
}
97+
});
98+
}, 2000);
99+
}, []);
100+
83101
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
84102
let inputVal = e.target.value;
85103
switch (e.target.name) {
@@ -188,10 +206,11 @@ const SignIn: React.FC<LoginInt & RouteComponentProps> = props => {
188206
helperText={invalidPassMsg}
189207
error={invalidPass}
190208
/>
209+
{/* **TODO** Make 'Remember Me' functional
191210
<FormControlLabel
192211
control={<Checkbox value="remember" color="primary" />}
193212
label="Remember me"
194-
/>
213+
/> */}
195214

196215
<Button
197216
fullWidth
@@ -203,25 +222,18 @@ const SignIn: React.FC<LoginInt & RouteComponentProps> = props => {
203222
Sign In
204223
</Button>
205224
{/* Hiding github oauth button as it's still buggy and not fully working */}
206-
{/* <Button
225+
<Button
207226
fullWidth
208227
variant="contained"
209228
color="default"
210229
className={classes.submit}
211-
href="https://reactype.heroku.com/github"
212230
onClick={() => {
213-
console.log('Inside onclick of github');
214-
setTimeout(() => {
215-
window.api.setCookie();
216-
window.api.getCookie(cookie => {
217-
window.localStorage.setItem('ssid', cookie[0].value);
218-
props.history.push('/');
219-
});
220-
}, 2000);
231+
// messages the main proces to open new window for github oauth
232+
window.api.github();
221233
}}
222234
>
223235
<GitHubIcon />
224-
</Button> */}
236+
</Button>
225237

226238
<Button
227239
fullWidth

app/src/helperFunctions/generateCode.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
import { Component, State, ChildElement } from '../interfaces/Interfaces';
22
import HTMLTypes from '../context/HTMLTypes';
33

4+
5+
6+
declare global {
7+
interface Window {
8+
api: any;
9+
}
10+
}
11+
412
// generate code based on the component heirarchy
513
const generateUnformattedCode = (
614
comps: Component[],
@@ -216,7 +224,21 @@ const generateUnformattedCode = (
216224

217225
// formats code with prettier linter
218226
const formatCode = (code: string) => {
219-
return window.api.formatCode(code);
227+
228+
// in test environment, window.api is not defined,
229+
// so we reference original prettier format function instead
230+
if (process.env.NODE_ENV === 'test') {
231+
const { format } = require('prettier');
232+
return format(code, {
233+
singleQuote: true,
234+
trailingComma: 'es5',
235+
bracketSpacing: true,
236+
jsxBracketSameLine: true,
237+
parser: 'babel'
238+
});
239+
} else {
240+
return window.api.formatCode(code);
241+
}
220242
};
221243

222244
// generate code based on component heirarchy and then return the rendered code

app/src/public/styles/style.css

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,8 @@ a.nav_link:hover {
311311
text-decoration: underline;
312312
}
313313

314+
/* Additional styling for ReacType X */
315+
314316
.componentDefault {
315317
width: 100%;
316318
border: 2px solid gray;

app/src/reducers/componentReducer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ const reducer = (state: State, action: Action) => {
133133
type,
134134
typeId,
135135
childId
136-
}: { type: string; typeId: number; childId: number } = action.payload;
136+
}: { type: string; typeId: number; childId: any} = action.payload;
137137
// the parent of the new child is whichever component that is currently focused on
138138
const parentComponentId: number = state.canvasFocus.componentId;
139139

app/src/utils/createNonce.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@ const { v4: uuidv4 } = require('uuid');
33
// Generate an arbitrary number
44
// this arbitrary number will be used in CspHtmlWebpackPlugin and HtmlWebpackPlugin configuration in webpack
55
module.exports = function() {
6-
return new Buffer(uuidv4()).toString('base64');
6+
return new Buffer.from(uuidv4()).toString('base64');
77
};

0 commit comments

Comments
 (0)