Skip to content

Commit 7329a36

Browse files
authored
Merge pull request #1 from oslabs-beta/feat/Switch
Feat/switch
2 parents 9383573 + 039dbcf commit 7329a36

File tree

11 files changed

+97
-29
lines changed

11 files changed

+97
-29
lines changed

app/src/components/left/DragDropPanel.tsx

Lines changed: 3 additions & 3 deletions
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,9 +37,9 @@ 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">

app/src/components/main/AddRoute.tsx

Lines changed: 31 additions & 0 deletions
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

Lines changed: 4 additions & 4 deletions
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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ 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 } });
@@ -27,7 +27,7 @@ function Canvas() {
2727
// 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
@@ -50,6 +50,7 @@ function Canvas() {
5050
}
5151
// if item dropped is going to be a new instance (i.e. it came from the left panel), then create a new child component
5252
if (item.newInstance) {
53+
console.log('Canvas first dispatch')
5354
dispatch({
5455
type: 'ADD CHILD',
5556
payload: {

app/src/components/main/DirectChildHTMLNestable.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import renderChildren from '../../helperFunctions/renderChildren';
99
import Annotation from './Annotation'
1010
import validateNewParent from '../../helperFunctions/changePositionValidation'
1111
import componentNest from '../../helperFunctions/componentNestValidation'
12+
// import addRoute from '../../helperFunctions/addRoute';
13+
import AddRoute from './AddRoute';
1214

1315
function DirectChildHTMLNestable({
1416
childId,
@@ -79,7 +81,7 @@ const snapShotFunc = () => {
7981
childId: childId,
8082
}
8183
});
82-
}
84+
}
8385
}
8486
// if item is not a new instance, change position of element dragged inside div so that the div is the new parent
8587
else {
@@ -95,7 +97,7 @@ const snapShotFunc = () => {
9597
}
9698
}
9799
},
98-
100+
99101
collect: (monitor: any) => {
100102
return {
101103
isOver: !!monitor.isOver({ shallow: true })
@@ -132,10 +134,16 @@ const snapShotFunc = () => {
132134

133135
drag(drop(ref));
134136

137+
const routeButton = [];
138+
if (typeId === 17) {
139+
routeButton.push(<AddRoute id={childId} name={name} />);
140+
}
141+
135142
return (
136143
<div onClick={onClickHandler} style={combinedStyle} ref={ref} id={`canv${childId}`}>
137144
<strong>{HTMLType.placeHolderShort}</strong>
138145
{` ( ${childId} )`}
146+
{routeButton}
139147
<Annotation
140148
id={childId}
141149
name={name}

app/src/components/main/SeparatorChild.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ function DirectChildHTMLNestable({
6464
childId: childId,
6565
}
6666
});
67-
}
67+
}
6868
}
6969
// if item is not a new instance, change position of element dragged inside separator so that separator is new parent (until replacement)
7070
else {

app/src/context/HTMLTypes.tsx

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -155,15 +155,24 @@ const HTMLTypes: HTMLType[] = [
155155
placeHolderShort: 'list item',
156156
placeHolderLong: '',
157157
icon: ListIcon
158-
},
158+
},
159159
{
160160
id: 17,
161161
tag: 'Switch',
162162
name: 'Switch',
163163
style: {},
164-
placeHolderShort: 'switch item',
164+
placeHolderShort: 'Switch',
165165
placeHolderLong: '',
166-
icon: ListIcon
166+
icon: HeaderIcon
167+
},
168+
{
169+
id: -1,
170+
tag: 'Route',
171+
name: 'Route',
172+
style: {},
173+
placeHolderShort: 'Route',
174+
placeHolderLong: '',
175+
icon: LinkIcon
167176
}
168177
];
169178

