From 5ca0ac7f6f68a9567a1802e39c121006ecc8ccc2 Mon Sep 17 00:00:00 2001 From: Jesse Zuniga Date: Tue, 10 Mar 2020 17:19:53 -0700 Subject: [PATCH] Added stateful toggle for all components --- src/actionTypes/index.js | 3 +- src/actions/components.ts | 173 +++++++----- src/components/LeftColExpansionPanel.tsx | 47 ++-- src/containers/AppContainer.tsx | 33 ++- src/containers/LeftContainer.tsx | 23 +- src/reducers/componentReducer.ts | 22 +- src/utils/Interfaces.ts | 1 + src/utils/componentReducer.util.ts | 324 ++++++++++++++++------- src/utils/componentRender.util.ts | 24 +- src/utils/htmlElements.util.ts | 20 +- 10 files changed, 425 insertions(+), 245 deletions(-) diff --git a/src/actionTypes/index.js b/src/actionTypes/index.js index 3aea099d1..2db963099 100644 --- a/src/actionTypes/index.js +++ b/src/actionTypes/index.js @@ -4,6 +4,7 @@ export const ADD_CHILD = 'ADD_CHILD'; export const DELETE_CHILD = 'DELETE_CHILD'; export const UPDATE_COMPONENT = 'UPDATE_COMPONENT'; export const DELETE_COMPONENT = 'DELETE_COMPONENT'; +export const TOGGLE_STATE = 'TOGGLE_STATE'; export const CHANGE_FOCUS_COMPONENT = 'CHANGE_FOCUS_COMPONENT'; export const CHANGE_COMPONENT_FOCUS_CHILD = 'CHANGE_COMPONENT_FOCUS_CHILD'; export const CHANGE_FOCUS_CHILD = 'CHANGE_FOCUS_CHILD'; @@ -26,4 +27,4 @@ export const ADD_PROP = 'ADD_PROP'; export const DELETE_ALL_DATA = 'DELETE_ALL_DATA'; export const CHANGE_IMAGE_PATH = 'CHANGE_IMAGE_PATH'; export const UPDATE_HTML_ATTR = 'UPDATE_HTML_ATTR'; -export const UPDATE_CHILDREN_SORT = 'UPDATE_CHILDREN_SORT' \ No newline at end of file +export const UPDATE_CHILDREN_SORT = 'UPDATE_CHILDREN_SORT'; diff --git a/src/actions/components.ts b/src/actions/components.ts index 32a28dd77..21df0e430 100644 --- a/src/actions/components.ts +++ b/src/actions/components.ts @@ -1,5 +1,8 @@ import { - ComponentInt, ComponentsInt, PropInt, ChildInt, + ComponentInt, + ComponentsInt, + PropInt, + ChildInt } from '../utils/Interfaces.ts'; import { @@ -8,6 +11,7 @@ import { ADD_CHILD, DELETE_CHILD, DELETE_COMPONENT, + TOGGLE_STATE, CHANGE_FOCUS_COMPONENT, CHANGE_FOCUS_CHILD, CHANGE_COMPONENT_FOCUS_CHILD, @@ -24,7 +28,7 @@ import { ADD_PROP, DELETE_ALL_DATA, UPDATE_HTML_ATTR, - UPDATE_CHILDREN_SORT, + UPDATE_CHILDREN_SORT } from '../actionTypes/index.js'; import { loadState } from '../localStorage'; @@ -32,26 +36,30 @@ import createFiles from '../utils/createFiles.util.ts'; import createApplicationUtil from '../utils/createApplication.util.ts'; export const loadInitData = () => (dispatch: any) => { - loadState().then((data: any) => dispatch({ - type: LOAD_INIT_DATA, - payload: { - data: data ? data.workspace : {}, - }, - })); + loadState().then((data: any) => + dispatch({ + type: LOAD_INIT_DATA, + payload: { + data: data ? data.workspace : {} + } + }) + ); }; -export const addComponent = ({ title }: { title: string }) => (dispatch: any) => { +export const addComponent = ({ title }: { title: string }) => ( + dispatch: any +) => { dispatch({ type: ADD_COMPONENT, payload: { title } }); }; export const addChild = ({ title, childType, - HTMLInfo, + HTMLInfo }: { -title: string; -childType: string; -HTMLInfo: object; + title: string; + childType: string; + HTMLInfo: object; }) => (dispatch: any) => { dispatch({ type: ADD_CHILD, payload: { title, childType, HTMLInfo } }); }; @@ -63,10 +71,10 @@ export const deleteChild = ({}) => (dispatch: any) => { export const deleteComponent = ({ componentId, - stateComponents, + stateComponents }: { -componentId: number; -stateComponents: ComponentsInt; + componentId: number; + stateComponents: ComponentsInt; }) => (dispatch: any) => { // find all places where the "to be deleted" is a child and do what u gotta do stateComponents.forEach((parent: ComponentInt) => { @@ -78,8 +86,8 @@ stateComponents: ComponentsInt; payload: { parentId: parent.id, childId: child.childId, - calledFromDeleteComponent: true, - }, + calledFromDeleteComponent: true + } }); }); }); @@ -90,25 +98,29 @@ stateComponents: ComponentsInt; dispatch({ type: DELETE_COMPONENT, payload: { componentId } }); }; -export const changeFocusComponent = ({ title }: { title: string }) => (dispatch: any) => { +export const changeFocusComponent = ({ title }: { title: string }) => ( + dispatch: any +) => { dispatch({ type: CHANGE_FOCUS_COMPONENT, payload: { title } }); }; // make sure childId is being sent in -export const changeFocusChild = ({ childId }: { childId: number }) => (dispatch: any) => { +export const changeFocusChild = ({ childId }: { childId: number }) => ( + dispatch: any +) => { dispatch({ type: CHANGE_FOCUS_CHILD, payload: { childId } }); }; export const changeComponentFocusChild = ({ componentId, - childId, + childId }: { -componentId: number; -childId: number; + componentId: number; + childId: number; }) => (dispatch: any) => { dispatch({ type: CHANGE_COMPONENT_FOCUS_CHILD, - payload: { componentId, childId }, + payload: { componentId, childId } }); }; @@ -116,40 +128,47 @@ export const exportFiles = ({ components, path, appName, - exportAppBool, + exportAppBool }: { -components: ComponentsInt; -path: string; -appName: string; -exportAppBool: boolean; + components: ComponentsInt; + path: string; + appName: string; + exportAppBool: boolean; }) => (dispatch: any) => { // this dispatch sets the global state property 'loading' to true until the createFiles call resolves below dispatch({ - type: EXPORT_FILES, + type: EXPORT_FILES }); createFiles(components, path, appName, exportAppBool) - .then(dir => dispatch({ - type: EXPORT_FILES_SUCCESS, - payload: { status: true, dir: dir[0] }, - })) - .catch(err => dispatch({ - type: EXPORT_FILES_ERROR, - payload: { status: true, err }, - })); + .then(dir => + dispatch({ + type: EXPORT_FILES_SUCCESS, + payload: { status: true, dir: dir[0] } + }) + ) + .catch(err => + dispatch({ + type: EXPORT_FILES_ERROR, + payload: { status: true, err } + }) + ); }; export const handleClose = () => ({ type: HANDLE_CLOSE, - payload: false, + payload: false }); export const handleTransform = ( componentId: number, childId: number, { - x, y, width, height, - }: { x: number; y: number; width: number; height: number }, + x, + y, + width, + height + }: { x: number; y: number; width: number; height: number } ) => ({ type: HANDLE_TRANSFORM, payload: { @@ -158,8 +177,8 @@ export const handleTransform = ( x, y, width, - height, - }, + height + } }); export const createApplication = ({ @@ -167,13 +186,13 @@ export const createApplication = ({ components = [], genOption, appName = 'reactype_app', - exportAppBool, + exportAppBool }: { -path: string; -components: ComponentsInt; -genOption: number; -appName: string; -exportAppBool: boolean; + path: string; + components: ComponentsInt; + genOption: number; + appName: string; + exportAppBool: boolean; }) => (dispatch: any) => { if (genOption === 0) { exportAppBool = false; @@ -182,72 +201,84 @@ exportAppBool: boolean; appName, path, components, - exportAppBool, - }), + exportAppBool + }) ); } else if (genOption) { exportAppBool = true; dispatch({ - type: CREATE_APPLICATION, + type: CREATE_APPLICATION }); createApplicationUtil({ path, appName, - genOption, + genOption // exportAppBool }) .then(() => { dispatch({ - type: CREATE_APPLICATION_SUCCESS, + type: CREATE_APPLICATION_SUCCESS }); dispatch( exportFiles({ appName, path, components, - exportAppBool, - }), + exportAppBool + }) ); }) - .catch(err => dispatch({ - type: CREATE_APPLICATION_ERROR, - payload: { status: true, err }, - })); + .catch(err => + dispatch({ + type: CREATE_APPLICATION_ERROR, + payload: { status: true, err } + }) + ); } }; export const openExpansionPanel = (component: ComponentInt) => ({ type: OPEN_EXPANSION_PANEL, - payload: { component }, + payload: { component } }); export const deleteAllData = () => ({ - type: DELETE_ALL_DATA, + type: DELETE_ALL_DATA }); export const deleteProp = (propId: number) => (dispatch: any) => { dispatch({ type: DELETE_PROP, payload: propId }); }; +export const toggleComponentState = (index: string) => (dispatch: any) => { + dispatch({ type: TOGGLE_STATE, payload: index }); +}; + export const addProp = (prop: PropInt) => ({ type: ADD_PROP, - payload: { ...prop }, + payload: { ...prop } }); -export const updateHtmlAttr = ({ attr, value }: { attr: string; value: string }) => ( - dispatch: any, -) => { +export const updateHtmlAttr = ({ + attr, + value +}: { + attr: string; + value: string; +}) => (dispatch: any) => { dispatch({ type: UPDATE_HTML_ATTR, - payload: { attr, value }, + payload: { attr, value } }); }; -export const updateChildrenSort = ({ newSortValues }: { newSortValues: any }) => ( - dispatch: any, -) => { +export const updateChildrenSort = ({ + newSortValues +}: { + newSortValues: any; +}) => (dispatch: any) => { dispatch({ type: UPDATE_CHILDREN_SORT, - payload: { newSortValues }, + payload: { newSortValues } }); }; diff --git a/src/components/LeftColExpansionPanel.tsx b/src/components/LeftColExpansionPanel.tsx index f301ece9b..f28a4d6cc 100644 --- a/src/components/LeftColExpansionPanel.tsx +++ b/src/components/LeftColExpansionPanel.tsx @@ -10,13 +10,12 @@ import AddIcon from '@material-ui/icons/Add'; import DeleteIcon from '@material-ui/icons/Delete'; import Button from '@material-ui/core/Button'; import Tooltip from '@material-ui/core/Tooltip'; -import Switch from '@material-ui/core/Switch'; // for state toggling +import Switch from '@material-ui/core/Switch'; // for state/class toggling import InputLabel from '@material-ui/core/InputLabel'; // labeling of state/class toggles -import Select from '@material-ui/core/Select'; // for Class/Functional drop down -import MenuItem from '@material-ui/core/MenuItem'; // for drop down item selections // import { ComponentInt, ComponentsInt, ChildInt } from '../utils/Interfaces'; // unused +// TODO: ASSIGN SPECIFIC TYPING TO INCOMING PROPS (REMOVE ANY) const LeftColExpansionPanel = (props: any) => { const { classes, @@ -26,8 +25,10 @@ const LeftColExpansionPanel = (props: any) => { changeFocusComponent, selectableChildren, components, - deleteComponent + deleteComponent, + toggleComponentState } = props; + const { title, id, color } = component; function isFocused() { @@ -66,6 +67,7 @@ const LeftColExpansionPanel = (props: any) => { {title} + {/* TOGGLE FOR STATEFULNESS */} { State? ONCHANGE FUNCTION PENDING ON STATE REDUCER - // updateComponent(id, { stateful: e.target.checked }) - // } + onChange={e => toggleComponentState(props.id)} value='stateful' color='primary' - id='stateful' + id={props.id.toString()} + // id={props.index.toString()} />
+ {/* TOGGLE FOR CLASS BASED */} { fontSize: '18px' }} > - Component Type + Class? - + ONCHANGE FUNCTION PENDING ON CLASS REDUCER + // updateComponent(id, { classBased: e.target.checked }) + // } + value='classBased' + color='primary' + id={props.index.toString()} + />
} diff --git a/src/containers/AppContainer.tsx b/src/containers/AppContainer.tsx index 71732f6c0..18e0875b7 100644 --- a/src/containers/AppContainer.tsx +++ b/src/containers/AppContainer.tsx @@ -1,12 +1,12 @@ -import React, { Component } from "react"; -import { connect } from "react-redux"; -import { MuiThemeProvider } from "@material-ui/core/styles"; -import LinearProgress from "@material-ui/core/LinearProgress"; -import LeftContainer from "./LeftContainer.tsx"; -import MainContainer from "./MainContainer.tsx"; -import theme from "../components/theme.ts"; -import { loadInitData } from "../actions/components.ts"; -import { ComponentInt, ComponentsInt } from "../utils/Interfaces.ts"; +import React, { Component } from 'react'; +import { connect } from 'react-redux'; +import { MuiThemeProvider } from '@material-ui/core/styles'; +import LinearProgress from '@material-ui/core/LinearProgress'; +import LeftContainer from './LeftContainer'; +import MainContainer from './MainContainer'; +import theme from '../components/theme'; +import { loadInitData } from '../actions/components'; +import { ComponentInt, ComponentsInt } from '../utils/Interfaces'; type Props = { components: ComponentsInt; @@ -50,7 +50,7 @@ class AppContainer extends Component { // uses component childIds and parentIds arrays (numbers) to build component-filled children and parents arrays return ( -
+
{ {loading ? (
- +
) : null}
@@ -75,7 +75,4 @@ class AppContainer extends Component { } } -export default connect( - mapStateToProps, - mapDispatchToProps -)(AppContainer); +export default connect(mapStateToProps, mapDispatchToProps)(AppContainer); diff --git a/src/containers/LeftContainer.tsx b/src/containers/LeftContainer.tsx index 88fe83f87..5711a1ab1 100644 --- a/src/containers/LeftContainer.tsx +++ b/src/containers/LeftContainer.tsx @@ -11,12 +11,12 @@ import List from '@material-ui/core/List'; import ListItem from '@material-ui/core/ListItem'; import ListItemText from '@material-ui/core/ListItemText'; import Fab from '@material-ui/core/Fab'; -import LeftColExpansionPanel from '../components/LeftColExpansionPanel.tsx'; -import HTMLComponentPanel from '../components/HTMLComponentPanel.tsx'; -import * as actions from '../actions/components.ts'; -import { ComponentInt, ComponentsInt, ChildInt } from '../utils/Interfaces.ts'; -import createModal from '../utils/createModal.util.tsx'; -import cloneDeep from '../utils/cloneDeep.ts'; +import LeftColExpansionPanel from '../components/LeftColExpansionPanel'; +import HTMLComponentPanel from '../components/HTMLComponentPanel'; +import * as actions from '../actions/components'; +import { ComponentInt, ComponentsInt, ChildInt } from '../utils/Interfaces'; +import createModal from '../utils/createModal.util'; +import cloneDeep from '../utils/cloneDeep'; const IPC = require('electron').ipcRenderer; @@ -32,6 +32,7 @@ interface PropsInt { deleteComponent: any; createApp: any; deleteAllData: any; + toggleComponentState: any; } interface StateInt { @@ -64,6 +65,8 @@ const mapDispatchToProps = (dispatch: any) => ({ componentId: number; stateComponents: ComponentsInt; }) => dispatch(actions.deleteComponent({ componentId, stateComponents })), + toggleComponentState: (id: string) => + dispatch(actions.toggleComponentState(id)), deleteAllData: () => dispatch(actions.deleteAllData()), createApp: ({ path, @@ -121,6 +124,8 @@ class LeftContainer extends Component { handleAddComponent = () => { this.props.addComponent({ title: this.state.componentName }); + + // reset the currently added componentName state field to blank after adding this.setState({ componentName: '' }); @@ -201,7 +206,8 @@ class LeftContainer extends Component { addChild, changeFocusComponent, changeFocusChild, - selectableChildren + selectableChildren, + toggleComponentState } = this.props; const { componentName, modal } = this.state; @@ -220,6 +226,7 @@ class LeftContainer extends Component { selectableChildren={selectableChildren} deleteComponent={deleteComponent} components={components} + toggleComponentState={toggleComponentState} /> )); @@ -235,7 +242,7 @@ class LeftContainer extends Component { { ...state, ...action.payload.data, loading: false, - appDir: "", + appDir: '', successOpen: false, errorOpen: false }; @@ -118,6 +120,8 @@ const componentReducer = (state = initialApplicationState, action: any) => { return deleteChild(state, action.payload); case DELETE_COMPONENT: return deleteComponent(state, action.payload); + case TOGGLE_STATE: + return toggleComponentState(state, action.payload); case CHANGE_FOCUS_COMPONENT: return changeFocusComponent(state, action.payload); case CHANGE_FOCUS_CHILD: diff --git a/src/utils/Interfaces.ts b/src/utils/Interfaces.ts index 057372700..490ff8c07 100644 --- a/src/utils/Interfaces.ts +++ b/src/utils/Interfaces.ts @@ -30,6 +30,7 @@ export interface ChildrenInt extends Array {} export interface ComponentInt { id: number; stateful: boolean; + // class: boolean; title: string; color: string; props: PropInt[]; diff --git a/src/utils/componentReducer.util.ts b/src/utils/componentReducer.util.ts index 61940f098..1bb3f9a1e 100644 --- a/src/utils/componentReducer.util.ts +++ b/src/utils/componentReducer.util.ts @@ -1,9 +1,15 @@ -import getSelectable from './getSelectable.util.ts'; -import getColor from './colors.util.ts'; -import { getSize } from './htmlElements.util.ts'; -import cloneDeep from './cloneDeep.ts'; -import { ComponentInt, ApplicationStateInt, ChildrenInt, ChildInt, ComponentsInt, PropInt } from './Interfaces.ts'; - +import getSelectable from './getSelectable.util'; +import getColor from './colors.util'; +import { getSize } from './htmlElements.util'; +import cloneDeep from './cloneDeep'; +import { + ComponentInt, + ApplicationStateInt, + ChildrenInt, + ChildInt, + ComponentsInt, + PropInt +} from './Interfaces'; const initialComponentState: ComponentInt = { id: 0, @@ -16,31 +22,38 @@ const initialComponentState: ComponentInt = { x: 25, y: 25, width: 800, - height: 550, + height: 550 }, childrenArray: [], nextChildId: 1, - focusChildId: 0, + focusChildId: 0 }; -export const addComponent = (state: ApplicationStateInt, { title }: { title: string }) => { +export const addComponent = ( + state: ApplicationStateInt, + { title }: { title: string } +) => { // remove whitespace and digits, capitalize first char const strippedTitle = title .replace(/[a-z]+/gi, word => word[0].toUpperCase() + word.slice(1)) .replace(/[-_\s0-9\W]+/gi, ''); // duplicate component names not allowed - if (state.components.find((comp: ComponentInt) => comp.title === strippedTitle)) { - window.alert(`A component with the name: "${strippedTitle}" already exists.\n Please think of another name.`); + if ( + state.components.find((comp: ComponentInt) => comp.title === strippedTitle) + ) { + window.alert( + `A component with the name: "${strippedTitle}" already exists.\n Please think of another name.` + ); return { - ...state, + ...state }; } // empty component name not allowed if (strippedTitle === '') { return { - ...state, + ...state }; } @@ -52,7 +65,7 @@ export const addComponent = (state: ApplicationStateInt, { title }: { title: str title: strippedTitle, id: componentId, color: componentColor, - childrenArray: [], + childrenArray: [] }; const components = [...state.components, newComponent]; @@ -60,7 +73,9 @@ export const addComponent = (state: ApplicationStateInt, { title }: { title: str const totalComponents = state.totalComponents + 1; const nextId = state.nextId + 1; - const selectableChildren = state.components.map(comp => comp.id).filter(id => id !== newComponent.id); + const selectableChildren = state.components + .map(comp => comp.id) + .filter(id => id !== newComponent.id); const ancestors: Array = []; @@ -74,13 +89,17 @@ export const addComponent = (state: ApplicationStateInt, { title }: { title: str focusComponent: newComponent, focusChild: newFocusChild, ancestors, - selectableChildren, // new component so everyone except yourself is available + selectableChildren // new component so everyone except yourself is available }; }; export const addChild = ( state: ApplicationStateInt, - { title, childType = '', HTMLInfo = {} }: { title: string; childType: string; HTMLInfo: object }, + { + title, + childType = '', + HTMLInfo = {} + }: { title: string; childType: string; HTMLInfo: object } ) => { const strippedTitle = title; @@ -95,7 +114,9 @@ export const addChild = ( // view represents the curretn FOCUSED COMPONENT - this is the component where the child is being added to // we only add childrent (or do any action) to the focused omconent - const view: ComponentInt = state.components.find(comp => comp.title === state.focusComponent.title); + const view: ComponentInt = state.components.find( + comp => comp.title === state.focusComponent.title + ); // parentComponent is the component this child is generated from (ex. instance of Box has comp of Box) let parentComponent; @@ -115,7 +136,9 @@ export const addChild = ( htmlElemPosition = getSize(htmlElement); // if above function doesnt reutn anything, it means html element is not in our database if (!htmlElemPosition.width) { - console.log(`Did not add html child: ${htmlElement} the GetSize function indicated that it isnt in our DB`); + console.log( + `Did not add html child: ${htmlElement} the GetSize function indicated that it isnt in our DB` + ); return; } } @@ -126,13 +149,13 @@ export const addChild = ( x: view.position.x + ((view.nextChildId * 16) % 150), // new children are offset by some amount, map of 150px y: view.position.y + ((view.nextChildId * 16) % 150), width: parentComponent.position.width - 1, // new children have an initial position of their CLASS (maybe don't need 90%) - height: parentComponent.position.height - 1, + height: parentComponent.position.height - 1 } : { x: view.position.x + view.nextChildId * 16, y: view.position.y + view.nextChildId * 16, width: htmlElemPosition.width, - height: htmlElemPosition.height, + height: htmlElemPosition.height }; const newChild: ChildInt = { @@ -144,7 +167,7 @@ export const addChild = ( position: newPosition, color: null, // parentComponent.color, // only relevant fot children of type COMPONENT htmlElement, // only relevant fot children of type HTML - HTMLInfo, + HTMLInfo }; const compsChildrenArr = [...view.childrenArray, newChild]; @@ -153,27 +176,31 @@ export const addChild = ( ...view, childrenArray: compsChildrenArr, focusChildId: newChild.childId, - nextChildId: view.nextChildId + 1, + nextChildId: view.nextChildId + 1 }; const components = [ ...state.components.filter(comp => { if (comp.title !== view.title) return comp; }), - component, + component ]; return { ...state, components, focusChild: newChild, - focusComponent: component, // refresh the focus component so we have the new child + focusComponent: component // refresh the focus component so we have the new child }; }; export const deleteChild = ( state: ApplicationStateInt, - { parentId = state.focusComponent.id, childId = state.focusChild.childId, calledFromDeleteComponent = false }, + { + parentId = state.focusComponent.id, + childId = state.focusChild.childId, + calledFromDeleteComponent = false + } ) => { /** ************************************************ if no parameters are provided we default to delete the FOCUSED CHILD of the FOCUSED COMPONENTS @@ -192,11 +219,15 @@ export const deleteChild = ( window.alert('Cannot delete root child of a component'); return state; } - // make a DEEP copy of the parent component (the one thats about to loose a child) - const parentComponentCopy: any = cloneDeep(state.components.find(c => c.id === parentId)); + // make a DEEP copy of the parent component (the one thats about to lose a child) + const parentComponentCopy: any = cloneDeep( + state.components.find(c => c.id === parentId) + ); - // delete the CHILD from the copied array - const indexToDelete = parentComponentCopy.childrenArray.findIndex((elem: ChildInt) => elem.childId === childId); + // delete the CHILD from the copied array + const indexToDelete = parentComponentCopy.childrenArray.findIndex( + (elem: ChildInt) => elem.childId === childId + ); if (indexToDelete < 0) { return window.alert('No such child component found'); } @@ -209,17 +240,20 @@ export const deleteChild = ( const modifiedComponentArray = [ ...state.components.filter(c => c.id !== parentId), // all elements besides the one just changed - parentComponentCopy, + parentComponentCopy ]; return { ...state, components: modifiedComponentArray, - focusComponent: calledFromDeleteComponent ? state.focusComponent : parentComponentCopy, // when called from delete component we dont need want to touch the focus + focusComponent: calledFromDeleteComponent + ? state.focusComponent + : parentComponentCopy, // when called from delete component we dont need want to touch the focus focusChild: calledFromDeleteComponent ? cloneDeep(state.initialApplicationFocusChild) - : parentComponentCopy.childrenArray[parentComponentCopy.childrenArray.length - 1] || - cloneDeep(state.initialApplicationFocusChild), // guard in case final child is deleted + : parentComponentCopy.childrenArray[ + parentComponentCopy.childrenArray.length - 1 + ] || cloneDeep(state.initialApplicationFocusChild) // guard in case final child is deleted }; }; @@ -231,7 +265,7 @@ export const handleTransform = ( x, y, width, - height, + height }: { componentId: number; childId: number; @@ -239,7 +273,7 @@ export const handleTransform = ( y: number; width: number; height: number; - }, + } ) => { if (childId === -1) { // the pseudochild has been transformed, its position is stored in the component @@ -250,15 +284,15 @@ export const handleTransform = ( x: x || component.position.x, y: y || component.position.y, width: width || component.position.width, - height: height || component.position.height, - }, + height: height || component.position.height + } }; const components = [ ...state.components.filter(comp => { if (comp.id !== componentId) return comp; }), - transformedComponent, + transformedComponent ]; return { ...state, components }; } @@ -274,15 +308,17 @@ export const handleTransform = ( x: x || child.position.x, y: y || child.position.y, width: width || child.position.width, - height: height || child.position.height, - }, + height: height || child.position.height + } }; const children = [ - ...state.components.find(comp => comp.id === componentId).childrenArray.filter(child => { - if (child.childId !== childId) return child; - }), - transformedChild, + ...state.components + .find(comp => comp.id === componentId) + .childrenArray.filter(child => { + if (child.childId !== childId) return child; + }), + transformedChild ]; let newFocusChild = state.focusChild; @@ -293,29 +329,36 @@ export const handleTransform = ( const component = { ...state.components.find(comp => comp.id === componentId), childrenArray: children, - focusChild: newFocusChild, + focusChild: newFocusChild }; const components: ComponentsInt = [ ...state.components.filter(comp => { if (comp.id !== componentId) return comp; }), - component, + component ]; return { ...state, components, - focusChild: newFocusChild, + focusChild: newFocusChild }; }; //Reducer that deletes the component selected -export const deleteComponent = (state: ApplicationStateInt, { componentId }: { componentId: number }) => { +export const deleteComponent = ( + state: ApplicationStateInt, + { componentId }: { componentId: number } +) => { //select the component from list of components - const compName = state.components.filter((value: ComponentInt) => value.id === componentId ); + const compName = state.components.filter( + (value: ComponentInt) => value.id === componentId + ); //confimation window to see if user really wants to delete component - const result = window.confirm(`Are you sure you want to delete ${compName[0].title}?`); + const result = window.confirm( + `Are you sure you want to delete ${compName[0].title}?` + ); //if cancelled, return focus to current selected component if (!result) { return { @@ -327,12 +370,14 @@ export const deleteComponent = (state: ApplicationStateInt, { componentId }: { c //is this really necessary if the App component is disabled from being deleted? -Tony if (componentId === 1) { return { - ...state, + ...state }; } //finds index of component to delete - const indexToDelete = state.components.findIndex((comp:ComponentInt) => comp.id == componentId); + const indexToDelete = state.components.findIndex( + (comp: ComponentInt) => comp.id == componentId + ); //creates a deep copy of the components const componentsCopy = cloneDeep(state.components); @@ -344,24 +389,50 @@ export const deleteComponent = (state: ApplicationStateInt, { componentId }: { c return { ...state, totalComponents, - components: componentsCopy, + components: componentsCopy + }; +}; + +//Reducer that toggles the component statefulness +export const toggleComponentState = ( + state: ApplicationStateInt, + id: number +) => { + //creates a deep copy of the components array + const componentCopy = cloneDeep(state.components); + + //iterate array, and invert statefulness for targeted component based on id prop + componentCopy.forEach((element: ComponentInt) => { + if (element.id === id) { + element.stateful = !element.stateful; + } + }); + + // return state and updated components array + return { + ...state, + components: componentCopy }; }; export const changeFocusComponent = ( state: ApplicationStateInt, - { title = state.focusComponent.title }: { title: string }, + { title = state.focusComponent.title }: { title: string } ) => { /** **************** * if the prm TITLE is a blank Object it means REFRESH focusd Components. * sometimes we update state like adding Children/Props etc and we want those changes to be reflected in focus component ************************************************* */ - const newFocusComp: ComponentInt = state.components.find(comp => comp.title === title); + const newFocusComp: ComponentInt = state.components.find( + comp => comp.title === title + ); // set the "focus child" to the focus child of this particular component . let newFocusChild: ChildInt | any; // check if the components has a child saved as a Focus child if (newFocusComp.focusChildId > 0) { - newFocusChild = newFocusComp.childrenArray.find(child => child.childId === newFocusComp.focusChildId); + newFocusChild = newFocusComp.childrenArray.find( + child => child.childId === newFocusComp.focusChildId + ); } if (!newFocusChild) { @@ -375,13 +446,20 @@ export const changeFocusComponent = ( focusComponent: newFocusComp, selectableChildren: result.selectableChildren, ancestors: result.ancestors, - focusChild: newFocusChild, + focusChild: newFocusChild }; }; -export const changeFocusChild = (state: ApplicationStateInt, { childId }: { childId: number }) => { - const focComp = state.components.find(comp => comp.title === state.focusComponent.title); - let newFocusChild: ChildInt = focComp.childrenArray.find(child => child.childId === childId); +export const changeFocusChild = ( + state: ApplicationStateInt, + { childId }: { childId: number } +) => { + const focComp = state.components.find( + comp => comp.title === state.focusComponent.title + ); + let newFocusChild: ChildInt = focComp.childrenArray.find( + child => child.childId === childId + ); if (!newFocusChild) { newFocusChild = { @@ -392,92 +470,114 @@ export const changeFocusChild = (state: ApplicationStateInt, { childId }: { chil x: focComp.position.x, y: focComp.position.y, width: focComp.position.width, - height: focComp.position.height, + height: focComp.position.height }, childSort: 0, color: focComp.color, childType: '', htmlElement: '', - HTMLInfo: {}, + HTMLInfo: {} }; } return { ...state, - focusChild: newFocusChild, + focusChild: newFocusChild }; }; export const changeComponentFocusChild = ( state: ApplicationStateInt, - { componentId, childId }: { componentId: number; childId: number }, + { componentId, childId }: { componentId: number; childId: number } ) => { - const component: ComponentInt = state.components.find(comp => comp.id === componentId); + const component: ComponentInt = state.components.find( + comp => comp.id === componentId + ); const modifiedComponent: any = cloneDeep(component); modifiedComponent.focusChildId = childId; - const components: ComponentsInt = state.components.filter(comp => comp.id !== componentId); + const components: ComponentsInt = state.components.filter( + comp => comp.id !== componentId + ); return { ...state, - components: [modifiedComponent, ...components], + components: [modifiedComponent, ...components] }; }; -export const exportFilesSuccess = (state: ApplicationStateInt, { status, dir }: { status: boolean; dir: string }) => ({ +export const exportFilesSuccess = ( + state: ApplicationStateInt, + { status, dir }: { status: boolean; dir: string } +) => ({ ...state, successOpen: status, appDir: dir, - loading: false, + loading: false }); -export const exportFilesError = (state: ApplicationStateInt, { status, err }: { status: boolean; err: string }) => ({ +export const exportFilesError = ( + state: ApplicationStateInt, + { status, err }: { status: boolean; err: string } +) => ({ ...state, errorOpen: status, appDir: err, - loading: false, + loading: false }); export const handleClose = (state: ApplicationStateInt, status: string) => ({ ...state, errorOpen: status, - successOpen: status, + successOpen: status }); -export const openExpansionPanel = (state: ApplicationStateInt, { component }: { component: ComponentInt }) => ({ - ...state, +export const openExpansionPanel = ( + state: ApplicationStateInt, + { component }: { component: ComponentInt } +) => ({ + ...state }); export const addProp = ( state: ApplicationStateInt, - { key, value = null, required, type }: { key: string; value: string; required: boolean; type: string }, + { + key, + value = null, + required, + type + }: { key: string; value: string; required: boolean; type: string } ) => { if (!state.focusComponent.id) { console.log('Add prop error. no focused component '); return state; } - const selectedComponent = state.components.find(comp => comp.id === state.focusComponent.id); + const selectedComponent = state.components.find( + comp => comp.id === state.focusComponent.id + ); const newProp: PropInt = { id: selectedComponent.nextPropId, key, value: value || key, required, - type, + type }; const newProps = [...selectedComponent.props, newProp]; const modifiedComponent: ComponentInt = { ...selectedComponent, props: newProps, - nextPropId: selectedComponent.nextPropId + 1, + nextPropId: selectedComponent.nextPropId + 1 }; - const newComponents: ComponentsInt = state.components.filter(comp => comp.id !== selectedComponent.id); + const newComponents: ComponentsInt = state.components.filter( + comp => comp.id !== selectedComponent.id + ); newComponents.push(modifiedComponent); return { ...state, components: newComponents, - focusComponent: modifiedComponent, + focusComponent: modifiedComponent }; }; @@ -487,27 +587,38 @@ export const deleteProp = (state: ApplicationStateInt, propId: number) => { return state; } - const modifiedComponent: any = cloneDeep(state.components.find(comp => comp.id === state.focusComponent.id)); + const modifiedComponent: any = cloneDeep( + state.components.find(comp => comp.id === state.focusComponent.id) + ); - const indexToDelete = modifiedComponent.props.findIndex((prop: PropInt) => prop.id === propId); + const indexToDelete = modifiedComponent.props.findIndex( + (prop: PropInt) => prop.id === propId + ); if (indexToDelete === -1) { - console.log(`Delete prop Error. Prop id:${propId} not found in ${modifiedComponent.title}`); + console.log( + `Delete prop Error. Prop id:${propId} not found in ${modifiedComponent.title}` + ); return state; } modifiedComponent.props.splice(indexToDelete, 1); - const newComponentsArray = state.components.filter(comp => comp.id !== modifiedComponent.id); + const newComponentsArray = state.components.filter( + comp => comp.id !== modifiedComponent.id + ); newComponentsArray.push(modifiedComponent); return { ...state, components: newComponentsArray, - focusComponent: modifiedComponent, + focusComponent: modifiedComponent }; }; -export const updateHtmlAttr = (state: ApplicationStateInt, { attr, value }: { attr: string; value: string }) => { +export const updateHtmlAttr = ( + state: ApplicationStateInt, + { attr, value }: { attr: string; value: string } +) => { if (!state.focusChild.childId) { console.log('Update HTML error. no focused child '); return state; @@ -517,46 +628,63 @@ export const updateHtmlAttr = (state: ApplicationStateInt, { attr, value }: { at modifiedChild.HTMLInfo[attr] = value; const modifiedComponent: ComponentInt = JSON.parse( - JSON.stringify(state.components.find(comp => comp.id === state.focusComponent.id)), + JSON.stringify( + state.components.find(comp => comp.id === state.focusComponent.id) + ) ); modifiedComponent.childrenArray = modifiedComponent.childrenArray.filter( - child => child.childId !== modifiedChild.childId, + child => child.childId !== modifiedChild.childId ); modifiedComponent.childrenArray.push(modifiedChild); - const newComponentsArray = state.components.filter(comp => comp.id !== modifiedComponent.id); + const newComponentsArray = state.components.filter( + comp => comp.id !== modifiedComponent.id + ); newComponentsArray.push(modifiedComponent); return { ...state, components: newComponentsArray, focusComponent: modifiedComponent, - focusChild: modifiedChild, + focusChild: modifiedChild }; }; -export const updateChildrenSort = (state: ApplicationStateInt, { newSortValues }: { newSortValues: any }) => { - const modifiedChildrenArray: ChildrenInt = cloneDeep(state.focusComponent.childrenArray); +export const updateChildrenSort = ( + state: ApplicationStateInt, + { newSortValues }: { newSortValues: any } +) => { + const modifiedChildrenArray: ChildrenInt = cloneDeep( + state.focusComponent.childrenArray + ); for (let i = 0; i < modifiedChildrenArray.length; i += 1) { const currChild = modifiedChildrenArray[i]; const currChildId = currChild.childId; - const newValueObj = newSortValues.find((n: any) => n.childId === currChildId); + const newValueObj = newSortValues.find( + (n: any) => n.childId === currChildId + ); const newSortValue = newValueObj.childSort; - console.log(` currChildId ${currChildId} currSortValue: ${currChild.childSort} newSortValue:${newSortValue}`); + console.log( + ` currChildId ${currChildId} currSortValue: ${currChild.childSort} newSortValue:${newSortValue}` + ); currChild.childSort = newSortValue; } - const modifiedComponent = state.components.find(comp => comp.id === state.focusComponent.id); + const modifiedComponent = state.components.find( + comp => comp.id === state.focusComponent.id + ); modifiedComponent.childrenArray = modifiedChildrenArray; - const modifiedComponentsArray = state.components.filter(comp => comp.id !== state.focusComponent.id); + const modifiedComponentsArray = state.components.filter( + comp => comp.id !== state.focusComponent.id + ); modifiedComponentsArray.push(modifiedComponent); return { ...state, components: modifiedComponentsArray, - focusComponent: modifiedComponent, + focusComponent: modifiedComponent }; }; diff --git a/src/utils/componentRender.util.ts b/src/utils/componentRender.util.ts index 813c759e1..dda3d1e7f 100644 --- a/src/utils/componentRender.util.ts +++ b/src/utils/componentRender.util.ts @@ -1,7 +1,16 @@ -import { ComponentInt, ComponentsInt, ChildInt, ChildrenInt, PropInt } from './Interfaces.ts'; -import cloneDeep from './cloneDeep.ts'; +import { + ComponentInt, + ComponentsInt, + ChildInt, + ChildrenInt, + PropInt +} from './Interfaces'; +import cloneDeep from './cloneDeep'; -const componentRender = (component: ComponentInt, components: ComponentsInt) => { +const componentRender = ( + component: ComponentInt, + components: ComponentsInt +) => { const { childrenArray, title, @@ -115,7 +124,10 @@ const componentRender = (component: ComponentInt, components: ComponentsInt) => import React from 'react'; ${childrenArray .filter(child => child.childType !== 'HTML') - .map(child => `import ${child.componentName} from './${child.componentName}.tsx'`) + .map( + child => + `import ${child.componentName} from './${child.componentName}.tsx'` + ) .reduce((acc: Array, child) => { if (!acc.includes(child)) { acc.push(child); @@ -138,7 +150,9 @@ const componentRender = (component: ComponentInt, components: ComponentsInt) => .sort((a: ChildInt, b: ChildInt) => a.childSort - b.childSort) .map( (child: ChildInt) => - `<${componentNameGenerator(child)} ${propDrillTextGenerator(child)}/>` + `<${componentNameGenerator(child)} ${propDrillTextGenerator( + child + )}/>` ) .join('\n')}
diff --git a/src/utils/htmlElements.util.ts b/src/utils/htmlElements.util.ts index e43dd3a76..8d9d6f190 100644 --- a/src/utils/htmlElements.util.ts +++ b/src/utils/htmlElements.util.ts @@ -18,46 +18,48 @@ const HTMLelements: htmlElementsInt = { Image: { width: 100, height: 100, - attributes: ['className', 'id', 'src'], + attributes: ['className', 'id', 'src'] }, Button: { width: 75, height: 28, - attributes: ['className', 'id', 'text'], + attributes: ['className', 'id', 'type'] // changed 'text' to 'type' for more accurate html element attributes }, Form: { width: 150, height: 150, - attributes: ['className', 'id', 'text'], + attributes: ['className', 'id', 'text'] }, Paragraph: { width: 250, height: 75, - attributes: ['className', 'id', 'text'], + attributes: ['className', 'id', 'text'] }, List: { width: 75, height: 75, - attributes: ['className', 'id', 'text'], + attributes: ['className', 'id', 'text'] }, Link: { width: 50, height: 50, - attributes: ['className', 'id', 'text'], - }, + attributes: ['className', 'id', 'text'] + } }; function getSize(htmlElement: string): htmlElemPositionInt { const localHTMLelements = HTMLelements; if (!(htmlElement in localHTMLelements)) { - window.alert(`htmlElement error: "${htmlElement} is not found in our database"`); + window.alert( + `htmlElement error: "${htmlElement} is not found in our database"` + ); return; } return { width: HTMLelements[htmlElement].width || 300, - height: HTMLelements[htmlElement].height || 300, + height: HTMLelements[htmlElement].height || 300 }; }