Skip to content

Commit 1a76601

Browse files
authored
Merge branch 'main' into realrevert
2 parents e7def14 + 75d6e78 commit 1a76601

File tree

5 files changed

+128
-42
lines changed

5 files changed

+128
-42
lines changed

app/src/components/main/Canvas.tsx

Lines changed: 86 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
1-
import React, { useContext } from 'react';
1+
import React, { useState, useContext } from 'react';
22
import { useDrop, DropTargetMonitor } from 'react-dnd';
33
import { ItemTypes } from '../../constants/ItemTypes';
44
import StateContext from '../../context/context';
55
import { Component, DragItem } from '../../interfaces/Interfaces';
66
import { combineStyles } from '../../helperFunctions/combineStyles';
77
import renderChildren from '../../helperFunctions/renderChildren';
8+
import List from '@material-ui/core/List';
9+
import ListItem from '@material-ui/core/ListItem';
10+
import ListItemText from '@material-ui/core/ListItemText';
11+
import createModal from '../right/createModal';
812

913
const findNestedChild = (curr, components) => {
1014
components.forEach((comp, i) => {
@@ -13,17 +17,18 @@ const findNestedChild = (curr, components) => {
1317
});
1418
if (comp.children.length !== 0) findNestedChild(curr, comp.children);
1519
});
20+
1621
};
1722