app/src/helperFunctions/generateCode.ts

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,14 @@ const generateUnformattedCode = (
5959
referencedHTML.tag === 'ul' ||
6060
referencedHTML.tag === 'ol' ||
6161
referencedHTML.tag === 'menu' ||
62-
referencedHTML.tag === 'li'
62+
referencedHTML.tag === 'li' ||
63+
referencedHTML.tag === 'Switch' ||
64+
referencedHTML.tag === 'Route'
6365
) {
6466
child.children = getEnrichedChildren(child);
6567
}
68+
// when we see a Switch, import React Router
69+
if (referencedHTML.tag === 'Switch') importReactRouter = true;
6670
return child;
6771
} else if (child.type === 'Route Link') {
6872
links = true;
@@ -89,7 +93,7 @@ const generateUnformattedCode = (
8993
// function to dynamically add classes, ids, and styles to an element if it exists.
9094
const elementTagDetails = (childElement: object) => {
9195
let customizationDetails = "";
92-
if (childElement.childId) customizationDetails += (' ' + `id="${+childElement.childId}"`);
96+
if (childElement.childId && childElement.tag !== 'Route') customizationDetails += (' ' + `id="${+childElement.childId}"`);
9397
if (childElement.attributes && childElement.attributes.cssClasses) customizationDetails += (' ' + `className="${childElement.attributes.cssClasses}"`);
9498
if (childElement.style && Object.keys(childElement.style).length > 0) customizationDetails +=(' ' + formatStyles(childElement));
9599
return customizationDetails;
@@ -120,8 +124,9 @@ const generateUnformattedCode = (
120124
childElement.tag === 'ol' ||
121125
childElement.tag === 'ul' ||
122126
childElement.tag === 'menu' ||
123-
childElement.tag === 'li';
124-
// childElement.tag === 'Switch';
127+
childElement.tag === 'li' ||
128+
childElement.tag === 'Switch' ||
129+
childElement.tag === 'Route';
125130

126131
if (childElement.tag === 'img') {
127132
return `${levelSpacer(level, 5)}<${childElement.tag} src="${activeLink}" ${elementTagDetails(childElement)}/>${levelSpacer(2, (3 + level))}`;
@@ -130,7 +135,8 @@ const generateUnformattedCode = (
130135
} else if (childElement.tag === 'input') {
131136
return `${levelSpacer(level, 5)}<${childElement.tag}${elementTagDetails(childElement)}></${childElement.tag}>${levelSpacer(2, (3 + level))}`;
132137
} else if (nestable) {
133-
return `${levelSpacer(level, 5)}<${childElement.tag}${elementTagDetails(childElement)}>${innerText}
138+
const routePath = (childElement.tag === 'Route') ? (' ' + 'exact path="' + activeLink + '"') : '';
139+
return `${levelSpacer(level, 5)}<${childElement.tag}${elementTagDetails(childElement)}${routePath}>${innerText}
134140
${tabSpacer(level)}${writeNestedElements(childElement.children, level + 1)}
135141
${tabSpacer(level - 1)}</${childElement.tag}>${levelSpacer(2, (3 + level))}`;
136142
} else if (childElement.tag !== 'separator'){
@@ -195,12 +201,14 @@ const generateUnformattedCode = (
195201

196202
const stateful = true;
197203
const classBased = false;
204+
let importReactRouter;
198205

199206
// create final component code. component code differs between classic react, next.js, gatsby.js
200207
// classic react code
201208
if (projectType === 'Classic React') {
202209
return `
203210
${stateful && !classBased ? `import React, {useState} from 'react';` : ''}
211+
${importReactRouter ? `import { BrowserRouter as Router, Route, Switch, Link } from 'react-router-dom';`: ``}
204212
${classBased ? `import React, {Component} from 'react';` : ''}
205213
${!stateful && !classBased ? `import React from 'react';` : ''}
206214
${importsMapped}
@@ -209,7 +217,6 @@ const generateUnformattedCode = (
209217
? `class ${currentComponent.name} extends Component {`
210218
: `const ${currentComponent.name} = (props: any): JSX.Element => {`
211219
}
212-
213220
${
214221
stateful && !classBased
215222
? `const [value, setValue] = useState<any | undefined>("INITIAL VALUE")${writeStateProps(currentComponent.useStateCodes)};
@@ -225,13 +232,18 @@ const generateUnformattedCode = (
225232
: ``
226233
}
227234
${classBased ? `render(): JSX.Element {` : ``}
228-
229-
return (
235+
${!importReactRouter ?
236+
`return (
237+
<div className="${currentComponent.name}" style={props.style}>
238+
${writeNestedElements(enrichedChildren)}
239+
</div>
240+
);` : `return (
241+
<Router>
230242
<div className="${currentComponent.name}" style={props.style}>
231243
${writeNestedElements(enrichedChildren)}
232244
</div>
233-
);
234-
}
245+
</Router>
246+
);`}
235247
${classBased ? `}` : ``}
236248
export default ${currentComponent.name};
237249
`;

app/src/helperFunctions/renderChildren.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ const renderChildren = (children: ChildElement[]) => {
1818
if (name === '') child.name = state.components[typeId - 1].name;
1919
// A DirectChildComponent is an instance of a top level component
2020
// This component will render IndirectChild components (div/components rendered inside a child component)
21-
// Removed style from prop drills so that styling isn't applied to canvas items.
21+
// Removed style from prop drills so that styling isn't applied to canvas items.
2222
// Also added keys & removed an unnecessary div around DirChildNestables that were causing errors.
2323
if (type === 'Component') {
2424
return (
@@ -34,7 +34,7 @@ const renderChildren = (children: ChildElement[]) => {
3434
}
3535
// ommitted orderedlists, unorderedlists, and menus, ommitted li items as non-nestable types because they can be nested within.
3636
// child is a non-nestable type of HTML element (everything except for divs and forms)
37-
else if (type === 'HTML Element' && typeId !== 11 && typeId !== 1000 && typeId !== 2 && typeId !== 3 && typeId !== 14 && typeId !== 15 && typeId !== 16 && typeId != 17) {
37+
else if (type === 'HTML Element' && typeId !== 11 && typeId !== 1000 && typeId !== 2 && typeId !== 3 && typeId !== 14 && typeId !== 15 && typeId !== 16 && typeId !== 17 && typeId !== -1) {
3838
return (
3939
<DirectChildHTML
4040
childId={childId}
@@ -48,8 +48,8 @@ const renderChildren = (children: ChildElement[]) => {
4848
}
4949
// Added Orderedlists, Unorderedlists, and Menus, changed lists to nestable because they are nestable.
5050
// child is a nestable type of HTML element (divs and forms)
51-
else if (type === 'HTML Element' && (typeId === 11 || typeId === 2 || typeId === 3 || typeId === 14 || typeId === 15 || typeId === 16 || typeId === 17)) {
52-
return (
51+
else if (type === 'HTML Element' && (typeId === 11 || typeId === 2 || typeId === 3 || typeId === 14 || typeId === 15 || typeId === 16 || typeId === 17 || typeId === -1)) {
52+
return (
5353
<DirectChildHTMLNestable
5454
childId={childId}
5555
type={type}

app/src/interfaces/Interfaces.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,3 +99,8 @@ export interface StatePropsPanelProps {
9999
selectHandler: (table: any) => void;
100100
deleteHandler: (id: number | any) => void;
101101
}
102+
103+
export interface AddRoutes {
104+
id: number;
105+
name: string;
106+
}

app/src/reducers/componentReducer.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
import initialState from '../context/initialState';
99
import generateCode from '../helperFunctions/generateCode';
1010
import manageSeparators from '../helperFunctions/manageSeparators';
11+
import addRoute from '../helperFunctions/addRoute';
1112

1213
let separator = initialState.HTMLTypes[1];
1314

@@ -308,6 +309,7 @@ const reducer = (state: State, action: Action) => {
308309
children: []
309310
};
310311

312+
311313
// if the childId is null, this signifies that we are adding a child to the top-level component rather than another child element
312314
// we also add a separator before any new child
313315
// if the newChild Element is an input or img type, delete the children key/value pair

0 commit comments

Comments
 (0)