Skip to content

Commit 639f1c7

Browse files
authored
Merge pull request #177 from oslabs-beta/master
Beta to OSLabs Launch Merge
2 parents 30fbc7c + f67c7e0 commit 639f1c7

24 files changed

+862
-249
lines changed

README.md

+20-5
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ Download for [MacOS](https://github.com/team-reactype/ReacType/releases), [Windo
2424

2525
### How to use
2626

27-
- **Sign-in page**: Sign up for an account, sign in via Github, or just continue as a guest. Registered users enjoy additional project-saving functionality.
27+
- **Sign-in page**: Sign up for an account or just continue as a guest. Registered users enjoy additional project-saving functionality.
2828
- **Tutorial**: Click ‘Tutorial’ from the Help tab’s dropdown menu (at the top left of the application) to view a tutorial.
2929
- **Start a project (only after registration)**: Registered users can create a new project and select whether they want their project to be a Next.js, Gatsby.js, or classic React project. Also, registered users can save projects to return to them at a later time.
3030
- **Add Components**: Create components on the right panel. Components can be associated with a route, or they can be used within other components.
@@ -34,6 +34,7 @@ Download for [MacOS](https://github.com/team-reactype/ReacType/releases), [Windo
3434
- **Create Instances on the Canvas**: Each component has its own canvas. Add an element to a component by dragging it onto the canvas. Div components are arbitrarily nestable and useful for complex layouts. Next.js and Gatsby.js projects have Link components to enable client-side navigation to other routes.
3535
- **Component Tree**: Click on the Component Tree tab next to the Code Preview tab to view the component tree hierarchy.
3636
- **Update Styling**: Select an element on the canvas to update its basic style attributes on the right panel. As you create new instances and add styling, watch as your code dynamically generates in the code preview in the bottom panel.
37+
- **Using State in Elements**: As of 9.0.0, you can now select an HTML element on the canvas and then navigate to the customization panel to click a button to pass a variable from state into your element's text or link field.
3738
- **User Preference Features**: With the click of a button, toggle between light mode and dark mode, depending on your preference.
3839
- **Export project**: Click the “Export Project’ button to export the project’s application files into a TypeScript file. The exported project is fully functional with Webpack, Express server, routing, etc., and will match what is mocked on the canvas.
3940
- **Export project with Tests**: Click the "includes tests" checkbox while exporting to include pre-configured Webpack, Jest, and Typescript files along with tests for your project.
@@ -43,11 +44,17 @@ Download for [MacOS](https://github.com/team-reactype/ReacType/releases), [Windo
4344
- Modernized and cleaner UI, including enhanced dark mode
4445
- Tutorial has been updated to reflect other modifications
4546

46-
**New with version 8.0.0:**
47+
**New with version 9.0.0:**
4748

4849
![CSSEditor](https://raw.githubusercontent.com/open-source-labs/ReacType/master/resources/export_tests_images/export-new.gif)
4950

50-
### Features
51+
### 9.0.0 New Features
52+
- **React Router**: Drag-and-drop LinkTo and Router elements (located below the HTML elements list) to implement fully-functional React Router components into your application to dynamically and quickly render components in the live demo render and in your exported application.
53+
- **Global State Management**: For the first time in ReacType history, users can utilize
54+
- **Composite Data Structures in State**: State creation in ReacType can now handle composite data types, which includes arrays, objects, and any amount of nesting of composite data types within other composite data types (i.e. arrays of objects and objects with objects as values).
55+
- **Additional Improvements with Local State Management**:
56+
- **Annotations**:
57+
5158

5259
- **OAuth via Github**: Sign up with your github accounts.
5360
- **Live Render Demo**: Live render demo in React using Electron's sandbox environment. Updates in realtime to reflect canvas structure and customization options.
@@ -81,7 +88,7 @@ Download for [MacOS](https://github.com/team-reactype/ReacType/releases), [Windo
8188
- Delete Project: Command + Backspace
8289
- Open Project: Command + o
8390

84-
**Windows**:
91+
**Windows**:
8592
- Export Project: Control + e
8693
- Undo: Control + z
8794
- Redo: Control + Shift + z
@@ -90,7 +97,7 @@ Download for [MacOS](https://github.com/team-reactype/ReacType/releases), [Windo
9097
- Delete HTML Tag on Canvas: Backspace
9198
- Delete Project: Control + Backspace
9299
- Open Project: Control + o
93-
100+
94101
#### Contributors
95102

96103
[Alex Yu](https://www.linkedin.com/in/alexjihunyu/) [@buddhajjigae](https://github.com/buddhajjigae)
@@ -111,8 +118,12 @@ Download for [MacOS](https://github.com/team-reactype/ReacType/releases), [Windo
111118

112119
[Chelsey Fewer](https://www.linkedin.com/in/chelsey-fewer/) [@chelseyeslehc](https://github.com/chelseyeslehc)
113120

121+
[Chris Tang] (https://www.linkedin.com/in/chrisjtang/) [@chrisjtang](https://github.com/chrisjtang)
122+
114123
[Christian Padilla](https://linkedin.com/in/ChristianEdwardPadilla) [@ChristianEdwardPadilla](https://github.com/ChristianEdwardPadilla)
115124

125+
[Crystal Lim] (https://linkedin.com/in/crystallim) [@crlim](https://github.com/crlim)
126+
116127
[Danial Reilley](https://linkedin.com/in/daniel-reilley)
117128
[@dreille](https://github.com/dreille)
118129

@@ -156,6 +167,8 @@ Download for [MacOS](https://github.com/team-reactype/ReacType/releases), [Windo
156167
[Philip Hua](https://www.linkedin.com/in/philip-minh-hua)
157168
[@pmhua](https://github.com/pmhua)
158169

170+
[Ron Fu] (https://www.linkedin.com/in/ronfu)[@rfvisuals] (https://github.com/rfvisuals)
171+
159172
[Sean Sadykoff](https://www.linkedin.com/in/sean-sadykoff/) [@sean1292](https://github.com/sean1292)
160173

161174
[Shana Hoehn](https://www.linkedin.com/in/shana-hoehn-70297b169/) [@slhoehn](https://github.com/slhoehn)
@@ -172,6 +185,8 @@ Download for [MacOS](https://github.com/team-reactype/ReacType/releases), [Windo
172185

173186
[Tyler Sullberg](https://www.linkedin.com/in/tyler-sullberg) [@tsully](https://github.com/tsully)
174187

188+
[William Cheng] (https://www.linkedin.com/in/william-cheng-0723/) [@williamcheng12345](https://github.com/WilliamCheng12345)
189+
175190
[William Rittwage](https://www.linkedin.com/in/william-rittwage)
176191
[@wbrittwage](https://github.com/wbrittwage)
177192

app/electron/main.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ async function createWindow() {
7373
webPreferences: {
7474
zoomFactor: 0.7,
7575
// enable devtools when in development mode
76-
devTools: isDev,
76+
devTools: true,
7777
// crucial security feature - blocks rendering process from having access to node modules
7878
nodeIntegration: false,
7979
// web workers will not have access to node
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import React, {useRef, useState, useContext, useEffect } from 'react';
2+
import Modal from '@material-ui/core/Modal';
3+
import StateContext from '../../context/context';
4+
import TableStateProps from '../right/TableStateProps';
5+
6+
function UseStateModal({ updateAttributeWithState, attributeToChange, childId }) {
7+
const [state, dispatch] = useContext(StateContext);
8+
const [open, setOpen] = useState(false);
9+
const [displayObject, setDisplayObject] = useState(null)
10+
const [stateKey, setStateKey] = useState('');
11+
const [statePropsId, setStatePropsId] = useState(-1);
12+
const [componentProviderId, setComponentProviderId] = useState(1);
13+
14+
// make tabs to choose which component to get state from
15+
const componentTabs = [];
16+
for (let i = 0; i < state.components.length; i ++) {
17+
componentTabs.push(<button
18+
onClick={() => {
19+
setComponentProviderId(i+1);
20+
setDisplayObject(null);
21+
setStateKey('');
22+
}}>
23+
{state.components[i].name}
24+
</button>)
25+
}
26+
27+
// table to choose state from
28+
const body = (
29+
<div className="useState-position">
30+
<div className="useState-header">
31+
<span>Choose State Source</span>
32+
<button
33+
style={{ margin: '5px 5px' ,padding: '1px', float: 'right' }}
34+
onClick={() => {
35+
setStateKey('');
36+
setStatePropsId(-1);
37+
setDisplayObject(null)
38+
setOpen(false)}}
39+
>
40+
X
41+
</button>
42+
</div>
43+
<div className="useState-window">
44+
<div className="useState-dropdown">
45+
{componentTabs}
46+
</div>
47+
<div className="useState-stateDisplay">
48+
<TableStateProps
49+
providerId = {componentProviderId}
50+
canDeleteState = {false}
51+
displayObject = {displayObject}
52+
selectHandler={(table) => {
53+
// if object or array => show sub table
54+
if (table.row.type === "object") {
55+
if (statePropsId < 0) setStatePropsId(table.row.id);
56+
setStateKey(stateKey + table.row.key + '.');
57+
setDisplayObject(table.row.value);
58+
} else if (table.row.type === "array") {
59+
if (statePropsId < 0) setStatePropsId(table.row.id);
60+
setStateKey(stateKey + table.row.key)
61+
setDisplayObject(table.row.value);
62+
} else {
63+
// if not object or array => update state
64+
setDisplayObject(null);
65+
updateAttributeWithState(attributeToChange, componentProviderId, statePropsId > 0 ? statePropsId : table.row.id, table.row, stateKey + table.row.key);
66+
setStateKey('')
67+
setStatePropsId(-1);
68+
setOpen(false);
69+
}
70+
}}
71+
deleteHandler={() => func()}
72+
isThemeLight={true}
73+
/>
74+
</div>
75+
</div>
76+
</div>
77+
);
78+
79+
return (
80+
<div>
81+
<button className="useState-btn" onClick={() => setOpen(true)}>USE STATE</button>
82+
<Modal open={open}>{body}</Modal>
83+
</div>
84+
);
85+
}
86+
87+
export default UseStateModal;

app/src/components/left/DragDropPanel.tsx

+34-13
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ Central state contains all available HTML elements (stored in the HTMLTypes prop
1414
initialState.tsx.
1515
1616
Hook state:
17-
-tag:
17+
-tag:
1818
*/
1919
// Extracted the drag and drop functionality from HTMLPanel to make a modular component that can hang wherever the future designers may choose.
2020
const DragDropPanel = (props): JSX.Element => {
@@ -37,25 +37,46 @@ const DragDropPanel = (props): JSX.Element => {
3737
payload: id
3838
});
3939
};
40-
40+
4141
// filter out separator so that it will not appear on the html panel
42-
const htmlTypesToRender = state.HTMLTypes.filter(type => type.name !== 'separator');
42+
const htmlTypesToRender = state.HTMLTypes.filter(type => type.name !== 'separator' && type.name !== 'Route');
4343
return (
4444
<div className="HTMLItems">
4545
<div id="HTMLItemsTopHalf">
4646
<Grid
4747
id="HTMLItemsGrid"
4848
>
49-
{htmlTypesToRender.map(option => (
50-
<HTMLItem
51-
name={option.name}
52-
key={`html-${option.name}`}
53-
id={option.id}
54-
Icon={option.icon}
55-
handleDelete={handleDelete}
56-
isThemeLight={isThemeLight}
57-
/>
58-
))}
49+
<h3>HTML ELEMENTS</h3>
50+
{htmlTypesToRender.map(option => {
51+
if(option.id !== 17 && option.id !== 18) {
52+
return (
53+
<HTMLItem
54+
name={option.name}
55+
key={`html-${option.name}`}
56+
id={option.id}
57+
Icon={option.icon}
58+
handleDelete={handleDelete}
59+
isThemeLight={isThemeLight}
60+
/>
61+
);
62+
}
63+
64+
})}
65+
<h3>REACT ROUTER</h3>
66+
{htmlTypesToRender.map(option => {
67+
if(option.id === 17 || option.id === 18) {
68+
return (
69+
<HTMLItem
70+
name={option.name}
71+
key={`html-${option.name}`}
72+
id={option.id}
73+
Icon={option.icon}
74+
handleDelete={handleDelete}
75+
isThemeLight={isThemeLight}
76+
/>
77+
);
78+
}
79+
})}
5980
</Grid>
6081
</div>
6182
</div>

app/src/components/left/HTMLItem.tsx

+5-5
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ const useStyles = makeStyles({
3535
darkThemeFontColor: {
3636
color: '#fff'
3737
}
38-
38+
3939
});
4040

4141
const HTMLItem : React.FC<{
@@ -45,9 +45,9 @@ const HTMLItem : React.FC<{
4545
handleDelete: (id: number) => void;
4646
isThemeLight: boolean;
4747
}> = ({ name, id, Icon, handleDelete, isThemeLight }) => {
48-
48+
4949
const classes = useStyles();
50-
50+
5151
const [modal, setModal] = useState(null);
5252
const [{ isDragging }, drag] = useDrag({
5353
item: {
@@ -122,11 +122,11 @@ const HTMLItem : React.FC<{
122122
// updated the id's to reflect the new element types input and label
123123
return ( // HTML Elements
124124
<Grid item xs={5} key={`html-g${name}`}>
125-
{ id <= 16 &&
125+
{ id <= 18 &&
126126
<div ref={drag} className={isThemeLight ? `${classes.HTMLPanelItem} ${classes.lightThemeFontColor}` : `${classes.HTMLPanelItem} ${classes.darkThemeFontColor}`} id="HTMLItem">
127127
<h3>{name}</h3>
128128
</div>}
129-
{id > 16 &&
129+
{id > 18 &&
130130
<span id="customHTMLElement">
131131
<div ref={drag} className={isThemeLight ? `${classes.HTMLPanelItem} ${classes.lightThemeFontColor}` : `${classes.HTMLPanelItem} ${classes.darkThemeFontColor}`} id="HTMLItem">
132132
<h3>{name}</h3>

app/src/components/main/AddRoute.tsx

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { AddRoutes } from '../../interfaces/Interfaces'
2+
import React, {
3+
useRef, useState, useContext, useEffect,
4+
} from 'react';
5+
import StateContext from '../../context/context';
6+
7+
function AddRoute({
8+
id,
9+
name
10+
}: AddRoutes) {
11+
const [state, dispatch] = useContext(StateContext);
12+
13+
const handleClick = (id) => {
14+
dispatch({
15+
type: 'ADD CHILD',
16+
payload: {
17+
type: 'HTML Element',
18+
typeId: -1,
19+
childId: id // this is the id of the parent to attach it to
20+
}
21+
});
22+
}
23+
24+
return (
25+
<div style={{ padding: '1px', float: 'right' }}>
26+
<button id={'routeBtn' + id} onClick={() => handleClick(id)}>+</button>
27+
</div>
28+
);
29+
}
30+
31+
export default AddRoute;

app/src/components/main/Annotation.tsx

+4-4
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ function Annotation({
3636
};
3737

3838
/**
39-
* Handles when text exists in the textarea of the modal.
39+
* Handles when text exists in the textarea of the modal.
4040
* If text exists/does not exist, corresponding button changes colors.
4141
* Sets hook value to what is contained in the textarea
4242
*/
@@ -53,7 +53,7 @@ function Annotation({
5353
}
5454

5555
/**
56-
* This handler will find the specific anno for the corresponding component on the canvas in the childrenArray -
56+
* This handler will find the specific anno for the corresponding component on the canvas in the childrenArray -
5757
* where the canvas components are placed
5858
*/
5959
const handleFindAnno = (array, id) => {
@@ -65,7 +65,7 @@ function Annotation({
6565
} else if (currentElement.children.length > 0) {
6666
// temp is to prevent a return of empty string since canvas element should always exist and allows the
6767
// recursion to continue
68-
const temp = handleFindAnno(currentElement.children, id)
68+
const temp = handleFindAnno(currentElement.children, id)
6969
if (temp != '') {
7070
return temp;
7171
}
@@ -84,7 +84,7 @@ function Annotation({
8484
}
8585
handleAnnoChange(event);
8686
}, [])
87-
87+
8888
const body = (
8989
<div className='annotate-position'>
9090
<span className='annotate-textarea-header'> Notes for: {name} ( {id} )</span>

app/src/components/main/Canvas.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,18 @@ function Canvas() {
1616
const currentComponent: Component = state.components.find(
1717
(elem: Component) => elem.id === state.canvasFocus.componentId
1818
);
19-
19+
2020
// changes focus of the canvas to a new component / child
2121
const changeFocus = (componentId?: number, childId?: number | null) => {
2222
dispatch({ type: 'CHANGE FOCUS', payload: { componentId, childId } });
2323
};
2424
// onClickHandler is responsible for changing the focused component and child component
2525
function onClickHandler(event) {
2626
event.stopPropagation();
27-
// note: a null value for the child id means that we are focusing on the top-level component rather than any child
27+
// note: a null value for the child id means that we are focusing on the top-level component rather than any child
2828
changeFocus(state.canvasFocus.componentId, null);
2929
};
30-
30+
3131
// stores a snapshot of state into the past array for UNDO. snapShotFunc is also invoked for nestable elements in DirectChildHTMLNestable.tsx
3232
const snapShotFunc = () => {
3333
// make a deep clone of state

0 commit comments

Comments
 (0)