1823
function Canvas() {
24+
const [modal, setModal] = useState(null);
25+
1926
const [state, dispatch] = useContext(StateContext);
2027
// find the current component to render on the canvas
2128
const currentComponent: Component = state.components.find(
2229
(elem: Component) => elem.id === state.canvasFocus.componentId
2330
);
2431

25-
findNestedChild(currentComponent, state.components);
26-
2732
// changes focus of the canvas to a new component / child
2833
const changeFocus = (componentId: number, childId: number | null) => {
2934
dispatch({ type: 'CHANGE FOCUS', payload: { componentId, childId } });
@@ -36,6 +41,48 @@ function Canvas() {
3641
changeFocus(state.canvasFocus.componentId, null);
3742
}
3843

44+
const closeModal = () => setModal(null);
45+
46+
// creates modal that asks if user wants to clear workspace
47+
// if user clears their workspace, then their components are removed from state and the modal is closed
48+
const triedToNestIncorrectly = () => {
49+
// set modal options
50+
const children = (
51+
<List className="export-preference">
52+
<ListItem
53+
key={`gotIt${state.canvasFocus.componentId}`}
54+
button
55+
onClick={closeModal}
56+
style={{
57+
border: '1px solid #3f51b5',
58+
marginBottom: '2%',
59+
marginTop: '5%'
60+
}}
61+
>
62+
<ListItemText
63+
primary={'Got it'}
64+
style={{ textAlign: 'center' }}
65+
onClick={closeModal}
66+
/>
67+
</ListItem>
68+
</List>
69+
);
70+
71+
// create modal
72+
setModal(
73+
createModal({
74+
closeModal,
75+
children,
76+
message: 'Unable to nest component in another component that contains that component.',
77+
primBtnLabel: null,
78+
primBtnAction: null,
79+
secBtnAction: null,
80+
secBtnLabel: null,
81+
open: true
82+
})
83+
);
84+
};
85+
3986
// This hook will allow the user to drag items from the left panel on to the canvas
4087
const [{ isOver }, drop] = useDrop({
4188
accept: ItemTypes.INSTANCE,
@@ -45,26 +92,41 @@ function Canvas() {
4592
return;
4693
}
4794

48-
// if item dropped is going to be a new instance (i.e. it came from the left panel), then create a new child component
49-
if (item.newInstance) {
50-
dispatch({
51-
type: 'ADD CHILD',
52-
payload: {
53-
type: item.instanceType,
54-
typeId: item.instanceTypeId,
55-
childId: null
56-
}
57-
});
95+
const runReducers = () => {
96+
if (item.newInstance) {
97+
dispatch({
98+
type: 'ADD CHILD',
99+
payload: {
100+
type: item.instanceType,
101+
typeId: item.instanceTypeId,
102+
childId: null
103+
}
104+
});
105+
}
106+
// if item is not a new instance, change position of element dragged inside div so that the div is the new parent
107+
else {
108+
dispatch({
109+
type: 'CHANGE POSITION',
110+
payload: {
111+
currentChildId: item.childId,
112+
newParentChildId: null
113+
}
114+
});
115+
}
58116
}
59-
// if item is not a new instance, change position of element dragged inside div so that the div is the new parent
60-
else {
61-
dispatch({
62-
type: 'CHANGE POSITION',
63-
payload: {
64-
currentChildId: item.childId,
65-
newParentChildId: null
66-
}
67-
});
117+
118+
const addingComponent = state.components.find(elem => elem.id === item.instanceTypeId);
119+
120+
if (item.instanceType === "HTML Element") {
121+
return runReducers();
122+
} else if (item.instanceType === 'Route Link') {
123+
return runReducers();
124+
} else if (checkChildren([addingComponent], currentComponent)) {
125+
triedToNestIncorrectly();
126+
return;
127+
} else {
128+
// if item dropped is going to be a new instance (i.e. it came from the left panel), then create a new child component
129+
return runReducers();
68130
}
69131
},
70132
collect: monitor => ({
@@ -84,10 +146,12 @@ function Canvas() {
84146
// The render children function renders all direct children of a given component
85147
// Direct children are draggable/clickable
86148

149+
87150
const canvasStyle = combineStyles(defaultCanvasStyle, currentComponent.style);
88151
return (
89152
<div ref={drop} style={canvasStyle} onClick={onClickHandler}>
90153
{renderChildren(currentComponent.children)}
154+
{modal}
91155
</div>
92156
);
93157
}

app/src/components/main/DirectChildComponent.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ function DirectChildComponent({ childId, type, typeId, style }: ChildElement) {
125125
placeHolder={HTMLDefaultPlaceholder}
126126
linkId={null}
127127
key={
128-
'indChild' +
128+
'indChildHTML' +
129129
child.childId.toString() +
130130
child.typeId.toString()
131131
}
@@ -138,7 +138,7 @@ function DirectChildComponent({ childId, type, typeId, style }: ChildElement) {
138138
placeHolder={HTMLDefaultPlaceholder}
139139
linkId={null}
140140
key={
141-
'indChild' +
141+
'indChildNest' +
142142
child.childId.toString() +
143143
child.typeId.toString()
144144
}
@@ -155,7 +155,7 @@ function DirectChildComponent({ childId, type, typeId, style }: ChildElement) {
155155
return (
156156
<IndirectChild
157157
key={
158-
'indChild' + child.childId.toString() + child.typeId.toString()
158+
'RouteLink' + child.childId.toString() + child.typeId.toString()
159159
}
160160
style={combinedStyle}
161161
placeHolder=""

app/src/context/HTMLTypes.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ const HTMLTypes: HTMLType[] = [
6666
tag: 'a',
6767
name: 'Link',
6868
style: { border: 'none' },
69-
placeHolderShort: <a href="">Link</a>,
69+
placeHolderShort: <a href="#">Link</a>,
7070
placeHolderLong: '',
7171
icon: LinkIcon
7272
},

app/src/helperFunctions/renderChildren.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ const renderChildren = (children: ChildElement[]) => {
2424
type={type}
2525
typeId={typeId}
2626
style={style}
27-
key={'DirChild' + childId.toString()}
27+
key={'DirChildComp' + childId.toString() + name}
2828
name={child.name}
2929
/>
3030
);
@@ -37,7 +37,7 @@ const renderChildren = (children: ChildElement[]) => {
3737
type={type}
3838
typeId={typeId}
3939
style={style}
40-
key={'DirChild' + childId.toString()}
40+
key={'DirChildHTML' + childId.toString() + name}
4141
name={child.name}
4242
/>
4343
);
@@ -51,7 +51,7 @@ const renderChildren = (children: ChildElement[]) => {
5151
typeId={typeId}
5252
style={style}
5353
children={children}
54-
key={'DirChild' + childId.toString()}
54+
key={'DirChildHTMLNest' + childId.toString() + name}
5555
name={child.name}
5656
/>
5757
);
@@ -66,7 +66,7 @@ const renderChildren = (children: ChildElement[]) => {
6666
typeId={typeId}
6767
style={style}
6868
children={children}
69-
key={'DirChild' + childId.toString()}
69+
key={'RouteLink' + childId.toString() + name}
7070
name={child.name}
7171
/>
7272
);

app/src/reducers/componentReducer.ts

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,7 @@ const reducer = (state: State, action: Action) => {
257257

258258
const parentComponentId: number = state.canvasFocus.componentId;
259259
const components = [...state.components];
260+
updateAllIds(components);
260261

261262
// find component that we're adding a child to
262263
const parentComponent = findComponent(components, parentComponentId);
@@ -327,7 +328,11 @@ const reducer = (state: State, action: Action) => {
327328
componentId: state.canvasFocus.componentId,
328329
childId: newChild.childId
329330
};
330-
const nextChildId = state.nextChildId + 1;
331+
332+
let nextChildId: number = 1;
333+
for (let i = 0; i < parentComponent.children.length; i+=1) {
334+
nextChildId +=1;
335+
}
331336
return { ...state, components, nextChildId, canvasFocus };
332337
}
333338
// move an instance from one position in a component to another position in a component
@@ -371,17 +376,23 @@ const reducer = (state: State, action: Action) => {
371376
state.HTMLTypes
372377
);
373378

374-
return { ...state, components };
379+
let nextChildId: number = 1;
380+
for (let i = 0; i < component.children.length; i+=1) {
381+
nextChildId +=1;
382+
}
383+
updateAllIds(components);
384+
return { ...state, components, nextChildId };
375385
}
376386
// Change the focus component and child
377387
case 'CHANGE FOCUS': {
378388
const {
379389
componentId,
380390
childId
381391
}: { componentId: number; childId: number | null } = action.payload;
382-
383-
const canvasFocus = { ...state.canvasFocus, componentId, childId };
384-
return { ...state, canvasFocus };
392+
const canvasFocus = { componentId, childId };
393+
const components = [...state.components];
394+
updateAllIds(components);
395+
return { ...state, canvasFocus, components };
385396
}
386397
case 'UPDATE CSS': {
387398
const { style } = action.payload;
@@ -407,7 +418,7 @@ const reducer = (state: State, action: Action) => {
407418
case 'DELETE CHILD': {
408419
// if in-focus instance is a top-level component and not a child, don't delete anything
409420

410-
if (!state.canvasFocus.childId) return state;
421+
// if (!state.canvasFocus.childId) return state;
411422

412423
// find the current component in focus
413424
const components = [...state.components];
@@ -432,15 +443,23 @@ const reducer = (state: State, action: Action) => {
432443
state.HTMLTypes
433444
);
434445

435-
const canvasFocus = { ...state.canvasFocus, childId: null };
436-
return { ...state, components, canvasFocus };
446+
let nextChildId: number = 1;
447+
for (let i = 0; i < component.children.length; i+=1) {
448+
nextChildId +=1;
449+
}
450+
451+
let childId: null | number = ((state.canvasFocus.childId - 1) === 0) ? null : state.canvasFocus.childId - 1;
452+
const canvasFocus = { ...state.canvasFocus, childId };
453+
updateAllIds(components);
454+
return { ...state, components, canvasFocus, nextChildId };
437455
}
438456

439457
case 'DELETE PAGE': {
440458
const id: number = state.canvasFocus.componentId;
441459
const name: string = state.components[id - 1].name;
442460

443461
const components: Component[] = deleteById(id, name);
462+
444463
// rebuild rootComponents with correct page IDs
445464
const rootComponents = updateRoots(components);
446465
const canvasFocus = { componentId: 1, childId: null };
@@ -455,10 +474,10 @@ const reducer = (state: State, action: Action) => {
455474
const rootComponents: number[] = updateRoots(components);
456475

457476
// iterate over the length of the components array
458-
for (let i = 0; i < components.length; i++) {
477+
components.forEach((el, i) => {
459478
// for each components' code, run the generateCode function to
460479
// update the code preview on the app
461-
components[i].code = generateCode(
480+
el.code = generateCode(
462481
components,
463482
components[i].id,
464483
rootComponents,
@@ -467,6 +486,7 @@ const reducer = (state: State, action: Action) => {
467486
);
468487
}
469488

489+
470490
const canvasFocus = { componentId: 1, childId: null };
471491

472492
return {
@@ -554,13 +574,14 @@ const reducer = (state: State, action: Action) => {
554574

555575
case 'OPEN PROJECT': {
556576
convertToJSX(action.payload.HTMLTypes);
577+
// action.payload.canvasFocus = { ...action.payload.canvasFocus, childId: null}
557578
return {
558579
...action.payload
559580
};
560581
}
561582

562583
case 'ADD ELEMENT': {
563-
const HTMLTypes = [...state.HTMLTypes];
584+
const HTMLTypes: HTMLType[] = [...state.HTMLTypes];
564585
HTMLTypes.push(action.payload);
565586
return {
566587
...state,
@@ -589,7 +610,8 @@ const reducer = (state: State, action: Action) => {
589610
})
590611
return {
591612
...state,
592-
HTMLTypes
613+
HTMLTypes,
614+
components
593615
};
594616
}
595617

0 commit comments

Comments
 (0)