├── fileMock.js ├── styleMock.js ├── .babelrc ├── .gitignore ├── jest-teardown.js ├── jest-setup.js ├── client ├── assets │ ├── images │ │ ├── darren.jpg │ │ ├── logo.png │ │ ├── randy.jpg │ │ ├── favicon.ico │ │ ├── kendall.jpg │ │ ├── krystal.jpg │ │ ├── feature-1.gif │ │ ├── feature-2.gif │ │ ├── linked-in.png │ │ ├── randy-funny.png │ │ ├── darren-funny.jpg │ │ ├── github-resume.jpg │ │ ├── kendall-funny.png │ │ ├── krystal-funny.jpg │ │ └── Resume - Nov, 2019.pdf │ ├── styles │ │ ├── partials │ │ │ ├── _visual-container.scss │ │ │ ├── _topnav-container.scss │ │ │ ├── _general.scss │ │ │ ├── _easter-egg.scss │ │ │ ├── _application.scss │ │ │ ├── _panel-container.scss │ │ │ └── _landing-page.scss │ │ ├── styles.scss │ │ ├── normalize.css │ │ └── styles.css.map │ └── index.html ├── templates-exports │ ├── fullStackTemplates │ │ ├── readmeMD.js │ │ ├── server.js │ │ ├── webpack.config.js │ │ └── packagejson.js │ ├── frontEndTemplates │ │ ├── indexJS.js │ │ └── indexHTML.js │ ├── frontEndFiles.js │ └── fullStackFiles.js ├── components │ ├── File.jsx │ ├── PanelNavIcons.jsx │ ├── SubTree.jsx │ ├── OnClickShowSubTree.jsx │ ├── CreateCodeEditor.jsx │ ├── EachChild.jsx │ ├── TemplateDropdown.jsx │ ├── OnClickShowCodeMirror.jsx │ ├── FileTree.jsx │ ├── ChildrenList.jsx │ ├── ComponentDetail.jsx │ └── TemplatingArea.jsx ├── reducers │ ├── index.js │ ├── utils │ │ ├── easterEgg.js │ │ ├── updateTree.js │ │ └── deleteNodeFuncs.js │ └── mainReducer.js ├── store.js ├── landing-page │ ├── Details.jsx │ ├── Hero.jsx │ ├── Action.jsx │ ├── Team.jsx │ ├── Features.jsx │ └── LandingPage.jsx ├── index.js ├── templates-code │ └── templates.js ├── constants │ └── actionTypes.js ├── containers │ ├── VisualContainer.jsx │ ├── TopNavContainer.jsx │ └── PanelContainer.jsx ├── App.jsx └── actions │ └── actions.js ├── __tests__ ├── template.test.js ├── template.enzyme.js ├── reducer.test.js └── enzyme.js ├── webpack.config.js ├── package.json ├── __mock__ └── stateMocks.js └── README.md /fileMock.js: -------------------------------------------------------------------------------- 1 | module.exports = "test-file-stub"; 2 | -------------------------------------------------------------------------------- /styleMock.js: -------------------------------------------------------------------------------- 1 | // __mocks__/styleMock.js 2 | 3 | module.exports = {}; 4 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-env", "@babel/preset-react"] 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | build 4 | npm-debug.log* 5 | dist/bundle.js 6 | -------------------------------------------------------------------------------- /jest-teardown.js: -------------------------------------------------------------------------------- 1 | module.exports = async globalConfig => { 2 | testServer.close(); 3 | }; 4 | -------------------------------------------------------------------------------- /jest-setup.js: -------------------------------------------------------------------------------- 1 | module.exports = async () => { 2 | global.testServer = await require("./server"); 3 | }; 4 | -------------------------------------------------------------------------------- /client/assets/images/darren.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/team-targaryen/react-blue/HEAD/client/assets/images/darren.jpg -------------------------------------------------------------------------------- /client/assets/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/team-targaryen/react-blue/HEAD/client/assets/images/logo.png -------------------------------------------------------------------------------- /client/assets/images/randy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/team-targaryen/react-blue/HEAD/client/assets/images/randy.jpg -------------------------------------------------------------------------------- /client/assets/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/team-targaryen/react-blue/HEAD/client/assets/images/favicon.ico -------------------------------------------------------------------------------- /client/assets/images/kendall.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/team-targaryen/react-blue/HEAD/client/assets/images/kendall.jpg -------------------------------------------------------------------------------- /client/assets/images/krystal.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/team-targaryen/react-blue/HEAD/client/assets/images/krystal.jpg -------------------------------------------------------------------------------- /client/assets/images/feature-1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/team-targaryen/react-blue/HEAD/client/assets/images/feature-1.gif -------------------------------------------------------------------------------- /client/assets/images/feature-2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/team-targaryen/react-blue/HEAD/client/assets/images/feature-2.gif -------------------------------------------------------------------------------- /client/assets/images/linked-in.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/team-targaryen/react-blue/HEAD/client/assets/images/linked-in.png -------------------------------------------------------------------------------- /client/assets/images/randy-funny.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/team-targaryen/react-blue/HEAD/client/assets/images/randy-funny.png -------------------------------------------------------------------------------- /client/assets/images/darren-funny.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/team-targaryen/react-blue/HEAD/client/assets/images/darren-funny.jpg -------------------------------------------------------------------------------- /client/assets/images/github-resume.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/team-targaryen/react-blue/HEAD/client/assets/images/github-resume.jpg -------------------------------------------------------------------------------- /client/assets/images/kendall-funny.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/team-targaryen/react-blue/HEAD/client/assets/images/kendall-funny.png -------------------------------------------------------------------------------- /client/assets/images/krystal-funny.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/team-targaryen/react-blue/HEAD/client/assets/images/krystal-funny.jpg -------------------------------------------------------------------------------- /client/assets/images/Resume - Nov, 2019.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/team-targaryen/react-blue/HEAD/client/assets/images/Resume - Nov, 2019.pdf -------------------------------------------------------------------------------- /client/templates-exports/fullStackTemplates/readmeMD.js: -------------------------------------------------------------------------------- 1 | let readmeMD = `Hey sup ^_________________^ I love Code and Coffee 🤓😎👍👍 2 | `; 3 | 4 | export default readmeMD; -------------------------------------------------------------------------------- /client/components/File.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const File = ({ file, name, setCurrentComponent }) => { 4 | return
  • setCurrentComponent(file)}>{name}
  • ; 5 | }; 6 | 7 | export default File; 8 | -------------------------------------------------------------------------------- /client/assets/styles/partials/_visual-container.scss: -------------------------------------------------------------------------------- 1 | #visual-container { 2 | flex: 1; 3 | background: $prime-color-5; 4 | 5 | .nodeBase { 6 | fill: $prime-color-1; 7 | } 8 | 9 | .leafNodeBase { 10 | fill: $prime-color-4; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /client/reducers/index.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux'; 2 | import mainReducer from './mainReducer'; 3 | 4 | /** 5 | * combine reducers 6 | **/ 7 | const reducers = combineReducers({ 8 | main: mainReducer 9 | }); 10 | 11 | export default reducers; 12 | -------------------------------------------------------------------------------- /client/assets/styles/styles.scss: -------------------------------------------------------------------------------- 1 | @import './partials/general'; 2 | @import './partials/landing-page'; 3 | @import './partials/application'; 4 | @import './partials/topnav-container'; 5 | @import './partials/panel-container'; 6 | @import './partials/visual-container'; 7 | @import './partials/easter-egg'; 8 | -------------------------------------------------------------------------------- /client/templates-exports/frontEndTemplates/indexJS.js: -------------------------------------------------------------------------------- 1 | let indexJS = `import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App.jsx'; 4 | import styles from './assets/styles/styles.css'; 5 | 6 | ReactDOM.render(, document.getElementById('root')); 7 | `; 8 | 9 | export default indexJS; 10 | -------------------------------------------------------------------------------- /client/store.js: -------------------------------------------------------------------------------- 1 | import { createStore, applyMiddleware } from 'redux'; 2 | import { composeWithDevTools } from 'redux-devtools-extension'; 3 | import thunk from 'redux-thunk'; 4 | import reducers from './reducers/index'; 5 | 6 | /** 7 | * add redux devtools to track the store 8 | **/ 9 | const store = createStore( 10 | reducers, 11 | composeWithDevTools(applyMiddleware(thunk)) 12 | ); 13 | 14 | export default store; 15 | -------------------------------------------------------------------------------- /client/templates-exports/fullStackTemplates/server.js: -------------------------------------------------------------------------------- 1 | let server = `const express = require('express'); 2 | const path = require('path'); 3 | const cors = require('cors'); 4 | const PORT = 8080; 5 | 6 | const app = express(); 7 | 8 | app.use(cors()); 9 | 10 | app.get('/', (req, res) => { 11 | res.sendFile(path.resolve(__dirname, './../assets.index.html')) 12 | }) 13 | 14 | app.listen(PORT, () => { 15 | console.log('listening on port 8080') 16 | })`; 17 | 18 | export default server; 19 | 20 | -------------------------------------------------------------------------------- /client/templates-exports/frontEndTemplates/indexHTML.js: -------------------------------------------------------------------------------- 1 | let indexHTML = ` 2 | 3 | 4 | 5 | 6 | 7 | React Blue 8 | 9 | 10 |
    11 | 12 | 13 | 14 | `; 15 | 16 | export default indexHTML; 17 | -------------------------------------------------------------------------------- /client/landing-page/Details.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ScrollAnimation from 'react-animate-on-scroll'; 3 | 4 | const Details = () => { 5 | return ( 6 |
    7 |

    React Blue is an Open-Source Project

    8 |

    Feel free to contribute

    9 | 10 | 11 | 12 | 13 | 14 |
    15 | ); 16 | }; 17 | 18 | export default Details; 19 | -------------------------------------------------------------------------------- /client/components/PanelNavIcons.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Link } from 'react-router-dom'; 3 | /** 4 | * Routes for React Router 5 | */ 6 | const PanelNavIcons = () => { 7 | return ( 8 | 19 | ); 20 | }; 21 | 22 | export default PanelNavIcons; 23 | -------------------------------------------------------------------------------- /__tests__/template.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { configure, shallow } from 'enzyme'; 3 | import Adapter from 'enzyme-adapter-react-16'; 4 | import TemplateArea from '../client/components/TemplatingArea'; 5 | 6 | configure({ adapter: new Adapter() }); 7 | 8 | describe('Template unit tests', () => { 9 | describe('TemplateArea', () => { 10 | let wrapper, headings; 11 | 12 | beforeAll(() => { 13 | wrapper = shallow(); 14 | headings = wrapper.find('h3'); 15 | }); 16 | 17 | it('Renders an Add Template feature', () => { 18 | expect(headings.at(0).text()).toMatch('Add Template'); 19 | expect(headings.at(1).text()).toMatch('Template List'); 20 | }); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /client/assets/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | React Blue 8 | 9 | 13 | 18 | 19 | 20 | 21 |
    22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /client/assets/styles/partials/_topnav-container.scss: -------------------------------------------------------------------------------- 1 | .navbar { 2 | background: $prime-color-1; 3 | padding-left: 20px; 4 | padding-right: 20px; 5 | 6 | .logo-frame { 7 | display: flex; 8 | justify-content: center; 9 | align-items: center; 10 | width: 40px; 11 | height: 40px; 12 | background: #fff; 13 | border-radius: 50%; 14 | margin-right: 10px; 15 | } 16 | 17 | .logo { 18 | width: 32px; 19 | } 20 | 21 | .dropdown-menu { 22 | font-size: $application-font-size; 23 | } 24 | 25 | .keyboard-shortcut { 26 | display: flex; 27 | justify-content: space-between; 28 | 29 | span { 30 | &:first-child { 31 | margin-right: 40px; 32 | } 33 | } 34 | } 35 | 36 | .export { 37 | .dropdown-menu { 38 | left: auto; 39 | right: 0; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /client/assets/styles/partials/_general.scss: -------------------------------------------------------------------------------- 1 | // material ui overrides 2 | html { 3 | overflow: auto !important; 4 | } 5 | 6 | body, 7 | header { 8 | padding: 0 !important; 9 | } 10 | 11 | // variables 12 | $landing-page-font-size: 16px; 13 | $application-font-size: 12px; 14 | 15 | $prime-color-1: #045590; 16 | $prime-color-2: #137ac1; 17 | $prime-color-3: #36a2c2; 18 | $prime-color-4: #71b8c2; 19 | $prime-color-5: #f8f8ff; 20 | 21 | // general 22 | html, 23 | body, 24 | #app { 25 | height: 100%; 26 | } 27 | 28 | body { 29 | font-size: $landing-page-font-size; 30 | background: $prime-color-5; 31 | } 32 | 33 | label { 34 | margin: 0; 35 | } 36 | 37 | ul { 38 | padding: 0; 39 | margin: 0; 40 | list-style-type: none; 41 | } 42 | 43 | figure { 44 | margin: 0; 45 | } 46 | 47 | // material ui overrides 48 | a { 49 | color: inherit; 50 | 51 | &:hover { 52 | color: inherit; 53 | text-decoration: none; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /client/templates-exports/fullStackTemplates/webpack.config.js: -------------------------------------------------------------------------------- 1 | const webpack = `const webpack = require('webpack'); 2 | const path = require('path'); 3 | const status = process.env.NODE_ENV; 4 | 5 | module.exports = { 6 | mode: status, 7 | entry: './index.js', 8 | output: { 9 | path: path.resolve(__dirname, 'build'), 10 | filename: 'bundle.js', 11 | }, 12 | module: { 13 | rules: [ 14 | { 15 | test: /\.jsx?/i, 16 | loader: 'babel-loader', 17 | exclude: /node_modules/, 18 | options: { 19 | presets: ['@babel/preset-env', '@babel/preset-react'] 20 | } 21 | }, 22 | { 23 | test: /\.css$/, 24 | use: ['style-loader', 'css-loader', 'sass-loader'], 25 | exclude: /node_modules/, 26 | } 27 | ]}, 28 | devServer: { 29 | publicPath: '/build', 30 | contentBase: path.resolve(__dirname, 'assets') 31 | }, 32 | resolve: { 33 | extensions: ['*', '.js', '.jsx'], 34 | } 35 | };` 36 | export default webpack; 37 | -------------------------------------------------------------------------------- /client/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from 'react-dom'; 3 | import { Provider } from 'react-redux'; 4 | import { BrowserRouter, Switch, Route } from 'react-router-dom'; 5 | import LandingPage from './landing-page/LandingPage.jsx'; 6 | import App from './App.jsx'; 7 | import store from './store'; 8 | import './assets/styles/normalize.css'; 9 | import 'bootstrap/dist/css/bootstrap.min.css'; 10 | import './assets/styles/styles.css'; 11 | /** 12 | * React Routed components to switch from landing page (immediate view of page) to the application 13 | * 14 | * Wrapped Root Component in the Provider allowing children to be connected with Redux store 15 | **/ 16 | 17 | render( 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | , 30 | document.getElementById('app') 31 | ); 32 | -------------------------------------------------------------------------------- /client/reducers/utils/easterEgg.js: -------------------------------------------------------------------------------- 1 | export const easterEgg = () => { 2 | const audio = new Audio( 3 | 'https://iringtone.net/rington/file?id=8454&type=sound&name=mp3' 4 | ); 5 | audio.play(); 6 | 7 | const app = document.getElementById('app'); 8 | app.classList.add('easter-egg'); 9 | 10 | for (let i = 0; i <= 1000; i += 1) { 11 | const particle = document.createElement('div'); 12 | particle.classList.add('c'); 13 | app.appendChild(particle); 14 | } 15 | 16 | const colorGen = () => { 17 | const r = Math.floor(Math.random() * 256); 18 | const g = Math.floor(Math.random() * 256); 19 | const b = Math.floor(Math.random() * 256); 20 | 21 | return 'rgb(' + r + ',' + g + ',' + b + ')'; 22 | }; 23 | 24 | setInterval(() => { 25 | document.querySelector('.navbar').style.backgroundColor = `${colorGen()}`; 26 | 27 | const buttons = document.querySelectorAll('#application *'); 28 | for (let i = 0; i < buttons.length; i += 1) { 29 | buttons[i].style.backgroundColor = `${colorGen()}`; 30 | buttons[i].style.color = `${colorGen()}`; 31 | buttons[i].style.fill = `${colorGen()}`; 32 | } 33 | }, 100); 34 | }; 35 | -------------------------------------------------------------------------------- /client/landing-page/Hero.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import logo from '../assets/images/logo.png'; 3 | import GitHubButton from 'react-github-btn'; 4 | 5 | const Hero = () => { 6 | return ( 7 |
    8 |
    9 |
    10 | react blue logo 11 |
    12 |

    React Blue[print]

    13 |
    14 | 19 | Follow React Blue 20 | 21 | 28 | Star 29 | 30 |
    31 |
    32 |
    33 | ); 34 | }; 35 | 36 | export default Hero; 37 | -------------------------------------------------------------------------------- /client/components/SubTree.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import OnClickShowSubTree from './OnClickShowSubTree.jsx'; 3 | /** 4 | * Renders the dropdown for each of the displaySubTreeDropDown properties 5 | */ 6 | 7 | const SubTree = ({ 8 | displaySubTreeDropDown, 9 | setTimeoutId, 10 | recentTimeoutId, 11 | state, 12 | checkID_ClearAndSetTimeout, 13 | showSubTree, 14 | deleteSubTreeDropdownItem 15 | }) => { 16 | const displaySubTreeArray = []; 17 | for (let [key, value] of Object.entries(displaySubTreeDropDown)) { 18 | displaySubTreeArray.push( 19 | 30 | ); 31 | } 32 | return ( 33 |
    34 |

    SubTrees

    35 |
      {displaySubTreeArray}
    36 |
    37 | ); 38 | }; 39 | export default SubTree; 40 | -------------------------------------------------------------------------------- /client/assets/styles/partials/_easter-egg.scss: -------------------------------------------------------------------------------- 1 | .easter-egg { 2 | $total: 144; 3 | $time: 4; 4 | $height: 500; 5 | $percent: 0.69444%; 6 | $dotSize: 0.9; 7 | 8 | .c { 9 | height: $height + px; 10 | width: $percent; 11 | margin-top: -$height + px; 12 | animation: drop $time + s infinite ease-in; 13 | position: absolute; 14 | top: 0; 15 | &:after { 16 | content: ''; 17 | position: absolute; 18 | width: $dotSize + vw; 19 | height: $dotSize + vw; 20 | border-radius: 50%; 21 | left: 50%; 22 | bottom: -($dotSize/2) + vw; 23 | margin-left: -($dotSize/2) + vw; 24 | } 25 | } 26 | 27 | @for $i from 1 through $total { 28 | $hue: (300 / $total) * $i; 29 | .c:nth-child(#{$i}) { 30 | left: ($i - 1) * $percent; 31 | background-image: linear-gradient( 32 | to bottom, 33 | transparent, 34 | hsla($hue, 100%, 50%, 0.8) 35 | ); 36 | animation-delay: random($total) * ($time/$total) * -1s; 37 | &:after { 38 | background: hsla($hue, 100%, 50%, 1); 39 | } 40 | } 41 | } 42 | 43 | @keyframes drop { 44 | 80% { 45 | opacity: 1; 46 | } 47 | 100% { 48 | transform: translate3d(0, 150vh, 0); 49 | opacity: 0; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /client/templates-code/templates.js: -------------------------------------------------------------------------------- 1 | const defaultSyntax = {}; 2 | 3 | defaultSyntax.InitialClassSyntax = function (inputName = "Template_Class") { 4 | (this.name = "React Class Syntax - DEFAULT"), 5 | (this.code = `import React, { Component } from 'react'; 6 | 7 | /* ADD your template code anywhere but please do not delete => the 'DONOTDELETESTRING' */ 8 | 9 | class ${inputName} extends Component { 10 | constructor(props){ 11 | super(props); 12 | this.state = { 13 | isTemplateClassComponent: true, 14 | 15 | }; 16 | }; 17 | 18 | render(){ 19 | 20 | return( 21 | 22 | 23 | 24 | DONOTDELETETHISSTRING 25 | 26 | 27 | 28 | ); 29 | }; 30 | };` 31 | ); 32 | }; 33 | 34 | defaultSyntax.InitialHookSyntax = function (inputName = "Template_Hooks") { 35 | (this.name = "React Hooks Syntax"), 36 | (this.code = `import React, { useState } from 'react'; 37 | /* ADD your template code anywhere but please do not delete => the 'DONOTDELETESTRING' */ 38 | 39 | const ${inputName} = ({/* INSERT PROPS HERE */}) =>{ 40 | const [istemplateHookComponent, setIstemplateHookComponent] = useState(true); 41 | 42 | return( 43 | 44 | 45 | 46 | DONOTDELETETHISSTRING 47 | 48 | 49 | 50 | ) 51 | }`); 52 | }; 53 | module.exports = defaultSyntax; 54 | -------------------------------------------------------------------------------- /client/templates-exports/fullStackTemplates/packagejson.js: -------------------------------------------------------------------------------- 1 | const packageJSON = `{ 2 | "name": "my-react-blue-app", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node server/server.js", 8 | "build": "cross-env NODE_ENV=production webpack", 9 | "dev": "cross-env NODE_ENV=development webpack-dev-server --open" 10 | }, 11 | "nodemonConfig": { 12 | "ignore": [ 13 | "build" 14 | ] 15 | }, 16 | "keywords": [], 17 | "author": "", 18 | "license": "MIT", 19 | "dependencies": { 20 | "cors": "^2.8.5", 21 | "express": "^4.17.1", 22 | "react": "^16.10.2", 23 | "react-dom": "^16.10.2", 24 | "webpack": "^4.40.2" 25 | }, 26 | "devDependencies": { 27 | "@babel/core": "^7.6.0", 28 | "@babel/plugin-proposal-class-properties": "^7.5.5", 29 | "@babel/preset-env": "^7.6.0", 30 | "@babel/preset-react": "^7.0.0", 31 | "babel-loader": "^8.0.6", 32 | "cross-env": "^5.2.0", 33 | "css-loader": "^3.2.0", 34 | "file-loader": "^3.0.1", 35 | "node-sass": "^4.12.0", 36 | "nodemon": "^1.19.2", 37 | "postcss-loader": "^3.0.0", 38 | "sass-loader": "^8.0.0", 39 | "style-loader": "^1.0.0", 40 | "webpack": "^4.40.2", 41 | "webpack-cli": "^3.3.9", 42 | "webpack-dev-server": "^3.8.1" 43 | } 44 | }` 45 | export default packageJSON; 46 | -------------------------------------------------------------------------------- /client/components/OnClickShowSubTree.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | // the !+id means that if the componentID of the string '0' is converted to the number 0 and then checked if !(false) === true, 3 | // if so don't render the - button because we dont want to have to option to delete the button if it is the root of the tree; 4 | /** 5 | * the !+id means '0' is converted to the number 0 6 | * if id === 0: don't render the button because we dont want to have to option to delete the button if it is the root of the tree; 7 | */ 8 | const OnClickShowSubTree = ({ 9 | setTimeoutId, 10 | recentTimeoutId, 11 | state, 12 | checkID_ClearAndSetTimeout, 13 | id, 14 | name, 15 | showSubTree, 16 | deleteSubTreeDropdownItem 17 | }) => { 18 | return ( 19 |
  • 20 | 27 | {!+id ? null : ( 28 | 38 | )} 39 |
  • 40 | ); 41 | }; 42 | export default OnClickShowSubTree; 43 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | 3 | module.exports = { 4 | entry: "./client/index.js", 5 | output: { 6 | path: path.resolve(__dirname, "build"), 7 | publicPath: "/", 8 | filename: "bundle.js" 9 | }, 10 | mode: process.env.NODE_ENV, 11 | devServer: { 12 | contentBase: path.join(__dirname, "./client/assets"), 13 | publicPath: "/build/", 14 | historyApiFallback: true 15 | }, 16 | module: { 17 | rules: [ 18 | { 19 | test: /\.jsx?/, 20 | exclude: /node_modules/, 21 | use: { 22 | loader: "babel-loader", 23 | options: { 24 | presets: ["@babel/preset-env", "@babel/preset-react"] 25 | } 26 | } 27 | }, 28 | { 29 | test: /(css|scss)$/, 30 | use: ["style-loader", "css-loader", "sass-loader"] 31 | }, 32 | { 33 | test: /\.(png|jpg|jpeg|gif|woff|woff2|eot|ttf|svg|ico)$/, 34 | use: [ 35 | { 36 | // loads files as base64 encoded data url if image file is less than set limit 37 | loader: "url-loader", 38 | options: { 39 | // if file is greater than the limit (bytes), file-loader is used as fallback 40 | limit: 90000 41 | } 42 | } 43 | ] 44 | } 45 | ] 46 | }, 47 | resolve: { 48 | extensions: ['.js', '.jsx'] 49 | } 50 | }; 51 | -------------------------------------------------------------------------------- /client/assets/styles/partials/_application.scss: -------------------------------------------------------------------------------- 1 | #application { 2 | display: flex; 3 | flex-direction: column; 4 | height: 100%; 5 | font-size: $application-font-size; 6 | 7 | h2 { 8 | font-size: 1.2rem; 9 | } 10 | 11 | h3 { 12 | font-size: 1rem; 13 | } 14 | 15 | h4 { 16 | font-size: 0.8rem; 17 | } 18 | 19 | i { 20 | font-size: 20px; 21 | color: $prime-color-1; 22 | transition: color 0.15s ease-in-out; 23 | cursor: pointer; 24 | 25 | &:hover { 26 | color: #007bff; 27 | } 28 | } 29 | 30 | .dropdown-item { 31 | font-size: $application-font-size; 32 | } 33 | 34 | // buttons 35 | button { 36 | border: 0; 37 | } 38 | 39 | .btn { 40 | font-size: 12px; 41 | } 42 | 43 | .btn-primary { 44 | background: $prime-color-1; 45 | border-color: $prime-color-1; 46 | } 47 | 48 | // content 49 | #app { 50 | display: flex; 51 | flex-direction: column; 52 | } 53 | 54 | #panel-main-container { 55 | display: flex; 56 | height: 100%; 57 | } 58 | 59 | .is-container { 60 | display: flex; 61 | } 62 | 63 | input { 64 | background: $prime-color-5; 65 | } 66 | 67 | input[type='text'] { 68 | border: 0; 69 | border-radius: 0.25rem; 70 | padding: 9px 12px; 71 | border: 1px solid $prime-color-1; 72 | } 73 | 74 | input[type='checkbox'] { 75 | margin-right: 5px; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /client/components/CreateCodeEditor.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | import OnClickShowCodeMirror from './OnClickShowCodeMirror.jsx'; 3 | /** 4 | * Current component display: 5 | * name of component 6 | * component or container(toggle button to change its attribute) 7 | * delete current component (if this component is a parent component, show warning message) 8 | * _____________________________________________________________________________________________________________________ 9 | * useEffect fn() : to make sure that the name of templates for each child were getting updated on clicks of the D3 tree 10 | */ 11 | const CreateCodeEditor = ({ 12 | syntaxObject, 13 | index, 14 | deleteTemplate, 15 | updateCode 16 | }) => { 17 | const [isName, setIsName] = useState(syntaxObject.name) 18 | useEffect(() => { 19 | if (syntaxObject.name !== isName) { 20 | setIsName(syntaxObject.name) 21 | } 22 | }, [syntaxObject.name]) 23 | return ( 24 |
    25 | 31 | 37 |
    38 | ); 39 | }; 40 | export default CreateCodeEditor; 41 | -------------------------------------------------------------------------------- /client/constants/actionTypes.js: -------------------------------------------------------------------------------- 1 | // sidebar actions 2 | export const RENAME_COMPONENT = 'RENAME_COMPONENT'; 3 | export const CHANGE_TYPE = 'CHANGE_TYPE'; 4 | export const DELETE_COMPONENT = 'DELETE_COMPONENT'; 5 | 6 | // main display container actions 7 | export const SET_CURRENT_COMPONENT = 'SET_CURRENT_COMPONENT'; 8 | export const SET_TRANS_AND_HISTORY = 'SET_TRANS_AND_HISTORY'; 9 | export const UN_DO = 'UN_DO'; 10 | export const RE_DO = 'RE_DO'; 11 | 12 | // change display of d3 tree 13 | export const CHANGE_DISPLAY_HORIZONTAL_OR_VERTICAL = 14 | 'CHANGE_DISPLAY_HORIZONTAL_OR_VERTICAL'; 15 | 16 | // children list actions 17 | export const SET_CHILDREN = 'SET_CHILDREN'; 18 | export const RENAME_CHILD = 'RENAME_CHILD'; 19 | export const CHANGE_CHILD_TYPE = 'CHANGE_CHILD_TYPE'; 20 | export const ADD_CHILD = 'ADD_CHILD'; 21 | export const DELETE_CHILD = 'DELETE_CHILD'; 22 | 23 | // file tree 24 | export const SHOW_FILE_TREE = 'SHOW_FILE_TREE'; 25 | 26 | //templating feature 27 | export const USE_TEMPLATES = 'USE_TEMPLATES'; 28 | export const SET_TEMPLATES_FOR_COMPONENT = 'SET_TEMPLATES_FOR_COMPONENT'; 29 | 30 | //ZOOM feature 31 | export const ZOOM_BY_CHANGING_X_AND_Y = 'ZOOM_BY_CHANGING_X_AND_Y'; 32 | 33 | //checking if the entire tree exists inside of local storage and updating it to the state 34 | export const UPDATE_STATE_WITH_LOCAL_STORAGE = 35 | 'UPDATE_STATE_WITH_LOCAL_STORAGE'; 36 | 37 | //deleting entire tree 38 | export const RESET_ENTIRE_TREE = 'RESET_ENTIRE_TREE'; 39 | 40 | // setTimeout functionality of Local Storage 41 | export const SET_TIMEOUT_ID = 'SET_TIMEOUT_ID'; 42 | 43 | //display sub tree 44 | export const SHOW_SUBTREE = 'SHOW_SUBTREE'; 45 | export const ADD_OR_DELETE_NEW_SUB_TREE = 'ADD_OR_DELETE_NEW_SUB_TREE'; 46 | export const DELETE_SUBTREE_DROPDOWN_ITEM = 'DELETE_SUBTREE_DROPDOWN_ITEM' -------------------------------------------------------------------------------- /client/components/EachChild.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | /** 3 | * Each Child Display: 4 | * Creates a child for Each child of the parent node 5 | * component or container(toggle button to change its attribute) 6 | * template dropdown feature, choose a template 7 | * delete current component 8 | */ 9 | const EachChild = ({ 10 | initiailName, 11 | name, 12 | childId, 13 | isContainer, 14 | renameChild, 15 | changeType, 16 | deleteChild, 17 | state, 18 | recentTimeoutId, 19 | setTimeoutId, 20 | checkID_ClearAndSetTimeout, 21 | showSubTree, 22 | currentlyDisplayedSubTreeId 23 | }) => ( 24 |
    25 | { 31 | renameChild(event, childId); 32 | showSubTree(currentlyDisplayedSubTreeId); 33 | checkID_ClearAndSetTimeout(setTimeoutId, recentTimeoutId, state); 34 | }} 35 | 36 | > 37 |
    38 | { 43 | changeType(event, childId); 44 | showSubTree(currentlyDisplayedSubTreeId); 45 | checkID_ClearAndSetTimeout(setTimeoutId, recentTimeoutId, state); 46 | }} 47 | /> 48 | Container 49 |
    50 | 57 |
    58 | ); 59 | 60 | export default EachChild; 61 | -------------------------------------------------------------------------------- /client/components/TemplateDropdown.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from "react"; 2 | import Dropdown from "react-bootstrap/Dropdown"; 3 | 4 | /** 5 | * changes in code templates for a component/container will cached in local state as well as redux state 6 | */ 7 | const TemplateDropdown = ({ 8 | templates, 9 | setTemplatesForComponent, 10 | currentComponent, 11 | nameAndCodeLinkedToComponentId, 12 | state, 13 | recentTimeoutId, 14 | setTimeoutId, 15 | checkID_ClearAndSetTimeout 16 | }) => { 17 | const [isDefault, setIsDefault] = useState(""); 18 | const [isCurrentId] = useState(currentComponent.componentId); 19 | if ( 20 | nameAndCodeLinkedToComponentId && 21 | nameAndCodeLinkedToComponentId[currentComponent.componentId] && 22 | isDefault !== 23 | nameAndCodeLinkedToComponentId[currentComponent.componentId].name 24 | ) { 25 | let name = 26 | nameAndCodeLinkedToComponentId[currentComponent.componentId].name; 27 | setIsDefault(name); 28 | } 29 | 30 | useEffect(() => { 31 | return () => { 32 | setIsDefault(""); 33 | }; 34 | }, []); 35 | 36 | return ( 37 | 38 | 39 | {!isDefault ? "Default Template - Class Syntax" : isDefault} 40 | 41 | 42 | {templates.length > 0 43 | ? templates.map((template, i) => { 44 | return ( 45 | { 48 | e.preventDefault(); 49 | if (template.name !== isDefault) { 50 | checkID_ClearAndSetTimeout(setTimeoutId, recentTimeoutId, state) 51 | setTemplatesForComponent(currentComponent, template); 52 | setIsDefault(template.name); 53 | } 54 | }} 55 | > 56 | {template.name} 57 | 58 | ); 59 | }) 60 | : null} 61 | 62 | 63 | ); 64 | }; 65 | export default TemplateDropdown; 66 | -------------------------------------------------------------------------------- /client/landing-page/Action.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Link } from 'react-router-dom'; 3 | import ScrollAnimation from 'react-animate-on-scroll'; 4 | 5 | const Action = () => { 6 | return ( 7 |
    8 |

    Get Started Now

    9 |
    10 | 11 | 12 | 16 | 17 | 18 | 19 | 20 | 24 | 25 | 26 | 27 | 28 | 32 | 33 | 34 | 35 | 36 | 40 | 41 | 42 |
    43 |

    Usage

    44 | 45 | 49 | 53 | 54 | 55 |
    56 | ); 57 | }; 58 | 59 | export default Action; 60 | -------------------------------------------------------------------------------- /client/landing-page/Team.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import ScrollAnimation from 'react-animate-on-scroll'; 3 | 4 | const Team = () => { 5 | const [isCreatorProfiles] = useState([ 6 | { 7 | name: 'Darren Zhu', 8 | github: 'https://github.com/Joodongri', 9 | linkedin: 'https://www.linkedin.com/in/darrenDzhu' 10 | }, 11 | { 12 | name: 'Kendall Lu', 13 | github: 'https://github.com/kendall-lu', 14 | linkedin: 'https://www.linkedin.com/in/kendall-lu' 15 | }, 16 | { 17 | name: 'Randy Reyes', 18 | github: 'https://github.com/rqreyes', 19 | linkedin: 'https://www.linkedin.com/in/rqreyes' 20 | }, 21 | { 22 | name: 'Krystal Chen', 23 | github: 'https://github.com/kcrystalchen', 24 | linkedin: 'https://www.linkedin.com/in/kcrystalchen' 25 | } 26 | ]); 27 | const creatorProfileArray = isCreatorProfiles.map(profile => { 28 | return ( 29 | 36 | ); 37 | }); 38 | return ( 39 |
    40 |

    Meet the Team

    41 |
    {creatorProfileArray}
    42 |
    43 | ); 44 | }; 45 | 46 | const Profiles = ({ src, name, linkedin, github }) => { 47 | return ( 48 | 49 |
    50 | 51 |
    52 |
    53 |
    54 |
    55 |
    {name}
    56 |
    57 |
    58 | 66 |
    67 | 68 |
    69 | ); 70 | }; 71 | 72 | export default Team; 73 | -------------------------------------------------------------------------------- /__tests__/template.enzyme.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { configure, shallow } from 'enzyme'; 3 | import Adapter from 'enzyme-adapter-react-16'; 4 | import TemplateArea from '../client/components/TemplatingArea'; 5 | import { useTemplates } from '../client/actions/actions'; 6 | import CreateCodeEditor from '../client/components/CreateCodeEditor'; 7 | configure({ adapter: new Adapter() }); 8 | 9 | describe('Template unit tests', () => { 10 | describe('TemplateArea', () => { 11 | let wrapper, headings; 12 | // functions inside the templateArea 13 | let deleteMock = jest.fn(); 14 | 15 | // props inside the templateArea 16 | let props = { 17 | isInitialSyntax: ['template1', 'template2'] 18 | }; 19 | 20 | // shallow copy the TemplateArea with all props 21 | beforeAll(() => { 22 | wrapper = shallow(); 23 | headings = wrapper.find('h3'); 24 | console.log(headings.debug()); 25 | }); 26 | it('Renders an Add Template feature', () => { 27 | expect(headings.at(0).text()).toMatch('Add Template'); 28 | const isHook = wrapper.at(1).find('input[type="checkbox"]'); 29 | // console.log(isHook.debug()); 30 | // expect(isHook) 31 | // .simulate('click') 32 | // .toBe(true); 33 | // wrapper.find('input[type="checkbox"]').simulate('click'); 34 | expect(isHook).toEqual(true); 35 | // wrapper.find('button[type="submit"]').simulate('click'); 36 | // expect(props.isInitialSyntax.length).toBe(3); 37 | }); 38 | 39 | it('Renders a Template List feature', () => { 40 | expect(wrapper.find('div[className=".template-container"]')); 41 | }); 42 | 43 | }); 44 | 45 | // pass component to shallow() method from Enzyme and store is in a wrapper variable. Then check that this component exists using a boolean assertion. 46 | describe('CreateCodeEditor Component', () => { 47 | test("renders", () => { 48 | const wrapper1 = shallow(< CreateCodeEditor />); 49 | expect(wrapper1.exists()).toBe(true); 50 | }); 51 | }) 52 | }); -------------------------------------------------------------------------------- /client/components/OnClickShowCodeMirror.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import 'codemirror/lib/codemirror.css'; 3 | import CodeMirror from 'react-codemirror'; 4 | require('codemirror/mode/javascript/javascript'); 5 | require('codemirror/mode/xml/xml'); 6 | require('codemirror/mode/markdown/markdown'); 7 | require('codemirror/mode/css/css'); 8 | require('codemirror/mode/htmlembedded/htmlembedded'); 9 | require('codemirror/mode/htmlmixed/htmlmixed'); 10 | /** 11 | * Template display: 12 | * changes are immediately updated to local state and updated to redux state as well 13 | */ 14 | const OnClickShowCodeMirror = ({ code, updateCode, index, deleteTemplate }) => { 15 | const [isClicked, setIsClicked] = useState(false); 16 | const [isSave, setIsSave] = useState(false); 17 | return isClicked ? ( 18 | 19 | 31 | {index > 1 ? ( 32 | 39 | ) : null} 40 | { 43 | updateCode(value, index); 44 | }} 45 | options={{ 46 | lineNumbers: true 47 | }} 48 | /> 49 | 50 | ) : ( 51 | 52 | 64 | {index > 1 ? ( 65 | 72 | ) : null} 73 | 74 | ); 75 | }; 76 | export default OnClickShowCodeMirror; 77 | -------------------------------------------------------------------------------- /client/reducers/utils/updateTree.js: -------------------------------------------------------------------------------- 1 | import clone from 'clone'; 2 | export function DoublyLinkedList(value) { 3 | this.value = value; 4 | this.prev = null; 5 | this.next = null; 6 | } 7 | const getCircularReplacer = () => { 8 | const seen = new WeakSet(); 9 | return (key, value) => { 10 | if (typeof value === 'object' && value !== null) { 11 | if (seen.has(value)) { 12 | return; 13 | } 14 | seen.add(value); 15 | } 16 | return value; 17 | }; 18 | }; 19 | export const updateTree = (state, currentComponent) => { 20 | let defaultNameCount; 21 | const data = clone(state.data); 22 | if (!currentComponent.name) { 23 | defaultNameCount = state.defaultNameCount + 1; 24 | currentComponent.name = `Component${defaultNameCount}`; 25 | } 26 | // check if any child has empty name, then change it to 'DEFAULT NAME' 27 | let children = currentComponent.children 28 | if (children) { 29 | for (let child of children) { 30 | if (child.name === '') { 31 | defaultNameCount = defaultNameCount 32 | ? defaultNameCount + 1 33 | : state.defaultNameCount + 1 34 | } 35 | } 36 | } else { 37 | children = currentComponent 38 | children.name = currentComponent.name; 39 | } 40 | function findComponentAndUpdate(data, currentComponent) { 41 | if (!data) return; 42 | if (data.componentId === currentComponent.componentId) { 43 | data.name = currentComponent.name; 44 | data.isContainer = currentComponent.isContainer; 45 | data.children = currentComponent.children 46 | return; 47 | } 48 | if (data.children) { 49 | data.children.forEach(child => { 50 | return findComponentAndUpdate(child, currentComponent); 51 | }); 52 | } 53 | }; 54 | findComponentAndUpdate(data, currentComponent); 55 | const preHistory = state.history; 56 | const displaySubTreeDropDown = Object.assign({}, state.displaySubTreeDropDown); 57 | const history = new DoublyLinkedList( 58 | { 59 | data, 60 | currentComponent, 61 | nameAndCodeLinkedToComponentId: state.nameAndCodeLinkedToComponentId, 62 | lastId: state.lastId, 63 | defaultNameCount: state.defaultNameCount, 64 | displaySubTreeDropDown 65 | } 66 | ); 67 | preHistory.next = history; 68 | history.prev = preHistory; 69 | return { 70 | data, 71 | currentComponent, 72 | history, 73 | defaultNameCount: defaultNameCount 74 | ? defaultNameCount 75 | : state.defaultNameCount 76 | }; 77 | }; 78 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-blue", 3 | "version": "1.0.0", 4 | "description": "React prototyping tool for creating file structure", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "NODE_ENV=development webpack-dev-server --open", 8 | "build": "NODE_ENV=production webpack --history-api-fallback", 9 | "dev": "NODE_ENV=development webpack-dev-server --open --history-api-fallback", 10 | "test": "jest --verbose" 11 | }, 12 | "jest": { 13 | "moduleNameMapper": { 14 | "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "/__mocks__/fileMock.js", 15 | "\\.(css|less)$": "identity-obj-proxy" 16 | } 17 | }, 18 | "author": "", 19 | "license": "MIT", 20 | "dependencies": { 21 | "@material-ui/core": "^4.5.2", 22 | "@material-ui/icons": "^4.5.1", 23 | "bootstrap": "^4.3.1", 24 | "clone": "^2.1.2", 25 | "codemirror": "^5.49.0", 26 | "file-saver": "^2.0.2", 27 | "hotkeys-js": "^3.7.2", 28 | "jest": "^24.9.0", 29 | "jszip": "^3.2.2", 30 | "react": "^16.10.2", 31 | "react-animate-on-scroll": "^2.1.5", 32 | "react-bootstrap": "^1.0.0-beta.14", 33 | "react-codemirror": "^1.0.0", 34 | "react-d3-tree": "^1.15.3", 35 | "react-dom": "^16.10.2", 36 | "react-github-btn": "^1.1.1", 37 | "react-particles-js": "^2.7.0", 38 | "react-redux": "^7.1.1", 39 | "react-router": "^5.1.2", 40 | "react-router-dom": "^5.1.2", 41 | "react-scroll": "^1.7.14", 42 | "redux": "^4.0.4", 43 | "redux-devtools-extension": "^2.13.8", 44 | "redux-thunk": "^2.3.0" 45 | }, 46 | "devDependencies": { 47 | "@babel/core": "^7.1.2", 48 | "@babel/plugin-transform-async-to-generator": "^7.5.0", 49 | "@babel/plugin-transform-runtime": "^7.6.2", 50 | "@babel/preset-env": "^7.1.0", 51 | "@babel/preset-react": "^7.0.0", 52 | "@testing-library/react": "^9.3.0", 53 | "@testing-library/user-event": "^7.1.2", 54 | "babel-loader": "^8.0.4", 55 | "concurrently": "^4.1.2", 56 | "cross-env": "^6.0.0", 57 | "css-loader": "^1.0.1", 58 | "enzyme": "^3.10.0", 59 | "enzyme-adapter-react-16": "^1.15.1", 60 | "enzyme-to-json": "^3.4.2", 61 | "file-loader": "^4.0.0", 62 | "identity-obj-proxy": "^3.0.0", 63 | "node-sass": "^4.12.0", 64 | "sass-loader": "^8.0.0", 65 | "style-loader": "^0.23.1", 66 | "url-loader": "^2.0.1", 67 | "webpack": "^4.20.2", 68 | "webpack-cli": "^3.1.2", 69 | "webpack-dev-server": "^3.1.9", 70 | "webpack-hot-middleware": "^2.24.3" 71 | } 72 | } -------------------------------------------------------------------------------- /client/reducers/utils/deleteNodeFuncs.js: -------------------------------------------------------------------------------- 1 | 2 | export const deleteChildrenInNameAndCodeLinkedToComponentId = (node, obj) => { 3 | if (node instanceof Object) { 4 | delete obj[node] 5 | return obj; 6 | } 7 | node.forEach((childNode, i) => { 8 | delete obj[childNode]; 9 | if (childNode.children) { 10 | delete obj[childNode]; 11 | deleteChildrenInNameAndCodeLinkedToComponentId(childNode.children, obj); 12 | } 13 | }); 14 | return obj; 15 | } 16 | export const findAndDeleteInCurrentComponent = (tree, currentComponent, parent) => { 17 | if (tree.componentId === parent.componentId) { 18 | for (let i = 0; i < tree.children.length; i++) { 19 | if(tree.children[i] === null){ 20 | tree.children.splice(i, 1); 21 | } 22 | if (tree.children[i].componentId === currentComponent.componentId) { 23 | tree.children.splice(i, 1); 24 | parent.children = tree.children.slice(); 25 | return; 26 | } 27 | } 28 | } else if (tree.children) { 29 | tree.children.forEach(child => { 30 | return findAndDeleteInCurrentComponent(child, currentComponent, parent); 31 | }); 32 | } 33 | }; 34 | 35 | export const findSubTreeAndDeleteAllPropertiesInObjectRelatedToSubTree = (id, data, displaySubTreeDropDown)=>{ 36 | let subTreeToDeleteFrom; 37 | function findSubTree(data, id){ 38 | if (!data) return; 39 | if (data.componentId === id) { 40 | subTreeToDeleteFrom = data; 41 | return; 42 | } 43 | if (data.children) { 44 | data.children.forEach(node => { 45 | return findSubTree(node, id); 46 | }); 47 | } 48 | } 49 | findSubTree(data, id); 50 | function deleteFromFoundSubTree(subTreeToDeleteFrom, displaySubTreeDropDown){ 51 | if (!subTreeToDeleteFrom) return; 52 | if (displaySubTreeDropDown[subTreeToDeleteFrom.componentId]){ 53 | delete displaySubTreeDropDown[subTreeToDeleteFrom.componentId]; 54 | } 55 | if (subTreeToDeleteFrom.children){ 56 | subTreeToDeleteFrom.children.forEach(node =>{ 57 | return deleteFromFoundSubTree(node, displaySubTreeDropDown); 58 | }) 59 | } 60 | } 61 | deleteFromFoundSubTree(subTreeToDeleteFrom, displaySubTreeDropDown) 62 | return; 63 | } 64 | 65 | export const deletePropertiesInsideOfSubTree = (currentComponent, displaySubTreeDropDown) =>{ 66 | if (displaySubTreeDropDown[currentComponent.componentId]){ 67 | delete displaySubTreeDropDown[currentComponent.componentId]; 68 | } 69 | if (currentComponent.children){ 70 | currentComponent.children.forEach(node =>{ 71 | return deletePropertiesInsideOfSubTree(node, displaySubTreeDropDown); 72 | }) 73 | } 74 | return; 75 | } 76 | -------------------------------------------------------------------------------- /client/landing-page/Features.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ScrollAnimation from 'react-animate-on-scroll'; 3 | 4 | const Features = () => { 5 | return ( 6 |
    7 |

    Streamline Your Development Process

    8 |
    9 |
    10 | feature 1 11 |
    12 | 13 |
    14 |

    Engineer-first Approach

    15 |

    16 | We envision the ability for engineers to quickly create their 17 | component file structure coupled with a friendly UI/UX. This tool 18 | provides an export feature that sets up a pre-configured 19 | development environment for front-end and full-stack React 20 | applications. 21 |

    22 |
    23 |
    24 |
    25 |
    26 | 27 |
    28 |

    Why Use Us?

    29 |
      30 |
    • 31 | Create your React file structure, without a single line of code 32 |
    • 33 |
    • 34 | Need to create an application at scale? Perfect, our 35 | visualization tool is optimized for it 36 |
    • 37 |
    • 38 | Choose between React Hooks or React Class component templates, 39 | or make your own 40 |
    • 41 |
    • 42 | We get it, coffee is important - come back later, we’ve cached 43 | your work 44 |
    • 45 |
    46 |
    47 |
    48 |
    49 | feature 2 50 |
    51 |
    52 |
    53 |
    54 | 55 | 56 |
    57 | 58 |
    59 |

    Shortcuts and Views

    60 |

    61 | Keyboard shortcuts right at your fingertips to perform undo 62 | (ctrl+z) and redo (ctrl+shift+z) actions and toggle between 63 | horizontal and vertical views of the component tree. 64 |

    65 |
    66 |
    67 |
    68 |
    69 | ); 70 | }; 71 | 72 | export default Features; 73 | -------------------------------------------------------------------------------- /client/components/FileTree.jsx: -------------------------------------------------------------------------------- 1 | import React, {useMemo, useCallback} from 'react'; 2 | import File from './File.jsx'; 3 | /** 4 | * File display: 5 | * Container || Component 6 | * click a specific container || component to show the current the clicked as current component (is bolded and made blue for (+)UX xD) 7 | * _____________________________________________________________________________________________________________________ 8 | * filterFiles fn() : recursively loops through the current subtree to create the displays between container and component 9 | */ 10 | const FileTree = ({ currentComponent, currentSubTreeDisplayToUser, setCurrentComponent, toggleFileTree }) => { 11 | const containerFiles = []; 12 | const componentFiles = []; 13 | 14 | const filterFiles = currentComponent => { 15 | if (currentComponent.isContainer) { 16 | containerFiles.push(currentComponent); 17 | } else { 18 | componentFiles.push(currentComponent); 19 | } 20 | if (currentComponent.children) { 21 | return currentComponent.children.forEach(child => { 22 | filterFiles(child); 23 | }); 24 | } 25 | }; 26 | filterFiles(currentSubTreeDisplayToUser); 27 | 28 | const getFileTree = () => { 29 | return toggleFileTree ? 'hidden' : ''; 30 | }; 31 | 32 | return ( 33 |
    34 |
      35 |
    • 36 |

      Containers

      37 |
        38 | {containerFiles.map((file, index) => { 39 | return currentComponent.componentId === file.componentId ? 40 | (
        41 |
        ) : 46 | () 52 | })} 53 |
      54 |
    • 55 |
    • 56 |

      Components

      57 |
        58 | {componentFiles.map((file, index) => { 59 | return currentComponent.componentId === file.componentId ? 60 | (
        61 |
        ) : 66 | () 72 | })} 73 |
      74 |
    • 75 |
    76 |
    77 | ); 78 | 79 | }; 80 | 81 | export default React.memo(FileTree); 82 | -------------------------------------------------------------------------------- /client/templates-exports/frontEndFiles.js: -------------------------------------------------------------------------------- 1 | import JSZip from 'jszip'; 2 | import indexHTML from './frontEndTemplates/indexHTML.js'; 3 | import indexJS from './frontEndTemplates/indexJS.js'; 4 | import { saveAs } from 'file-saver'; 5 | 6 | function connectFiles(currentComponent, code, fileObject) { 7 | let childComponents, imports; 8 | if (currentComponent.children) { 9 | imports = currentComponent.children 10 | .map(child => { 11 | if (child.isContainer) { 12 | return `import ${child.name} from './containers/${child.name}.jsx';\n`; 13 | } else { 14 | return `import ${child.name} from './components/${child.name}.jsx';\n`; 15 | } 16 | }) 17 | .join(''); 18 | childComponents = currentComponent.children.map(child => { 19 | return `\t<${child.name} />\n\t\t`; 20 | }) 21 | .join(''); 22 | } else if (!currentComponent.children) { 23 | imports = ""; 24 | } 25 | if (childComponents) { 26 | code = code.replace('DONOTDELETETHISSTRING', childComponents) 27 | } else { 28 | code = code.replace('DONOTDELETETHISSTRING', '') 29 | } 30 | if (currentComponent.isContainer) { 31 | fileObject.container[currentComponent.name] = imports.concat(code.replace("Template_Class", currentComponent.name)); 32 | } else { 33 | fileObject.component[currentComponent.name] = imports.concat(code.replace("Template_Class", currentComponent.name)); 34 | } 35 | return fileObject; 36 | } 37 | 38 | export default (data, nameAndCodeLinkedToComponentId) => { 39 | const zip = new JSZip(); 40 | let fileCounter = { 41 | container: {}, 42 | component: {} 43 | }; 44 | function recursivelyCreateTemplates(data, nameAndCode, fileCounter) { 45 | for (let id in nameAndCode) { 46 | if (JSON.stringify(data.componentId) === id) { 47 | let newFileCounter = connectFiles(data, nameAndCode[id].code, fileCounter); 48 | fileCounter = newFileCounter; 49 | } 50 | } 51 | if (data.children) { 52 | data.children.forEach(child => { 53 | recursivelyCreateTemplates(child, nameAndCode, fileCounter); 54 | }) 55 | } else return; 56 | } 57 | 58 | recursivelyCreateTemplates(data, nameAndCodeLinkedToComponentId, fileCounter); 59 | 60 | 61 | // creating zip file/folder 62 | const containerObject = fileCounter.container; 63 | const componentObject = fileCounter.component; 64 | for (let container in containerObject) { 65 | zip.file(`containers/${container}.jsx`, containerObject[container]); 66 | } 67 | for (let component in componentObject) { 68 | zip.file(`components/${component}.jsx`, componentObject[component]); 69 | } 70 | zip.file('assets/index.html', indexHTML); 71 | zip.file('assets/styles/styles.css', ''); 72 | zip.file('index.js', indexJS); 73 | 74 | zip.generateAsync({ type: 'blob' }).then(function (content) { 75 | saveAs(content, 'react-blue.zip'); 76 | }); 77 | }; 78 | 79 | 80 | -------------------------------------------------------------------------------- /client/containers/VisualContainer.jsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, memo } from 'react'; 2 | import Tree from 'react-d3-tree'; 3 | import hotkeys from 'hotkeys-js'; 4 | /** 5 | * Issue: When D3 tree receives the nested property from state(data) it will create an _children that is *hidden*; 6 | * when deleting children nodes, _children would replace the children property inside of the node; 7 | * Example: (3 children nodes under one parent, when deleting the 3 children nodes everything worked smoothly when deleting 2 children but when deleting the last child; the _children will replace the empty children array with all 3 children) 8 | * Solution: Recursively found if the length of the children array was empty, if so delete _children; 9 | */ 10 | function deleteNull_ChildrenFromD3Tree(data) { 11 | if (!data) return; 12 | if (!data.children) { 13 | if (data.parent && data.parent.children) { 14 | data.parent.children = data.parent.children.filter(el => el !== null); 15 | } 16 | delete data.children; 17 | return; 18 | } 19 | if (data.children && !data.children.length) { 20 | delete data._children; 21 | return; 22 | } 23 | for (let i = 0; i < data.children.length; i += 1) { 24 | if (data.children[i] === null) { 25 | data.children.splice(i, 1); 26 | continue; 27 | } 28 | deleteNull_ChildrenFromD3Tree(data.children[i]); 29 | } 30 | if (data.children.includes(null)) { 31 | deleteNull_ChildrenFromD3Tree(data); 32 | } 33 | } 34 | /** 35 | * hotkeys fn() : Hotkey feature, event handlers listening to key down presses of the options. 36 | * 37 | * useEffect hook(): Clear data object on unmount 38 | */ 39 | const VisualContainer = ({ 40 | translate, 41 | orientation, 42 | setCurrentComponent, 43 | undo, 44 | redo, 45 | currentSubTreeDisplayToUser, 46 | showSubTree 47 | }) => { 48 | deleteNull_ChildrenFromD3Tree(currentSubTreeDisplayToUser); 49 | const undoFunc = undo; 50 | const redoFunc = redo; 51 | hotkeys('ctrl+z, ctrl+shift+z', function(event, handler) { 52 | event.preventDefault(); 53 | switch (handler.key) { 54 | case 'ctrl+z': 55 | undoFunc(); 56 | break; 57 | case 'ctrl+shift+z': 58 | redoFunc(); 59 | break; 60 | } 61 | showSubTree(); 62 | }); 63 | useEffect(() => { 64 | return () => { 65 | showSubTree(0); 66 | }; 67 | }, []); 68 | return ( 69 |
    70 | { 91 | setCurrentComponent(currentComponent); 92 | }} 93 | transitionDuration={500} 94 | /> 95 |
    96 | ); 97 | }; 98 | export default memo(VisualContainer); 99 | -------------------------------------------------------------------------------- /client/templates-exports/fullStackFiles.js: -------------------------------------------------------------------------------- 1 | import JSZip from 'jszip'; 2 | import { saveAs } from 'file-saver'; 3 | import indexHTML from './frontEndTemplates/indexHTML.js'; 4 | import indexJS from './frontEndTemplates/indexJS.js'; 5 | import server from './fullStackTemplates/server.js'; 6 | import packageJSON from './fullStackTemplates/packageJSON.js'; 7 | import webpack from './fullStackTemplates/webpack.config.js'; 8 | import readmeMD from './fullStackTemplates/readmeMD.js'; 9 | 10 | function connectFiles(currentComponent, code, fileObject) { 11 | let childComponents, imports; 12 | if (currentComponent.children) { 13 | imports = currentComponent.children 14 | .map(child => { 15 | if (child.isContainer) { 16 | return `import ${child.name} from './containers/${child.name}.jsx';\n`; 17 | } else { 18 | return `import ${child.name} from './components/${child.name}.jsx';\n`; 19 | } 20 | }) 21 | .join(''); 22 | childComponents = currentComponent.children.map(child => { 23 | return `\t<${child.name} />\n\t\t`;; 24 | }) 25 | .join(''); 26 | } else if (!currentComponent.children) { 27 | imports = ""; 28 | } 29 | if (childComponents) { 30 | code = code.replace('DONOTDELETETHISSTRING', childComponents) 31 | } else { 32 | code = code.replace('DONOTDELETETHISSTRING', '') 33 | } 34 | if (currentComponent.isContainer) { 35 | fileObject.container[currentComponent.name] = imports.concat( 36 | code.replace('Template_Class', currentComponent.name) 37 | ); 38 | } else { 39 | fileObject.component[currentComponent.name] = imports.concat( 40 | code.replace('Template_Class', currentComponent.name) 41 | ); 42 | } 43 | return fileObject; 44 | } 45 | 46 | export default (data, nameAndCodeLinkedToComponentId) => { 47 | const zip = new JSZip(); 48 | let fileCounter = { 49 | container: {}, 50 | component: {} 51 | }; 52 | function recursivelyCreateTemplates(data, nameAndCode, fileCounter) { 53 | for (let id in nameAndCode) { 54 | if (JSON.stringify(data.componentId) === id) { 55 | let newFileCounter = connectFiles( 56 | data, 57 | nameAndCode[id].code, 58 | fileCounter 59 | ); 60 | fileCounter = newFileCounter; 61 | } 62 | } 63 | if (data.children) { 64 | data.children.forEach(child => { 65 | recursivelyCreateTemplates(child, nameAndCode, fileCounter); 66 | }); 67 | } else return; 68 | } 69 | recursivelyCreateTemplates(data, nameAndCodeLinkedToComponentId, fileCounter); 70 | const containerObject = fileCounter.container; 71 | const componentObject = fileCounter.component; 72 | for (let container in containerObject) { 73 | zip.file(`containers/${container}.jsx`, containerObject[container]); 74 | } 75 | for (let component in componentObject) { 76 | zip.file(`components/${component}.jsx`, componentObject[component]); 77 | } 78 | zip.file('assets/index.html', indexHTML); 79 | zip.file('assets/styles/styles.css', ''); 80 | zip.file('index.js', indexJS); 81 | zip.file('server/server.js', server); 82 | zip.file('package.json', packageJSON); 83 | zip.file('webpack.config.js', webpack); 84 | zip.file('server/readmeMD.js', readmeMD); 85 | 86 | zip.generateAsync({ type: 'blob' }) 87 | .then(function (content) { 88 | 89 | saveAs(content, 'react-blue.zip'); 90 | }); 91 | }; 92 | -------------------------------------------------------------------------------- /__mock__/stateMocks.js: -------------------------------------------------------------------------------- 1 | import { DoublyLinkedList } from '../client/reducers/utils/updateTree' 2 | 3 | const appComponent = { 4 | name: "App", 5 | depth: 0, 6 | id: 0, 7 | componentId: 0, 8 | isContainer: true, 9 | children: [] 10 | }; 11 | 12 | const childComponent1 = { 13 | name: "childComponent1", 14 | depth: 1, 15 | id: 1, 16 | componentId: 1, 17 | parent: appComponent, 18 | isContainer: false, 19 | children: [] 20 | } 21 | 22 | const childComponent2 = { 23 | name: "childComponent2", 24 | depth: 1, 25 | id: 2, 26 | componentId: 2, 27 | parent: appComponent, 28 | isContainer: false, 29 | children: [] 30 | } 31 | 32 | const appComponentWithChild = { 33 | name: "App", 34 | depth: 0, 35 | id: 0, 36 | componentId: 0, 37 | isContainer: true, 38 | children: [childComponent1] 39 | }; 40 | 41 | const appComponentWithChildren = { 42 | name: "App", 43 | depth: 0, 44 | id: 0, 45 | componentId: 0, 46 | isContainer: true, 47 | children: [childComponent1, childComponent2] 48 | }; 49 | 50 | const initialNode = new DoublyLinkedList({ 51 | data: appComponent, 52 | translate: { x: 0, y: 0 }, 53 | currentComponent: appComponent, 54 | nameAndCodeLinkedToComponentId: {}, 55 | lastId: 0, 56 | defaultNameCount: 0 57 | }); 58 | 59 | const currentNode = new DoublyLinkedList({ 60 | value: new DoublyLinkedList({ 61 | data: appComponentWithChild, 62 | translate: { x: 50, y: 50 }, 63 | currentComponent: appComponentWithChild, 64 | nameAndCodeLinkedToComponentId: {}, 65 | lastId: 1, 66 | defaultNameCount: 0 67 | }), 68 | }); 69 | 70 | const nextNode = new DoublyLinkedList({ 71 | data: appComponentWithChildren, 72 | translate: { x: 50, y: 50 }, 73 | currentComponent: appComponentWithChildren, 74 | nameAndCodeLinkedToComponentId: {}, 75 | lastId: 2, 76 | defaultNameCount: 0 77 | }); 78 | 79 | export const initialHistory = { 80 | value: initialNode, 81 | prev: null, 82 | next: null 83 | } 84 | 85 | export const currentHistory = { 86 | value: currentNode, 87 | prev: initialNode, 88 | next: nextNode 89 | } 90 | 91 | export const nextHistory = { 92 | value: nextNode, 93 | prev: currentNode, 94 | next: null 95 | } 96 | 97 | 98 | export const initialStateMock = { 99 | data: appComponent, 100 | translate: { x: 0, y: 0 }, 101 | history: initialHistory, 102 | currentComponent: appComponent, 103 | nameAndCodeLinkedToComponentId: {}, 104 | lastId: 0, 105 | defaultNameCount: 0, 106 | templates: [], 107 | orientation: "vertical" 108 | }; 109 | 110 | export const stateWithChildMock = { 111 | data: appComponentWithChild, 112 | translate: { x: 50, y: 50 }, 113 | history: currentHistory, 114 | currentComponent: childComponent1, 115 | nameAndCodeLinkedToComponentId: {}, 116 | lastId: 1, 117 | defaultNameCount: 0, 118 | templates: [], 119 | orientation: "vertical" 120 | } 121 | 122 | export const stateWithChildrenMock = { 123 | data: appComponentWithChildren, 124 | translate: { x: 50, y: 50 }, 125 | history: nextHistory, 126 | currentComponent: childComponent2, 127 | nameAndCodeLinkedToComponentId: {}, 128 | lastId: 2, 129 | defaultNameCount: 0, 130 | templates: [], 131 | orientation: "vertical" 132 | } 133 | -------------------------------------------------------------------------------- /client/landing-page/LandingPage.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import AppBar from '@material-ui/core/AppBar'; 3 | import Toolbar from '@material-ui/core/Toolbar'; 4 | import Menu from '@material-ui/core/Menu'; 5 | import MenuItem from '@material-ui/core/MenuItem'; 6 | import Button from '@material-ui/core/Button'; 7 | import { Link } from 'react-router-dom'; 8 | import Particles from 'react-particles-js'; 9 | import { Link as LinkScroll, animateScroll } from 'react-scroll'; 10 | import logo from '../assets/images/logo.png'; 11 | 12 | import Hero from './Hero'; 13 | import Features from './Features'; 14 | import Action from './Action'; 15 | import Details from './Details'; 16 | import Team from './Team'; 17 | 18 | const LandingPage = () => { 19 | const [anchorEl, setAnchorEl] = React.useState(null); 20 | 21 | const handleClick = event => { 22 | setAnchorEl(event.currentTarget); 23 | }; 24 | 25 | const handleClose = () => { 26 | setAnchorEl(null); 27 | }; 28 | 29 | return ( 30 |
    31 | 32 | 33 |
    34 |
    35 | react blue logo 36 |
    37 |

    React Blue

    38 | 39 | Features 40 | 41 | 42 | Contribute 43 | 44 | 45 | Team 46 | 47 |
    48 |
    49 | 56 | 63 | 64 | Web App 65 | 66 | 67 | Download Mac 68 | 69 | 70 | Download Linux 71 | 72 | 73 | Download Windows 74 | 75 | 76 |
    77 |
    78 |
    79 | 100 | 101 | 102 | 103 |
    104 | 105 |
    106 | ); 107 | }; 108 | 109 | export default LandingPage; 110 | -------------------------------------------------------------------------------- /client/components/ChildrenList.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import EachChild from './EachChild.jsx'; 3 | import TemplateDropdown from './TemplateDropdown.jsx'; 4 | const ChildrenList = ({ 5 | addChild, 6 | renameChild, 7 | changeChildType, 8 | deleteChild, 9 | templates, 10 | setTemplatesForComponent, 11 | currentComponent, 12 | nameAndCodeLinkedToComponentId, 13 | state, 14 | recentTimeoutId, 15 | setTimeoutId, 16 | checkID_ClearAndSetTimeout, 17 | showSubTree, 18 | currentlyDisplayedSubTreeId, 19 | }) => { 20 | return ( 21 | 22 |

    Add Child

    23 |
    { 24 | addChild(e); 25 | showSubTree(currentlyDisplayedSubTreeId); 26 | checkID_ClearAndSetTimeout(setTimeoutId, recentTimeoutId, state); 27 | }}> 28 | 29 | 35 |
    36 | 41 | 47 |
    48 | 51 |
    52 |

    Children List

    53 |
    54 | {currentComponent.children && 55 | currentComponent.children.filter((node, index) => { 56 | return node !== null; 57 | }).map((child, index) => { 58 | return childMaker( 59 | child, 60 | index, 61 | renameChild, 62 | changeChildType, 63 | deleteChild, 64 | templates, 65 | setTemplatesForComponent, 66 | nameAndCodeLinkedToComponentId, 67 | state, 68 | recentTimeoutId, 69 | setTimeoutId, 70 | checkID_ClearAndSetTimeout, 71 | showSubTree, 72 | currentlyDisplayedSubTreeId 73 | ) 74 | } 75 | )} 76 |
    77 |
    78 | ); 79 | }; 80 | 81 | const childMaker = ( 82 | child, 83 | index, 84 | renameChild, 85 | changeChildType, 86 | deleteChild, 87 | templates, 88 | setTemplatesForComponent, 89 | nameAndCodeLinkedToComponentId, 90 | state, 91 | recentTimeoutId, 92 | setTimeoutId, 93 | checkID_ClearAndSetTimeout, 94 | showSubTree, 95 | currentlyDisplayedSubTreeId 96 | ) => { 97 | return ( 98 |
    99 | 114 | 126 |
    127 | ); 128 | }; 129 | 130 | export default ChildrenList; 131 | 132 | -------------------------------------------------------------------------------- /client/App.jsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect } from 'react'; 2 | import { connect } from 'react-redux'; 3 | import { bindActionCreators } from 'redux'; 4 | import { 5 | setTransAndHistory, 6 | updateStateWithLocalStorage, 7 | undo, 8 | redo, 9 | setCurrentComponent, 10 | showSubTree 11 | } from './actions/actions'; 12 | import clone from 'clone'; 13 | import TopNavContainer from './containers/TopNavContainer.jsx'; 14 | import PanelContainer from './containers/PanelContainer.jsx'; 15 | import VisualContainer from './containers/VisualContainer.jsx'; 16 | /** 17 | * Doubly Linked List constructor function for undo & redo feature 18 | * 19 | * Inserting nodes at head position so no traversal of the LL is necessary 20 | **/ 21 | function DoublyLinkedList(value) { 22 | this.value = value; 23 | this.prev = null; 24 | this.next = null; 25 | } 26 | 27 | const mapStateToProps = store => ({ 28 | state: store.main, 29 | data: store.main.data, 30 | translate: store.main.translate, 31 | orientation: store.main.orientation, 32 | currentSubTreeDisplayToUser: store.main.currentSubTreeDisplayToUser, 33 | currentlyDisplayedSubTreeId: store.main.currentlyDisplayedSubTreeId 34 | }); 35 | 36 | const mapDispatchToProps = dispatch => 37 | bindActionCreators( 38 | { 39 | updateStateWithLocalStorage, 40 | setTransAndHistory, 41 | undo, 42 | redo, 43 | setCurrentComponent, 44 | showSubTree 45 | }, 46 | dispatch 47 | ); 48 | 49 | /** 50 | * First render 51 | * 1) check local storage to see if there is a data object, if so send it off (lines 67- 75) to update redux initial state 52 | * 2) create an initial node(DLL) with this.value set to the initial state 53 | * 3) setting center point of node by grabbing the visual container's dimensions 54 | **/ 55 | const App = ({ 56 | state, 57 | updateStateWithLocalStorage, 58 | setTransAndHistory, 59 | undo, 60 | redo, 61 | setCurrentComponent, 62 | data, 63 | translate, 64 | orientation, 65 | currentSubTreeDisplayToUser, 66 | showSubTree, 67 | currentlyDisplayedSubTreeId 68 | }) => { 69 | useEffect(() => { 70 | let data = localStorage.getObj('data'); 71 | if (data) { 72 | const nameAndCodeLinkedToComponentId = localStorage.getObj( 73 | 'nameAndCodeLinkedToComponentId' 74 | ); 75 | const currentComponent = localStorage.getObj('currentComponent'); 76 | const lastId = localStorage.getObj('lastId'); 77 | const history = localStorage.getObj('history'); 78 | const displaySubTreeDropDown = localStorage.getObj( 79 | 'displaySubTreeDropDown' 80 | ); 81 | updateStateWithLocalStorage( 82 | data, 83 | currentComponent, 84 | nameAndCodeLinkedToComponentId, 85 | lastId, 86 | history, 87 | displaySubTreeDropDown 88 | ); 89 | } 90 | const initialHistory = new DoublyLinkedList(clone(state)); 91 | const domElementForVisualContainer = document.getElementById( 92 | 'visual-container' 93 | ); 94 | const dimensions = domElementForVisualContainer.getBoundingClientRect(); 95 | setTransAndHistory( 96 | { 97 | x: dimensions.width / 2, 98 | y: dimensions.height / 6 99 | }, 100 | initialHistory 101 | ); 102 | showSubTree(currentlyDisplayedSubTreeId); 103 | }, []); 104 | return ( 105 |
    106 | 107 |
    108 | 109 | 120 |
    121 |
    122 | ); 123 | }; 124 | 125 | export default connect( 126 | mapStateToProps, 127 | mapDispatchToProps 128 | )(App); 129 | -------------------------------------------------------------------------------- /client/components/ComponentDetail.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Current component display: 3 | * name of component 4 | * component or container(toggle button to change its attribute) 5 | * delete current component (if this component is a parent component, show warning message) 6 | */ 7 | 8 | import React from 'react'; 9 | import TemplateDropdown from './TemplateDropdown.jsx'; 10 | const ComponentDetail = ({ 11 | initialName, 12 | renameComponent, 13 | changeType, 14 | deleteComponent, 15 | currentComponent, 16 | templates, 17 | setTemplatesForComponent, 18 | nameAndCodeLinkedToComponentId, 19 | recentTimeoutId, 20 | setTimeoutId, 21 | checkID_ClearAndSetTimeout, 22 | showSubTree, 23 | currentlyDisplayedSubTreeId, 24 | addOrDeleteNewSubTree, 25 | state, 26 | displaySubTreeDropDown 27 | }) => { 28 | const disabled = () => { 29 | return currentComponent.depth === 0 ? 'disabled' : ''; 30 | }; 31 | return ( 32 | 33 |

    Current Component

    34 |
    35 |
    36 | { 42 | renameComponent(event); 43 | showSubTree(currentlyDisplayedSubTreeId); 44 | checkID_ClearAndSetTimeout(setTimeoutId, recentTimeoutId, state); 45 | }} 46 | disabled={disabled()} 47 | /> 48 |
    49 |
    50 | { 55 | changeType(event); 56 | showSubTree(currentlyDisplayedSubTreeId); 57 | }} 58 | /> 59 | 62 |
    63 |
    64 | { 73 | addOrDeleteNewSubTree( 74 | event, 75 | currentComponent.componentId, 76 | currentComponent.name 77 | ); 78 | checkID_ClearAndSetTimeout( 79 | setTimeoutId, 80 | recentTimeoutId, 81 | state 82 | ); 83 | }} 84 | disabled={disabled()} 85 | /> 86 | 89 |
    90 |
    91 | 100 |
    101 |
    102 | 111 |
    112 |
    113 |
    114 | ); 115 | }; 116 | 117 | export default ComponentDetail; 118 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React Blue 2 | 3 | React Blue is a prototyping and visualization tool that helps engineers build component trees with custom templates. We envision the ability for engineers to quickly create their component file structure coupled with a friendly UI/UX. This tool provides an export feature that sets up a pre-configured development environment for front-end and full-stack React applications. 4 | 5 | React Blue is in beta. The founding team is actively working on new features to improve the tool. All feedback is welcome. Please post issues directly to this GitHub. 6 | 7 | ## Getting Started 8 | 9 | React Blue is a client-side application available via the browser and a downloadable GUI. 10 | 11 | **Browser**
    12 | http://reactblue.io/app 13 | 14 | **Desktop GUI (alpha)**
    15 | Download (Mac, Windows, Linux) 16 | 17 | 1. Extract file 18 | 2. Run application 19 | How to Use 20 | When starting, an ‘App’ component will always pre-populate in order to serve as your prototype’s root node. 21 | 22 | Main Display visually renders the hierarchical component tree. Clicking a node on the tree makes it the ‘Current Component’ and subject for edits. Left Panel functions as the control center. It contains three separate tabs: Current Component & Current File-Structure, Templates and SubTrees. 23 | 24 | ## Usage 25 | 26 | Control Center _left panel_ 27 | 28 | 1. Current Component _inside of left panel, 1st Icon_ : 29 | 30 | - To ADD a new Component: input text below ‘Add Child’, check the Container checkbox (if applicable), and click the ‘+’ button. 31 | 32 | - To RENAME a Component: input text below ‘Current Component’ (ensure your desired component is already selected) and click outside the text field. 33 | 34 | - To EDIT a Component’s Container classification: check/uncheck the checkbox below ‘Current Component’ (ensure your desired component is already selected). 35 | 36 | - To DELETE a Component: click the ‘-’ button below ‘Current Component’ (ensure your desired component is already selected). 37 | 38 | - To VIEW/UNVIEW a list of all Components and Containers: click the ‘Toggle File Tree’ button. 39 | 40 | - Parent components have the option of toggling the 'SubTree' checkbox; _HIGHLY SUGGESTED_ for heavily nested or complex relationships between parent/child. Utilize this feature if your tree has over 70+ Components. 41 | 42 | - SUMMARY: Add, edit and/or delete components within the top half. Create a name for your component, this will be the _Actual_ name of the component so be mindful of your naming conventions. You have the option to choose a template before you create the Component/Container (which is a toggle, True is Container and False is Component). You can always change these presets later on, so don't worry about choosing the wrong option. 43 | 44 | 2. Current File-Structure: - Click the toggle to view the components under _Container_ or _Component_. You can also click on a component to make it the _Current Component_ display. 45 | 46 | Templates _inside of left panel click, 2nd Icon_ 47 | 48 | - Create and edit file templates. Templates will default to Class Syntax, you have the option to choose the default Hook Syntax, and or create your own template. Assign any/all templates to specific components in the Current Component. 49 | SubTree _inside of left panel click, 3rd Icon_ 50 | 51 | ## Export 52 | 53 | When you are finished creating your file structure generate a zip package of your pre-configured codebase by clicking the right ‘Export’ button. 54 | 55 | ## Shortcuts and Views 56 | 57 | Keyboard shortcuts right at your fingertips to perform undo (ctrl+z) and redo (ctrl+shift+z) actions and toggle between horizontal and vertical views of the component tree. 58 | 59 | Our tool is your playground. 60 | 61 | --- 62 | 63 | **Disclaimer**
    64 | Currently, client-side caching is available for both browser and downloaded version of the application. If a page does not load within the browser, clear the local storage cache. 65 | 66 | **License**
    67 | This project is under the MIT License. 68 | 69 | **Authors**
    70 | Darren Zhu: https://github.com/joodongri
    71 | Kendall Lu: https://github.com/kendall-lu
    72 | Krystal Chen: https://github.com/kcrystalchen
    73 | Randy Reyes: https://github.com/rqreyes 74 | 75 | **Acknowledgements**
    76 | Huge thank you to Victoria Adnet (https://www.linkedin.com/in/victoria-lellis/) for her input, advice and mentorship. 77 | 78 | React Blue v1.0 79 | -------------------------------------------------------------------------------- /__tests__/reducer.test.js: -------------------------------------------------------------------------------- 1 | import mainReducer from '../client/reducers/mainReducer'; 2 | import { 3 | initialStateMock, 4 | stateWithChildMock, 5 | stateWithChildrenMock, 6 | initialHistory, 7 | currentHistory, 8 | nextHistory 9 | } from '../__mock__/stateMocks'; 10 | import * as types from '../client/constants/actionTypes'; 11 | window.alert = jest.fn(); 12 | 13 | describe('validation of main reducer', () => { 14 | it('should return the initial state when the action is not found', () => { 15 | expect(mainReducer(initialStateMock, { 16 | type: "NO_SUCH_ACTION" 17 | })).toEqual(initialStateMock); 18 | }); 19 | }); 20 | 21 | describe('renameComponent', () => { 22 | const renameComponentState = mainReducer(initialStateMock, { 23 | type: types.RENAME_COMPONENT, 24 | payload: { 25 | inputName: 'Test' 26 | } 27 | }) 28 | it('should return the state with new current component name "Test"', () => { 29 | expect(renameComponentState.currentComponent.name).toEqual('Test'); 30 | }); 31 | it('should mutate data tree with new input name', () => { 32 | expect(renameComponentState.data.name).toEqual('Test'); 33 | }); 34 | }); 35 | 36 | describe('changeType', () => { 37 | const changeTypeState = mainReducer(initialStateMock, { 38 | type: types.CHANGE_TYPE, 39 | payload: { 40 | isContainer: false 41 | } 42 | }) 43 | it('should return the state with current component is not container', () => { 44 | expect(changeTypeState.currentComponent.isContainer).toEqual(false); 45 | }); 46 | it('should mutate data tree with container type', () => { 47 | expect(changeTypeState.data.isContainer).toEqual(false); 48 | }); 49 | }); 50 | 51 | describe('deleteComponent', () => { 52 | const deleteComponentState = mainReducer(stateWithChildrenMock, { 53 | type: types.DELETE_COMPONENT 54 | }); 55 | it('should return state with data that has only one child ', () => { 56 | expect(deleteComponentState.data.children).toHaveLength(1); 57 | }); 58 | it('should delete the correct child component and reset the index of children array', () => { 59 | expect(deleteComponentState.data.children[0].name).toEqual('childComponent1'); 60 | }); 61 | it('should have current component that assigned by the parent of the deleted component', () => { 62 | expect(deleteComponentState.currentComponent.componentId).toEqual(0); 63 | }); 64 | const deleteRootComponentState = mainReducer(initialStateMock, { 65 | type: types.DELETE_COMPONENT 66 | }) 67 | it('should not be able to delete root component', () => { 68 | window.alert.mockClear(); 69 | expect(deleteRootComponentState.currentComponent).toEqual(initialStateMock.currentComponent); 70 | }); 71 | }); 72 | 73 | describe('setCurrentComponent', () => { 74 | const setCurrentComponentState = mainReducer(stateWithChildrenMock, { 75 | type: types.SET_CURRENT_COMPONENT, 76 | payload: { 77 | currentComponent: { 78 | name: "CurrentComponentTest", 79 | depth: 1, 80 | id: 3, 81 | componentId: 2, 82 | parent: {}, 83 | isContainer: false, 84 | children: [] 85 | } 86 | } 87 | }); 88 | it('should return state with current component named "CurrentComponentTest"', () => { 89 | expect(setCurrentComponentState.currentComponent.name).toEqual("CurrentComponentTest"); 90 | }); 91 | it('should have not mutated original data', () => { 92 | expect(setCurrentComponentState.data).toEqual(stateWithChildrenMock.data); 93 | }); 94 | }); 95 | 96 | describe('setTransAndHistory', () => { 97 | const setTransAndHistoryState = mainReducer(initialStateMock, { 98 | type: types.SET_TRANS_AND_HISTORY, 99 | payload: { 100 | translate: {x: 100, y: 100}, 101 | history: currentHistory 102 | } 103 | }); 104 | it('should set the translate of initial state to x:100 and y:100', () => { 105 | expect(setTransAndHistoryState.translate.x).toBe(100); 106 | expect(setTransAndHistoryState.translate.y).toBe(100); 107 | }); 108 | it('should set the history of initial state to current history', () => { 109 | expect(setTransAndHistoryState.history).toEqual(currentHistory); 110 | }) 111 | }); 112 | 113 | describe('undo', () => { 114 | const undoState = mainReducer(stateWithChildrenMock, { 115 | type: types.UN_DO 116 | }); 117 | it('should set the state back to the previous state', () => { 118 | expect(undoState).toEqual(stateWithChildMock); 119 | }); 120 | 121 | }); -------------------------------------------------------------------------------- /client/assets/styles/partials/_panel-container.scss: -------------------------------------------------------------------------------- 1 | // panel nav icons 2 | #panel-nav-icons { 3 | display: flex; 4 | 5 | > a { 6 | &:not(:last-child) { 7 | margin-right: 20px; 8 | } 9 | } 10 | } 11 | 12 | .divider-panel { 13 | flex: 0 0 auto; 14 | width: 90%; 15 | height: 1px; 16 | background: $prime-color-1; 17 | margin: 20px auto; 18 | } 19 | 20 | // panel container 21 | #panel-container { 22 | display: flex; 23 | flex-direction: column; 24 | width: 25%; 25 | background: rgba(248, 248, 255, 0.5); 26 | border-radius: 10px; 27 | box-shadow: 0 0 15px; 28 | padding: 20px; 29 | margin: 20px; 30 | 31 | button { 32 | background: transparent; 33 | 34 | &#toggle-file-tree { 35 | background: $prime-color-1; 36 | } 37 | } 38 | } 39 | 40 | // current component 41 | #component-detail { 42 | display: flex; 43 | flex-direction: column; 44 | overflow: auto; 45 | 46 | #component-form { 47 | margin-bottom: 20px; 48 | } 49 | 50 | #component-form-top, 51 | #component-form-bottom { 52 | display: flex; 53 | align-items: center; 54 | 55 | > *:not(:last-child) { 56 | margin-right: 20px; 57 | } 58 | } 59 | 60 | #component-form-top { 61 | margin-bottom: 10px; 62 | } 63 | 64 | input[type='text'] { 65 | flex: 1; 66 | width: 100%; 67 | max-width: 219px; 68 | } 69 | 70 | #component-name-input { 71 | border: 1px solid $prime-color-1; 72 | } 73 | 74 | .is-container { 75 | display: flex; 76 | align-items: center; 77 | } 78 | 79 | #code-editor-container { 80 | display: none; 81 | } 82 | } 83 | 84 | // children list 85 | form#children-list-form { 86 | display: flex; 87 | align-items: center; 88 | margin-bottom: 20px; 89 | 90 | > *:not(:last-child) { 91 | margin-right: 20px; 92 | } 93 | } 94 | 95 | #children-list { 96 | height: 100%; 97 | overflow: auto; 98 | 99 | > * { 100 | margin: 0 auto 10px; 101 | } 102 | 103 | form, 104 | .each-child { 105 | display: flex; 106 | align-items: center; 107 | 108 | > *:not(:last-child) { 109 | margin-right: 20px; 110 | } 111 | } 112 | 113 | .each-child-container { 114 | position: relative; 115 | 116 | &::after { 117 | content: ''; 118 | display: block; 119 | width: 90%; 120 | height: 1px; 121 | background: $prime-color-1; 122 | margin: 20px auto; 123 | } 124 | 125 | &:last-child { 126 | &::after { 127 | display: none; 128 | } 129 | } 130 | } 131 | 132 | .each-child { 133 | margin-bottom: 10px; 134 | } 135 | } 136 | 137 | // file tree 138 | #toggle-file-tree { 139 | flex: 0 0 auto; 140 | width: 120px; 141 | height: 38px; 142 | color: #fff; 143 | border-radius: 0.25rem; 144 | margin: auto; 145 | } 146 | 147 | #file-tree { 148 | flex: 0 0 auto; 149 | max-height: 120px; 150 | overflow: auto; 151 | margin-top: 20px; 152 | 153 | &.hidden { 154 | display: none; 155 | } 156 | 157 | > ul { 158 | display: flex; 159 | justify-content: space-around; 160 | } 161 | #current-component-file-tree { 162 | color: $prime-color-1; 163 | font-weight: bold; 164 | } 165 | #container-files, 166 | #component-files { 167 | > ul { 168 | list-style-type: square; 169 | padding-left: 15px; 170 | 171 | > li { 172 | cursor: pointer; 173 | } 174 | } 175 | } 176 | } 177 | 178 | // templates 179 | #code-editor-container { 180 | display: flex; 181 | flex-direction: column; 182 | height: 100%; 183 | 184 | .template-container { 185 | height: 100%; 186 | overflow: auto; 187 | } 188 | 189 | .template-item { 190 | display: flex; 191 | flex-wrap: wrap; 192 | margin-bottom: 10px; 193 | overflow: auto; 194 | 195 | button { 196 | margin: 0 0 10px 20px; 197 | } 198 | } 199 | 200 | input[type='text'] { 201 | width: 100%; 202 | max-width: 219px; 203 | } 204 | 205 | .change-name { 206 | flex: 1 0 auto; 207 | margin-bottom: 10px; 208 | } 209 | 210 | form { 211 | display: flex; 212 | align-items: center; 213 | 214 | > *:not(:last-child) { 215 | margin-right: 20px; 216 | } 217 | } 218 | 219 | .is-hook-container { 220 | display: flex; 221 | align-items: center; 222 | } 223 | 224 | #reset-templates { 225 | display: block; 226 | color: #fff; 227 | background: $prime-color-1; 228 | border-radius: 0.25rem; 229 | padding: 10px 20px; 230 | margin: auto; 231 | transition: background-color 0.15s ease-in-out; 232 | 233 | &:hover { 234 | background: #007bff; 235 | } 236 | } 237 | } 238 | 239 | // subtrees 240 | #subtree-container { 241 | ul { 242 | list-style-type: square; 243 | padding-left: 15px; 244 | } 245 | 246 | li { 247 | width: 200px; 248 | } 249 | 250 | .delete-subtree { 251 | float: right; 252 | } 253 | } 254 | -------------------------------------------------------------------------------- /client/containers/TopNavContainer.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { connect } from 'react-redux'; 3 | import { bindActionCreators } from 'redux'; 4 | import { 5 | undo, 6 | redo, 7 | changeDisplayHorizontalToVertical, 8 | resetEntireTree 9 | } from '../actions/actions'; 10 | import Navbar from 'react-bootstrap/Navbar'; 11 | import Nav from 'react-bootstrap/Nav'; 12 | import NavDropdown from 'react-bootstrap/NavDropdown'; 13 | import logo from '../assets/images/logo.png'; 14 | import exportZipFront from '../templates-exports/frontEndFiles.js'; 15 | import exportZipFull from '../templates-exports/fullStackFiles.js'; 16 | 17 | const mapStateToProps = store => ({ 18 | data: store.main.data, 19 | history: store.main.history, 20 | nameAndCodeLinkedToComponentId: store.main.nameAndCodeLinkedToComponentId 21 | }); 22 | 23 | const mapDispatchToProps = dispatch => 24 | bindActionCreators( 25 | { 26 | undo, 27 | redo, 28 | changeDisplayHorizontalToVertical, 29 | resetEntireTree 30 | }, 31 | dispatch 32 | ); 33 | 34 | const TopNavContainer = ({ 35 | data, 36 | nameAndCodeLinkedToComponentId, 37 | history, 38 | undo, 39 | redo, 40 | changeDisplayHorizontalToVertical, 41 | resetEntireTree 42 | }) => { 43 | let undoDisabled = () => false; 44 | let redoDisabled = () => false; 45 | if (history) { 46 | undoDisabled = () => { 47 | return history.prev ? false : true; 48 | }; 49 | redoDisabled = () => { 50 | return history.next ? false : true; 51 | }; 52 | } 53 | return ( 54 | 55 |
    56 | react blue logo 57 |
    58 | React Blue 59 | 60 | 61 | 119 | 141 | 142 |
    143 | ); 144 | }; 145 | 146 | export default connect( 147 | mapStateToProps, 148 | mapDispatchToProps 149 | )(TopNavContainer); 150 | -------------------------------------------------------------------------------- /client/components/TemplatingArea.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | 3 | import clone from 'clone'; 4 | import { 5 | InitialHookSyntax, 6 | InitialClassSyntax 7 | } from '../templates-code/templates'; 8 | import CreateCodeEditor from './CreateCodeEditor.jsx'; 9 | /** 10 | * Constructor fn which instantiates a new instance of either a hook/class syntax (imported from templates-code/templates) 11 | */ 12 | function CustomTemplate(name, isHook) { 13 | (this.name = name 14 | ? name 15 | : isHook 16 | ? 'DEFAULT_HOOK_TEMPLATE' 17 | : 'DEFAULT_CLASS_TEMPLATE'), 18 | (this.code = isHook 19 | ? new InitialHookSyntax(name).code 20 | : new InitialClassSyntax(name).code); 21 | } 22 | 23 | /** 24 | * base templates for the component to utilize as initial Local state 25 | */ 26 | const initialHookSyntax = new InitialHookSyntax(); 27 | const initialClassSyntax = new InitialClassSyntax(); 28 | 29 | const TemplatingArea = ({ useTemplates }) => { 30 | const [isInitialSyntax, setIsInitialSyntax] = useState([ 31 | initialClassSyntax, 32 | initialHookSyntax 33 | ]); 34 | useEffect(() => { 35 | let data = getItemFromLocalStorage(); 36 | setItemForLocalStorage(data); 37 | }, []); 38 | /** 39 | * Sets 'storage' prop for local storage, sends all templates to redux store to allow components to use them 40 | */ 41 | const setItemForLocalStorage = data => { 42 | data = 43 | data !== null && data.length > 0 44 | ? data 45 | : [initialClassSyntax, initialHookSyntax]; 46 | localStorage.setObj('storage', data); 47 | useTemplates(data); 48 | }; 49 | /** 50 | * grabbing items from local storage and setting local state as well as sending to redux store 51 | */ 52 | const getItemFromLocalStorage = reset => { 53 | const resetData = [initialClassSyntax, initialHookSyntax]; 54 | if (reset !== 'reset') { 55 | const data = localStorage.getObj('storage'); 56 | if (data) { 57 | setIsInitialSyntax(data); 58 | useTemplates(data); 59 | } else { 60 | setIsInitialSyntax(resetData); 61 | useTemplates(resetData); 62 | } 63 | return data; 64 | } else { 65 | setIsInitialSyntax(resetData); 66 | setItemForLocalStorage(resetData); 67 | useTemplates(resetData); 68 | } 69 | }; 70 | /** 71 | * deleting object from local state array, and updating local storage by invoking setIsInitialSyntax fn(), setting local state, and sending to redux store 72 | */ 73 | const deleteTemplate = index => { 74 | let cloneOfIsInitialSyntax = clone(isInitialSyntax); 75 | cloneOfIsInitialSyntax.splice(index, 1); 76 | setIsInitialSyntax(cloneOfIsInitialSyntax); 77 | setItemForLocalStorage(cloneOfIsInitialSyntax); 78 | useTemplates(cloneOfIsInitialSyntax); 79 | }; 80 | /** 81 | * Any changes to template code will update local state 82 | */ 83 | const updateCode = (newCode, index, name) => { 84 | const cloneOfInitialSyntax = clone(isInitialSyntax); 85 | for (let i = 0; i < cloneOfInitialSyntax.length; i += 1) { 86 | if (i === index) { 87 | if (!name) { 88 | cloneOfInitialSyntax[i].code = newCode; 89 | } else { 90 | cloneOfInitialSyntax[i].name = name; 91 | } 92 | break; 93 | } 94 | } 95 | setIsInitialSyntax(cloneOfInitialSyntax); 96 | setItemForLocalStorage(cloneOfInitialSyntax); 97 | return; 98 | }; 99 | 100 | return ( 101 |
    102 |

    Add Template

    103 |
    { 105 | e.preventDefault(); 106 | const templateName = document.getElementById('add-template-name'); 107 | const isClass = document.getElementById('is-hook'); 108 | let nameVal; 109 | if (templateName.value === '') { 110 | nameVal = undefined; 111 | } else { 112 | nameVal = templateName.value; 113 | } 114 | const newCustomTemplate = new CustomTemplate( 115 | nameVal, 116 | isClass.checked 117 | ); 118 | const clonedInitial = clone(isInitialSyntax); 119 | clonedInitial.push(newCustomTemplate); 120 | setIsInitialSyntax(clonedInitial); 121 | setItemForLocalStorage(clonedInitial); 122 | templateName.value = ''; 123 | isClass.checked = !isClass.checked 124 | ? isClass.checked 125 | : !isClass.checked; 126 | }} 127 | > 128 | 133 |
    134 | 135 | 136 |
    137 | 140 |
    141 |
    142 |

    Template List

    143 |
    144 | {isInitialSyntax.map((syntaxObject, index) => { 145 | return ( 146 | 153 | ); 154 | })} 155 |
    156 |
    157 | 165 |
    166 | ); 167 | }; 168 | 169 | export default TemplatingArea; 170 | -------------------------------------------------------------------------------- /__tests__/enzyme.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { configure, shallow, mount } from "enzyme"; 3 | import Adapter from "enzyme-adapter-react-16"; 4 | import EachChild from "../client/components/EachChild.jsx"; 5 | import ComponentDetail from "../client/components/ComponentDetail.jsx"; 6 | import ChildrenList from "../client/components/ChildrenList.jsx"; 7 | import { 8 | initialStateMock 9 | } from '../__mock__/stateMocks'; 10 | import { cleanup } from "@testing-library/react"; // testing helpers 11 | 12 | configure({ adapter: new Adapter() }); 13 | 14 | describe("React Blue unit tests", () => { 15 | describe("EachChild.jsx", () => { 16 | let wrapper, input; 17 | const renameMock = jest.fn(); 18 | const changeMock = jest.fn(); 19 | const deleteMock = jest.fn(); 20 | 21 | let props = { 22 | name: "test", 23 | childId: 0, 24 | isContainer: true, 25 | renameChild: renameMock, 26 | changeType: changeMock, 27 | deleteChild: deleteMock 28 | }; 29 | 30 | beforeAll(() => { 31 | wrapper = shallow(); 32 | input = wrapper.find("input"); 33 | }); 34 | 35 | it("Expect type to be text and defaultValue to be test", () => { 36 | expect(input.at(0).props().type).toBe("text"); 37 | expect(input.at(0).props().defaultValue).toBe("test"); 38 | }); 39 | it("Expect checked to be true and type to be checkbox", () => { 40 | expect(input.at(1).props().checked).toBe(true); 41 | expect(input.at(1).props().type).toBe("checkbox"); 42 | }); 43 | }); 44 | describe("ComponentDetail.jsx", () => { 45 | let wrapper, input; 46 | const renameMock = jest.fn(); 47 | const changeMock = jest.fn(); 48 | const deleteMock = jest.fn(); 49 | const setTemplatesMock = jest.fn(); 50 | const checkID_ClearAndSetTimeout = jest.fn(); 51 | const showSubTree = jest.fn(); 52 | const addOrDeleteNewSubTree = jest.fn(); 53 | const mockComponent = { 54 | name: "test", 55 | isContainer: true, 56 | depth: 0 57 | }; 58 | let props = { 59 | renameComponent: renameMock, 60 | changeType: changeMock, 61 | deleteComponent: deleteMock, 62 | currentComponent: mockComponent, 63 | templates: "templateMock1", 64 | setTemplatesForComponent: setTemplatesMock, 65 | nameAndCodeLinkedToComponentId: { "0": "templateMock1" }, 66 | recentTimeoutId: 0, 67 | setTimeoutId: 1, 68 | checkID_ClearAndSetTimeout: checkID_ClearAndSetTimeout, 69 | showSubTree: showSubTree, 70 | currentlyDisplayedSubTreeId: 0, 71 | addOrDeleteNewSubTree: addOrDeleteNewSubTree, 72 | state: initialStateMock, 73 | displaySubTreeDropDown: { "0": "App" } 74 | }; 75 | beforeAll(() => { 76 | wrapper = shallow(); 77 | input = wrapper.find("input"); 78 | }); 79 | it("Should show text of Current Component", () => { 80 | expect( 81 | wrapper.containsMatchingElement(

    Current Component

    ) 82 | ).toBeTruthy(); 83 | 84 | }); 85 | it("Should have input ONE be type of text and defaultValue to test", () => { 86 | expect(input.at(0).props().type).toBe("text"); 87 | expect(input.at(0).props().defaultValue).toBe("test"); 88 | }); 89 | it("Should have field TWO to have type of checkbox and checked to be true", () => { 90 | expect(input.at(1).props().type).toBe("checkbox"); 91 | expect(input.at(1).props().checked).toBe(true); 92 | }); 93 | it("Should have text of Container ", () => { 94 | expect( 95 | wrapper.containsMatchingElement() 96 | ).toBeTruthy(); 97 | }); 98 | it("Should invoke delete function onclick", () => { 99 | wrapper.find("button").simulate("click"); 100 | expect(deleteMock).toHaveBeenCalled; 101 | }); 102 | }); 103 | 104 | }); 105 | // describe("Integration testing", () => { 106 | // let childrenList, input; 107 | // const addMock = function () { 108 | // return "added"; 109 | // }; 110 | // const renameMock = jest.fn(); 111 | // const changeMock = jest.fn(); 112 | // const deleteMock = jest.fn(); 113 | // const setTemplatesMock = jest.fn(); 114 | // const checkID_ClearAndSetTimeoutMock = jest.fn(); 115 | // const showSubTreeMock = jest.fn(); 116 | // const currentComponentMock = { 117 | // name: "App", 118 | // depth: 0, 119 | // id: 0, 120 | // componentId: 0, 121 | // isContainer: true, 122 | // children: [{ name: 'children', componentId: '1', isContainer: false }] 123 | // } 124 | 125 | // let childrenListProps = { 126 | // addChild: addMock, 127 | // renameChild: renameMock, 128 | // changeChildType: changeMock, 129 | // deleteChild: deleteMock, 130 | // currentComponent: currentComponentMock, 131 | // templates: [{ name: "templateMock1", code: 'test code' }], 132 | // setTemplatesForComponent: setTemplatesMock, 133 | // nameAndCodeLinkedToComponentId: { "0": "templateMock1" }, 134 | // state: initialStateMock, 135 | // recentTimeoutId: 0, 136 | // setTimeoutId: 1, 137 | // checkID_ClearAndSetTimeout: checkID_ClearAndSetTimeoutMock, 138 | // showSubTree: showSubTreeMock, 139 | // currentlyDisplayedSubTreeId: 0, 140 | // }; 141 | 142 | // beforeAll(() => { 143 | // childrenList = mount(); 144 | // input = childrenList.find('input'); 145 | // }); 146 | // afterAll(() => cleanup); 147 | // describe("Adding nodes display correct length of childrenList", () => { 148 | // expect(childrenList.exists()).to.be(true); 149 | // // .to.be.equal('each-child-container'); 150 | // // childrenList.find("button").simulate("click"); 151 | // // expect(childrenList.find('.each-child-container')).toHaveLength(1); 152 | // }); 153 | // describe("Showing correct number of children on d3 tree", () => { }); 154 | // }); 155 | -------------------------------------------------------------------------------- /client/actions/actions.js: -------------------------------------------------------------------------------- 1 | import * as types from '../constants/actionTypes'; 2 | 3 | /******************************* actions for side bar ************************************/ 4 | export const renameComponent = event => dispatch => { 5 | let inputName = event.target.value; 6 | inputName = inputName.replace(/(\w)(\w*)/g, (g0, g1, g2) => { 7 | return g1.toUpperCase() + g2.toLowerCase(); 8 | }); 9 | inputName = inputName.replace(/\s/g, ''); 10 | 11 | dispatch({ 12 | type: types.RENAME_COMPONENT, 13 | payload: { 14 | inputName 15 | } 16 | }); 17 | }; 18 | 19 | export const changeType = event => dispatch => { 20 | const isContainer = event.target.checked; 21 | dispatch({ 22 | type: types.CHANGE_TYPE, 23 | payload: { 24 | isContainer 25 | } 26 | }); 27 | }; 28 | 29 | export const deleteComponent = () => dispatch => { 30 | dispatch({ 31 | type: types.DELETE_COMPONENT, 32 | payload: null 33 | }); 34 | }; 35 | 36 | /******************************* actions for main container ************************************/ 37 | 38 | 39 | export const setCurrentComponent = (currentComponent) => dispatch => { 40 | dispatch({ 41 | type: types.SET_CURRENT_COMPONENT, 42 | payload: { 43 | currentComponent 44 | } 45 | }) 46 | }; 47 | 48 | export const setTransAndHistory = (translate, history) => dispatch => { 49 | dispatch({ 50 | type: types.SET_TRANS_AND_HISTORY, 51 | payload: { 52 | translate, 53 | history 54 | } 55 | }); 56 | }; 57 | 58 | export const undo = () => dispatch => { 59 | dispatch({ 60 | type: types.UN_DO, 61 | payload: null 62 | }); 63 | }; 64 | 65 | export const redo = () => dispatch => { 66 | dispatch({ 67 | type: types.RE_DO, 68 | payload: null 69 | }); 70 | }; 71 | 72 | /*********************** actions for current component children list ****************************/ 73 | export const renameChild = (event, childId) => dispatch => { 74 | const inputName = event.target.value.replace(/\s/g, ''); 75 | dispatch({ 76 | type: types.RENAME_CHILD, 77 | payload: { 78 | inputName, 79 | childId 80 | } 81 | }); 82 | }; 83 | 84 | export const changeChildType = (event, childId) => dispatch => { 85 | const isChecked = event.target.checked; 86 | dispatch({ 87 | type: types.CHANGE_CHILD_TYPE, 88 | payload: { 89 | isChecked, 90 | childId 91 | } 92 | }); 93 | }; 94 | 95 | export const addChild = event => dispatch => { 96 | event.preventDefault(); 97 | let name = event.target.childName.value; 98 | name = name.replace(/(\w)(\w*)/g, (g0, g1, g2) => { 99 | return g1.toUpperCase() + g2.toLowerCase(); 100 | }); 101 | name = name.replace(/\s/g, ''); 102 | const isContainer = event.target.checkbox.checked; 103 | 104 | // reset the input fields 105 | document.getElementById('add-child-name').value = ''; 106 | document.getElementById('add-child-container-checkbox').checked = false; 107 | 108 | dispatch({ 109 | type: types.ADD_CHILD, 110 | payload: { 111 | name, 112 | isContainer 113 | } 114 | }); 115 | }; 116 | 117 | export const deleteChild = childId => dispatch => { 118 | dispatch({ 119 | type: types.DELETE_CHILD, 120 | payload: { 121 | childId 122 | } 123 | }); 124 | }; 125 | 126 | // actions for taking the templates and sending it to the store 127 | export const useTemplates = templates => dispatch => { 128 | dispatch({ 129 | type: types.USE_TEMPLATES, 130 | payload: { templates } 131 | }); 132 | }; 133 | 134 | export const setTemplatesForComponent = ( 135 | currentComponent, 136 | template 137 | ) => dispatch => { 138 | dispatch({ 139 | type: types.SET_TEMPLATES_FOR_COMPONENT, 140 | payload: { currentComponent, template } 141 | }); 142 | }; 143 | export const changeDisplayHorizontalToVertical = orientation => dispatch => { 144 | dispatch({ 145 | type: types.CHANGE_DISPLAY_HORIZONTAL_OR_VERTICAL, 146 | payload: orientation 147 | }); 148 | }; 149 | // export const setZoom = (x, y) => dispatch => { 150 | // dispatch({ 151 | // type: types.ZOOM_BY_CHANGING_X_AND_Y, 152 | // payload: { x, y } 153 | // }); 154 | // }; 155 | export const updateStateWithLocalStorage = ( 156 | data, 157 | currentComponent, 158 | nameAndCodeLinkedToComponentId, 159 | lastId, 160 | history, 161 | displaySubTreeDropDown 162 | ) => dispatch => { 163 | dispatch({ 164 | type: types.UPDATE_STATE_WITH_LOCAL_STORAGE, 165 | payload: { data, currentComponent, nameAndCodeLinkedToComponentId, lastId, history, displaySubTreeDropDown } 166 | }); 167 | }; 168 | 169 | export const resetEntireTree = () => dispatch => { 170 | dispatch({ 171 | type: types.RESET_ENTIRE_TREE, 172 | payload: null 173 | }); 174 | }; 175 | 176 | // toggle file tree 177 | export const showFileTree = () => dispatch => { 178 | dispatch({ 179 | type: types.SHOW_FILE_TREE 180 | }); 181 | }; 182 | // update set timeout id 183 | export const setTimeoutId = (id) => dispatch => { 184 | dispatch({ 185 | type: types.SET_TIMEOUT_ID, 186 | payload: id 187 | }) 188 | } 189 | 190 | //subtree action creators 191 | export const showSubTree = (componentId) => dispatch => { 192 | dispatch({ 193 | type: types.SHOW_SUBTREE, 194 | payload: componentId 195 | }) 196 | } 197 | 198 | export const addOrDeleteNewSubTree = (event, componentId, name) => dispatch => { 199 | const isChecked = event.target.checked; 200 | dispatch({ 201 | type: types.ADD_OR_DELETE_NEW_SUB_TREE, 202 | payload: { isChecked, componentId, name } 203 | }) 204 | } 205 | export const deleteSubTreeDropdownItem = (componentId) =>dispatch =>{ 206 | dispatch({ 207 | type: types.DELETE_SUBTREE_DROPDOWN_ITEM, 208 | payload: componentId 209 | }) 210 | } -------------------------------------------------------------------------------- /client/assets/styles/normalize.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ 2 | 3 | /* Document 4 | ========================================================================== */ 5 | 6 | /** 7 | * 1. Correct the line height in all browsers. 8 | * 2. Prevent adjustments of font size after orientation changes in iOS. 9 | */ 10 | 11 | html { 12 | line-height: 1.15; /* 1 */ 13 | -webkit-text-size-adjust: 100%; /* 2 */ 14 | } 15 | 16 | /* Sections 17 | ========================================================================== */ 18 | 19 | /** 20 | * Remove the margin in all browsers. 21 | */ 22 | 23 | body { 24 | margin: 0; 25 | } 26 | 27 | /** 28 | * Render the `main` element consistently in IE. 29 | */ 30 | 31 | main { 32 | display: block; 33 | } 34 | 35 | /** 36 | * Correct the font size and margin on `h1` elements within `section` and 37 | * `article` contexts in Chrome, Firefox, and Safari. 38 | */ 39 | 40 | h1 { 41 | font-size: 2em; 42 | margin: 0.67em 0; 43 | } 44 | 45 | /* Grouping content 46 | ========================================================================== */ 47 | 48 | /** 49 | * 1. Add the correct box sizing in Firefox. 50 | * 2. Show the overflow in Edge and IE. 51 | */ 52 | 53 | hr { 54 | box-sizing: content-box; /* 1 */ 55 | height: 0; /* 1 */ 56 | overflow: visible; /* 2 */ 57 | } 58 | 59 | /** 60 | * 1. Correct the inheritance and scaling of font size in all browsers. 61 | * 2. Correct the odd `em` font sizing in all browsers. 62 | */ 63 | 64 | pre { 65 | font-family: monospace, monospace; /* 1 */ 66 | font-size: 1em; /* 2 */ 67 | } 68 | 69 | /* Text-level semantics 70 | ========================================================================== */ 71 | 72 | /** 73 | * Remove the gray background on active links in IE 10. 74 | */ 75 | 76 | a { 77 | background-color: transparent; 78 | } 79 | 80 | /** 81 | * 1. Remove the bottom border in Chrome 57- 82 | * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. 83 | */ 84 | 85 | abbr[title] { 86 | border-bottom: none; /* 1 */ 87 | text-decoration: underline; /* 2 */ 88 | text-decoration: underline dotted; /* 2 */ 89 | } 90 | 91 | /** 92 | * Add the correct font weight in Chrome, Edge, and Safari. 93 | */ 94 | 95 | b, 96 | strong { 97 | font-weight: bolder; 98 | } 99 | 100 | /** 101 | * 1. Correct the inheritance and scaling of font size in all browsers. 102 | * 2. Correct the odd `em` font sizing in all browsers. 103 | */ 104 | 105 | code, 106 | kbd, 107 | samp { 108 | font-family: monospace, monospace; /* 1 */ 109 | font-size: 1em; /* 2 */ 110 | } 111 | 112 | /** 113 | * Add the correct font size in all browsers. 114 | */ 115 | 116 | small { 117 | font-size: 80%; 118 | } 119 | 120 | /** 121 | * Prevent `sub` and `sup` elements from affecting the line height in 122 | * all browsers. 123 | */ 124 | 125 | sub, 126 | sup { 127 | font-size: 75%; 128 | line-height: 0; 129 | position: relative; 130 | vertical-align: baseline; 131 | } 132 | 133 | sub { 134 | bottom: -0.25em; 135 | } 136 | 137 | sup { 138 | top: -0.5em; 139 | } 140 | 141 | /* Embedded content 142 | ========================================================================== */ 143 | 144 | /** 145 | * Remove the border on images inside links in IE 10. 146 | */ 147 | 148 | img { 149 | border-style: none; 150 | } 151 | 152 | /* Forms 153 | ========================================================================== */ 154 | 155 | /** 156 | * 1. Change the font styles in all browsers. 157 | * 2. Remove the margin in Firefox and Safari. 158 | */ 159 | 160 | button, 161 | input, 162 | optgroup, 163 | select, 164 | textarea { 165 | font-family: inherit; /* 1 */ 166 | font-size: 100%; /* 1 */ 167 | line-height: 1.15; /* 1 */ 168 | margin: 0; /* 2 */ 169 | } 170 | 171 | /** 172 | * Show the overflow in IE. 173 | * 1. Show the overflow in Edge. 174 | */ 175 | 176 | button, 177 | input { /* 1 */ 178 | overflow: visible; 179 | } 180 | 181 | /** 182 | * Remove the inheritance of text transform in Edge, Firefox, and IE. 183 | * 1. Remove the inheritance of text transform in Firefox. 184 | */ 185 | 186 | button, 187 | select { /* 1 */ 188 | text-transform: none; 189 | } 190 | 191 | /** 192 | * Correct the inability to style clickable types in iOS and Safari. 193 | */ 194 | 195 | button, 196 | [type="button"], 197 | [type="reset"], 198 | [type="submit"] { 199 | -webkit-appearance: button; 200 | } 201 | 202 | /** 203 | * Remove the inner border and padding in Firefox. 204 | */ 205 | 206 | button::-moz-focus-inner, 207 | [type="button"]::-moz-focus-inner, 208 | [type="reset"]::-moz-focus-inner, 209 | [type="submit"]::-moz-focus-inner { 210 | border-style: none; 211 | padding: 0; 212 | } 213 | 214 | /** 215 | * Restore the focus styles unset by the previous rule. 216 | */ 217 | 218 | button:-moz-focusring, 219 | [type="button"]:-moz-focusring, 220 | [type="reset"]:-moz-focusring, 221 | [type="submit"]:-moz-focusring { 222 | outline: 1px dotted ButtonText; 223 | } 224 | 225 | /** 226 | * Correct the padding in Firefox. 227 | */ 228 | 229 | fieldset { 230 | padding: 0.35em 0.75em 0.625em; 231 | } 232 | 233 | /** 234 | * 1. Correct the text wrapping in Edge and IE. 235 | * 2. Correct the color inheritance from `fieldset` elements in IE. 236 | * 3. Remove the padding so developers are not caught out when they zero out 237 | * `fieldset` elements in all browsers. 238 | */ 239 | 240 | legend { 241 | box-sizing: border-box; /* 1 */ 242 | color: inherit; /* 2 */ 243 | display: table; /* 1 */ 244 | max-width: 100%; /* 1 */ 245 | padding: 0; /* 3 */ 246 | white-space: normal; /* 1 */ 247 | } 248 | 249 | /** 250 | * Add the correct vertical alignment in Chrome, Firefox, and Opera. 251 | */ 252 | 253 | progress { 254 | vertical-align: baseline; 255 | } 256 | 257 | /** 258 | * Remove the default vertical scrollbar in IE 10+. 259 | */ 260 | 261 | textarea { 262 | overflow: auto; 263 | } 264 | 265 | /** 266 | * 1. Add the correct box sizing in IE 10. 267 | * 2. Remove the padding in IE 10. 268 | */ 269 | 270 | [type="checkbox"], 271 | [type="radio"] { 272 | box-sizing: border-box; /* 1 */ 273 | padding: 0; /* 2 */ 274 | } 275 | 276 | /** 277 | * Correct the cursor style of increment and decrement buttons in Chrome. 278 | */ 279 | 280 | [type="number"]::-webkit-inner-spin-button, 281 | [type="number"]::-webkit-outer-spin-button { 282 | height: auto; 283 | } 284 | 285 | /** 286 | * 1. Correct the odd appearance in Chrome and Safari. 287 | * 2. Correct the outline style in Safari. 288 | */ 289 | 290 | [type="search"] { 291 | -webkit-appearance: textfield; /* 1 */ 292 | outline-offset: -2px; /* 2 */ 293 | } 294 | 295 | /** 296 | * Remove the inner padding in Chrome and Safari on macOS. 297 | */ 298 | 299 | [type="search"]::-webkit-search-decoration { 300 | -webkit-appearance: none; 301 | } 302 | 303 | /** 304 | * 1. Correct the inability to style clickable types in iOS and Safari. 305 | * 2. Change font properties to `inherit` in Safari. 306 | */ 307 | 308 | ::-webkit-file-upload-button { 309 | -webkit-appearance: button; /* 1 */ 310 | font: inherit; /* 2 */ 311 | } 312 | 313 | /* Interactive 314 | ========================================================================== */ 315 | 316 | /* 317 | * Add the correct display in Edge, IE 10+, and Firefox. 318 | */ 319 | 320 | details { 321 | display: block; 322 | } 323 | 324 | /* 325 | * Add the correct display in all browsers. 326 | */ 327 | 328 | summary { 329 | display: list-item; 330 | } 331 | 332 | /* Misc 333 | ========================================================================== */ 334 | 335 | /** 336 | * Add the correct display in IE 10+. 337 | */ 338 | 339 | template { 340 | display: none; 341 | } 342 | 343 | /** 344 | * Add the correct display in IE 10. 345 | */ 346 | 347 | [hidden] { 348 | display: none; 349 | } 350 | -------------------------------------------------------------------------------- /client/containers/PanelContainer.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useRef, useEffect } from 'react'; 2 | import { connect } from 'react-redux'; 3 | import { bindActionCreators } from 'redux'; 4 | import { BrowserRouter, Switch, Route } from 'react-router-dom'; 5 | import { 6 | renameChild, 7 | changeChildType, 8 | addChild, 9 | deleteChild, 10 | renameComponent, 11 | changeType, 12 | deleteComponent, 13 | setCurrentComponent, 14 | showFileTree, 15 | setTemplatesForComponent, 16 | useTemplates, 17 | setTimeoutId, 18 | showSubTree, 19 | addOrDeleteNewSubTree, 20 | deleteSubTreeDropdownItem 21 | } from '../actions/actions'; 22 | import ComponentDetail from '../components/ComponentDetail.jsx'; 23 | import TemplatingArea from '../components/TemplatingArea.jsx'; 24 | import FileTree from '../components/FileTree.jsx'; 25 | import PanelNavIcons from '../components/PanelNavIcons.jsx'; 26 | import ChildrenList from '../components/ChildrenList.jsx'; 27 | import SubTree from '../components/SubTree.jsx'; 28 | const mapStateToProps = store => ({ 29 | state: store.main, 30 | data: store.main.data, 31 | currentComponent: store.main.currentComponent, 32 | toggleFileTree: store.main.toggleFileTree, 33 | templates: store.main.templates, 34 | nameAndCodeLinkedToComponentId: store.main.nameAndCodeLinkedToComponentId, 35 | recentTimeoutId: store.main.recentTimeoutId, 36 | displaySubTreeDropDown: store.main.displaySubTreeDropDown, 37 | currentlyDisplayedSubTreeId: store.main.currentlyDisplayedSubTreeId, 38 | currentSubTreeDisplayToUser: store.main.currentSubTreeDisplayToUser 39 | }); 40 | 41 | const mapDispatchToProps = dispatch => 42 | bindActionCreators( 43 | { 44 | renameChild, 45 | changeChildType, 46 | addChild, 47 | deleteChild, 48 | renameComponent, 49 | changeType, 50 | deleteComponent, 51 | setCurrentComponent, 52 | showFileTree, 53 | setTemplatesForComponent, 54 | useTemplates, 55 | setTimeoutId, 56 | showSubTree, 57 | addOrDeleteNewSubTree, 58 | deleteSubTreeDropdownItem 59 | }, 60 | dispatch 61 | ); 62 | /** 63 | * getting rid of circular references inside of nodes (parent has a child and child has the same parent) 64 | */ 65 | 66 | const getCircularReplacer = () => { 67 | const seen = new WeakSet(); 68 | return (key, value) => { 69 | if (value instanceof Object && value !== null) { 70 | if (seen.has(value)) { 71 | return; 72 | } 73 | seen.add(value); 74 | } 75 | return value; 76 | }; 77 | }; 78 | /** 79 | * .setObj : JSON.stringify && getting rid of circular references 80 | * .getObj : JSON.parse 81 | */ 82 | 83 | Storage.prototype.setObj = function(key, obj) { 84 | return this.setItem(key, JSON.stringify(obj, getCircularReplacer())); 85 | }; 86 | Storage.prototype.getObj = function(key) { 87 | return JSON.parse(this.getItem(key)); 88 | }; 89 | /** 90 | * Delayed sending to local storage 91 | * any triggers of major updates(triggered event listeners) to state will reset the timer from state, and create a new timer (defaults to 10 seconds) 92 | */ 93 | 94 | function checkID_ClearAndSetTimeout(setTimeoutId, recentTimeoutId, state) { 95 | function setTimeoutAndSendToReducer(setTimeoutId, state) { 96 | const newSetTimeoutID = setTimeout(() => { 97 | localStorage.setObj( 98 | 'nameAndCodeLinkedToComponentId', 99 | state.nameAndCodeLinkedToComponentId 100 | ); 101 | localStorage.setObj('data', state.data); 102 | localStorage.setObj('currentComponent', state.currentComponent); 103 | localStorage.setObj( 104 | 'displaySubTreeDropDown', 105 | state.displaySubTreeDropDown 106 | ); 107 | state.history.next = null; 108 | state.history.prev = null; 109 | localStorage.setObj('history', state.history); 110 | localStorage.setObj('lastId', state.lastId); 111 | }, 10000); 112 | setTimeoutId(newSetTimeoutID); 113 | } 114 | if (!recentTimeoutId) { 115 | return setTimeoutAndSendToReducer(setTimeoutId, state); 116 | } 117 | clearTimeout(recentTimeoutId); 118 | setTimeoutAndSendToReducer(setTimeoutId, state); 119 | return; 120 | } 121 | const SideNavContainer = ({ 122 | currentComponent, 123 | templates, 124 | renameChild, 125 | changeChildType, 126 | addChild, 127 | deleteChild, 128 | renameComponent, 129 | changeType, 130 | showFileTree, 131 | toggleFileTree, 132 | deleteComponent, 133 | setCurrentComponent, 134 | setTemplatesForComponent, 135 | useTemplates, 136 | nameAndCodeLinkedToComponentId, 137 | recentTimeoutId, 138 | setTimeoutId, 139 | state, 140 | displaySubTreeDropDown, 141 | showSubTree, 142 | currentlyDisplayedSubTreeId, 143 | currentSubTreeDisplayToUser, 144 | addOrDeleteNewSubTree, 145 | deleteSubTreeDropdownItem 146 | }) => { 147 | return ( 148 |
    152 | 153 | 154 |
    155 | 156 | 157 |
    158 | 175 | 192 |
    193 | 201 | 207 | 208 |
    209 |
    210 | 211 | 212 | 213 | 214 | 223 | 224 |
    225 |
    226 |
    227 | ); 228 | }; 229 | 230 | export default React.memo( 231 | connect( 232 | mapStateToProps, 233 | mapDispatchToProps 234 | )(SideNavContainer) 235 | ); 236 | -------------------------------------------------------------------------------- /client/assets/styles/partials/_landing-page.scss: -------------------------------------------------------------------------------- 1 | #landing-page { 2 | // general 3 | h1 { 4 | font-size: 1.25rem; 5 | } 6 | h2, 7 | h3 { 8 | text-align: center; 9 | } 10 | 11 | // sections 12 | header { 13 | background: rgba(0, 0, 0, 0.5); 14 | box-shadow: none; 15 | position: fixed; 16 | 17 | .logo-frame { 18 | display: flex; 19 | justify-content: center; 20 | align-items: center; 21 | width: 50px; 22 | height: 50px; 23 | background: #fff; 24 | border-radius: 50%; 25 | margin-right: 10px; 26 | } 27 | 28 | .logo { 29 | width: 38px; 30 | } 31 | 32 | h1 { 33 | margin: 0 10px 0 0; 34 | } 35 | 36 | a { 37 | transition: 0.2s; 38 | 39 | &:hover { 40 | color: $prime-color-4; 41 | cursor: pointer; 42 | } 43 | } 44 | 45 | button { 46 | color: #fff; 47 | } 48 | 49 | #top-nav { 50 | justify-content: space-between; 51 | } 52 | 53 | .top-nav-left { 54 | display: flex; 55 | align-items: center; 56 | 57 | a { 58 | padding: 0 10px; 59 | } 60 | } 61 | 62 | // material ui overrides 63 | button { 64 | transition: 0.2s; 65 | 66 | &:hover { 67 | color: $prime-color-4; 68 | background-color: transparent; 69 | } 70 | } 71 | 72 | span.MuiButton-label { 73 | font-family: inherit; 74 | font-size: 16px; 75 | font-weight: 400; 76 | text-transform: none; 77 | 78 | &::after { 79 | display: inline-block; 80 | margin-left: 0.255em; 81 | vertical-align: 0.255em; 82 | content: ''; 83 | border-top: 0.3em solid; 84 | border-right: 0.3em solid transparent; 85 | border-bottom: 0; 86 | border-left: 0.3em solid transparent; 87 | } 88 | } 89 | } 90 | 91 | .landing-bg { 92 | width: 100%; 93 | height: 100%; 94 | background: linear-gradient(45deg, $prime-color-1, teal); 95 | position: fixed; 96 | top: 0; 97 | } 98 | 99 | #hero { 100 | display: flex; 101 | justify-content: center; 102 | align-items: center; 103 | width: 352px; 104 | height: 352px; 105 | color: #fff; 106 | margin: auto; 107 | position: absolute; 108 | top: 22vh; 109 | right: 0; 110 | left: 0; 111 | 112 | .logo-frame { 113 | display: flex; 114 | justify-content: center; 115 | align-items: center; 116 | width: 240px; 117 | height: 240px; 118 | background: #fff; 119 | border-radius: 50%; 120 | margin: 0 auto 20px; 121 | } 122 | 123 | .logo { 124 | width: 200px; 125 | } 126 | 127 | h2 { 128 | margin-bottom: 20px; 129 | } 130 | 131 | .github-buttons { 132 | display: flex; 133 | justify-content: center; 134 | 135 | > span { 136 | margin: 0 10px; 137 | } 138 | } 139 | } 140 | 141 | #features { 142 | background: $prime-color-5; 143 | padding: 80px 0; 144 | margin-top: 80vh; 145 | position: relative; 146 | 147 | h2 { 148 | margin-bottom: 40px; 149 | } 150 | 151 | figure.feature-item { 152 | display: flex; 153 | justify-content: center; 154 | align-items: center; 155 | max-width: 1200px; 156 | margin: 0 auto 80px; 157 | 158 | &:last-of-type { 159 | margin-bottom: 0; 160 | } 161 | 162 | > div { 163 | width: 50%; 164 | } 165 | } 166 | 167 | .image-frame { 168 | display: flex; 169 | justify-content: center; 170 | align-items: center; 171 | } 172 | 173 | figcaption { 174 | padding: 0 40px; 175 | } 176 | 177 | ul { 178 | list-style-type: disc; 179 | } 180 | 181 | i { 182 | font-size: 100px; 183 | color: $prime-color-1; 184 | margin: 0 20px; 185 | } 186 | } 187 | 188 | #action { 189 | display: flex; 190 | flex-direction: column; 191 | justify-content: center; 192 | align-items: center; 193 | max-width: 752px; 194 | color: #fff; 195 | margin: 160px auto; 196 | position: relative; 197 | 198 | h2, 199 | h3 { 200 | margin-bottom: 40px; 201 | } 202 | 203 | #tool-group { 204 | display: flex; 205 | justify-content: center; 206 | margin-bottom: 40px; 207 | } 208 | 209 | i { 210 | font-size: 100px; 211 | color: #fff; 212 | margin: 0 10px 10px; 213 | transition: 0.2s; 214 | } 215 | 216 | p { 217 | font-size: 24px; 218 | color: #fff; 219 | } 220 | 221 | button { 222 | background: none; 223 | border: 0; 224 | padding: 0; 225 | margin: 0 10px; 226 | 227 | &:hover { 228 | i { 229 | color: $prime-color-4; 230 | } 231 | } 232 | } 233 | } 234 | 235 | #details { 236 | text-align: center; 237 | padding: 160px 0; 238 | background: $prime-color-5; 239 | position: relative; 240 | 241 | a { 242 | &:hover { 243 | i { 244 | color: $prime-color-4; 245 | } 246 | } 247 | } 248 | 249 | i { 250 | font-size: 100px; 251 | color: $prime-color-1; 252 | transition: 0.2s; 253 | } 254 | } 255 | 256 | #team { 257 | display: flex; 258 | align-items: center; 259 | flex-direction: column; 260 | width: 100%; 261 | max-width: 1000px; 262 | margin: 160px auto; 263 | position: relative; 264 | 265 | h2 { 266 | color: #fff; 267 | margin-bottom: 40px; 268 | } 269 | 270 | #profile-group { 271 | display: flex; 272 | justify-content: space-between; 273 | width: 100%; 274 | 275 | > div { 276 | &:nth-of-type(1) { 277 | .profile-frame { 278 | &:hover { 279 | .profile-photo { 280 | background-image: url('../images/darren-funny.jpg'); 281 | } 282 | } 283 | } 284 | 285 | .profile-photo { 286 | background: url('../images/darren.jpg') no-repeat center; 287 | background-size: cover; 288 | } 289 | } 290 | 291 | &:nth-of-type(2) { 292 | .profile-frame { 293 | &:hover { 294 | .profile-photo { 295 | background-image: url('../images/kendall-funny.png'); 296 | } 297 | } 298 | } 299 | 300 | .profile-photo { 301 | background: url('../images/kendall.jpg') no-repeat center; 302 | background-size: cover; 303 | } 304 | } 305 | 306 | &:nth-of-type(3) { 307 | .profile-frame { 308 | &:hover { 309 | .profile-photo { 310 | background-image: url('../images/randy-funny.png'); 311 | } 312 | } 313 | } 314 | 315 | .profile-photo { 316 | background: url('../images/randy.jpg') no-repeat center; 317 | background-size: cover; 318 | } 319 | } 320 | 321 | &:nth-of-type(4) { 322 | .profile-frame { 323 | &:hover { 324 | .profile-photo { 325 | background-image: url('../images/krystal-funny.jpg'); 326 | } 327 | } 328 | } 329 | 330 | .profile-photo { 331 | background: url('../images/krystal.jpg') no-repeat center; 332 | background-size: cover; 333 | } 334 | } 335 | } 336 | 337 | > i { 338 | font-size: 80px; 339 | padding-top: 40px; 340 | 341 | &:last-child { 342 | display: none; 343 | } 344 | } 345 | } 346 | 347 | .profile { 348 | display: flex; 349 | flex-direction: column; 350 | align-items: center; 351 | position: relative; 352 | z-index: 1; 353 | } 354 | 355 | .profile-frame { 356 | display: flex; 357 | justify-content: center; 358 | align-items: center; 359 | width: 160px; 360 | height: 160px; 361 | background: $prime-color-5; 362 | border-radius: 50%; 363 | margin-bottom: 10px; 364 | 365 | &:hover { 366 | .profile-photo { 367 | transform: rotateY(180deg); 368 | } 369 | } 370 | } 371 | 372 | .profile-photo { 373 | width: 140px; 374 | height: 140px; 375 | border-radius: 50%; 376 | transition: 0.2s; 377 | } 378 | 379 | figcaption { 380 | font-size: 24px; 381 | text-align: center; 382 | color: #fff; 383 | margin-bottom: 4px; 384 | } 385 | 386 | .profile-links { 387 | display: flex; 388 | justify-content: center; 389 | 390 | a { 391 | margin: 0 10px; 392 | } 393 | 394 | i { 395 | transition: 0.2s; 396 | 397 | &:hover { 398 | color: $prime-color-4; 399 | } 400 | } 401 | } 402 | 403 | i { 404 | font-size: 40px; 405 | color: #fff; 406 | } 407 | } 408 | } 409 | -------------------------------------------------------------------------------- /client/reducers/mainReducer.js: -------------------------------------------------------------------------------- 1 | import * as types from '../constants/actionTypes'; 2 | import clone from 'clone'; 3 | import { 4 | deleteChildrenInNameAndCodeLinkedToComponentId, 5 | findAndDeleteInCurrentComponent, 6 | findSubTreeAndDeleteAllPropertiesInObjectRelatedToSubTree, 7 | deletePropertiesInsideOfSubTree, 8 | } from './utils/deleteNodeFuncs'; 9 | import { easterEgg } from './utils/easterEgg' 10 | import { updateTree, DoublyLinkedList } from './utils/updateTree' 11 | 12 | const appComponent = { 13 | name: 'App', 14 | depth: 0, 15 | id: 0, 16 | componentId: 0, 17 | isContainer: true, 18 | children: [] 19 | }; 20 | 21 | const initialState = { 22 | data: appComponent, 23 | dataClone: {}, 24 | translate: { x: 0, y: 0 }, 25 | history: null, 26 | currentComponent: appComponent, 27 | nameAndCodeLinkedToComponentId: {}, 28 | lastId: 0, 29 | defaultNameCount: 0, 30 | templates: [], 31 | orientation: 'vertical', 32 | toggleFileTree: true, 33 | recentTimeoutId: 0, 34 | displaySubTreeDropDown: { 0: 'App' }, 35 | currentSubTreeDisplayToUser: {}, 36 | currentlyDisplayedSubTreeId: 0 37 | }; 38 | 39 | const mainReducer = (state = initialState, action) => { 40 | let isContainer, 41 | currentComponent, 42 | childId, 43 | children, 44 | data, 45 | inputName, 46 | updatedState, 47 | history, 48 | nameAndCodeLinkedToComponentId, 49 | lastId, 50 | currentSubTreeDisplayToUser, 51 | currentlyDisplayedSubTreeId, 52 | displaySubTreeDropDown, 53 | defaultNameCount; 54 | switch (action.type) { 55 | /******************************* actions for side bar ************************************/ 56 | case types.RENAME_COMPONENT: 57 | inputName = action.payload.inputName; 58 | currentComponent = clone(state.currentComponent); 59 | currentComponent.name = inputName; 60 | updatedState = updateTree(state, currentComponent); 61 | displaySubTreeDropDown = Object.assign({}, state.displaySubTreeDropDown); 62 | if (state.displaySubTreeDropDown[`${currentComponent.componentId}`]) { 63 | displaySubTreeDropDown[`${currentComponent.componentId}`] = inputName; 64 | } 65 | return { 66 | ...state, 67 | ...updatedState, 68 | displaySubTreeDropDown 69 | }; 70 | 71 | case types.CHANGE_TYPE: 72 | isContainer = action.payload.isContainer; 73 | currentComponent = clone(state.currentComponent); 74 | currentComponent.isContainer = isContainer; 75 | updatedState = updateTree(state, currentComponent); 76 | 77 | return { 78 | ...state, 79 | ...updatedState 80 | }; 81 | 82 | case types.DELETE_COMPONENT: 83 | if (state.currentComponent.depth === 0) { 84 | alert("Error: can't delete root component."); 85 | return { 86 | ...state 87 | }; 88 | } 89 | //grabbing props from state to clone and mututate 90 | const parent = Object.assign({}, state.currentComponent.parent); 91 | data = clone(state.data); 92 | currentComponent = clone(state.currentComponent); 93 | nameAndCodeLinkedToComponentId = clone(state.nameAndCodeLinkedToComponentId); 94 | nameAndCodeLinkedToComponentId = deleteChildrenInNameAndCodeLinkedToComponentId(currentComponent, nameAndCodeLinkedToComponentId) 95 | findAndDeleteInCurrentComponent(data, currentComponent, parent); 96 | //deleting all of the properties in subtree dropdown that are related to the current component and its children 97 | displaySubTreeDropDown = Object.assign({}, state.displaySubTreeDropDown); 98 | deletePropertiesInsideOfSubTree(currentComponent, displaySubTreeDropDown); 99 | currentComponent = parent; 100 | lastId = state.lastId 101 | defaultNameCount = state.defaultNameCount; 102 | let preHistory = state.history; 103 | history = new DoublyLinkedList( 104 | clone({ 105 | data, 106 | currentComponent, 107 | nameAndCodeLinkedToComponentId, 108 | lastId, 109 | defaultNameCount, 110 | displaySubTreeDropDown 111 | }) 112 | ); 113 | preHistory.next = history; 114 | history.prev = preHistory; 115 | return { 116 | ...state, 117 | data, 118 | currentComponent: parent, 119 | nameAndCodeLinkedToComponentId, 120 | history, 121 | displaySubTreeDropDown 122 | }; 123 | 124 | /******************************* actions for main container ************************************/ 125 | case types.SET_CURRENT_COMPONENT: 126 | currentComponent = action.payload.currentComponent; 127 | return { 128 | ...state, 129 | currentComponent 130 | }; 131 | case types.SET_TRANS_AND_HISTORY: 132 | const translate = action.payload.translate; 133 | history = action.payload.history; 134 | return { 135 | ...state, 136 | translate, 137 | history 138 | }; 139 | case types.UN_DO: 140 | if (state.history.prev) { 141 | history = clone(state.history.prev); 142 | data = clone(history.value.data); 143 | currentComponent = clone(history.value.currentComponent); 144 | nameAndCodeLinkedToComponentId = clone( 145 | history.value.nameAndCodeLinkedToComponentId 146 | ); 147 | displaySubTreeDropDown = history.value.displaySubTreeDropDown; 148 | 149 | return { 150 | ...state, 151 | data, 152 | history, 153 | currentComponent, 154 | nameAndCodeLinkedToComponentId, 155 | displaySubTreeDropDown 156 | }; 157 | } else { 158 | return { 159 | ...state 160 | }; 161 | } 162 | 163 | case types.RE_DO: 164 | if (state.history.next) { 165 | history = clone(state.history.next); 166 | data = clone(history.value.data); 167 | currentComponent = clone(history.value.currentComponent); 168 | nameAndCodeLinkedToComponentId = clone( 169 | history.value.nameAndCodeLinkedToComponentId 170 | ); 171 | displaySubTreeDropDown = history.value.displaySubTreeDropDown; 172 | return { 173 | ...state, 174 | data, 175 | history, 176 | currentComponent, 177 | nameAndCodeLinkedToComponentId, 178 | displaySubTreeDropDown 179 | }; 180 | } else { 181 | return { 182 | ...state 183 | }; 184 | } 185 | /*********************** actions for current component children list ****************************/ 186 | 187 | case types.RENAME_CHILD: 188 | inputName = action.payload.inputName; 189 | childId = action.payload.childId; 190 | children = state.currentComponent.children.slice(); 191 | displaySubTreeDropDown = Object.assign({}, state.displaySubTreeDropDown); 192 | for (let child of children) { 193 | if (child.componentId === childId) { 194 | child.name = inputName; 195 | if (displaySubTreeDropDown[`${child.componentId}`]) { 196 | displaySubTreeDropDown[`${child.componentId}`] = inputName; 197 | } 198 | } 199 | } 200 | currentComponent = clone(state.currentComponent); 201 | currentComponent.children = children; 202 | updatedState = updateTree(state, currentComponent); 203 | return { 204 | ...state, 205 | ...updatedState, 206 | displaySubTreeDropDown 207 | }; 208 | 209 | case types.CHANGE_CHILD_TYPE: 210 | isContainer = action.payload.isChecked; 211 | childId = action.payload.childId; 212 | children = clone(state.currentComponent.children); 213 | for (let child of children) { 214 | if (child.componentId === childId) { 215 | child.isContainer = isContainer; 216 | } 217 | } 218 | currentComponent = clone(state.currentComponent); 219 | currentComponent.children = children; 220 | updatedState = updateTree(state, currentComponent); 221 | 222 | return { 223 | ...state, 224 | ...updatedState, 225 | }; 226 | 227 | case types.ADD_CHILD: 228 | 229 | let name, defaultNameCount; 230 | if (action.payload.name) { 231 | name = action.payload.name; 232 | if (name === 'Sandstorm') { 233 | easterEgg() 234 | } 235 | } else { 236 | defaultNameCount = state.defaultNameCount + 1; 237 | name = `Component${defaultNameCount}`; 238 | } 239 | 240 | isContainer = action.payload.isContainer; 241 | const componentId = state.lastId + 1; 242 | const newChild = { 243 | name, 244 | componentId, 245 | isContainer, 246 | parent: state.currentComponent 247 | }; 248 | children = state.currentComponent.children 249 | ? state.currentComponent.children.slice() 250 | : []; 251 | children.push(newChild); 252 | currentComponent = clone(state.currentComponent); 253 | currentComponent.children = children.slice(); 254 | updatedState = updateTree(state, currentComponent); 255 | nameAndCodeLinkedToComponentId = clone( 256 | state.nameAndCodeLinkedToComponentId 257 | ); 258 | 259 | nameAndCodeLinkedToComponentId[componentId] = state.templates[0]; 260 | updatedState.history.value.nameAndCodeLinkedToComponentId[componentId] = 261 | state.templates[0]; 262 | return { 263 | ...state, 264 | ...updatedState, 265 | nameAndCodeLinkedToComponentId, 266 | lastId: componentId, 267 | defaultNameCount: defaultNameCount 268 | ? defaultNameCount 269 | : state.defaultNameCount 270 | }; 271 | 272 | case types.DELETE_CHILD: 273 | childId = action.payload.childId; 274 | currentComponent = clone(state.currentComponent); 275 | let tempNode; 276 | for (let i = 0; i < currentComponent.children.length; i += 1) { 277 | if (currentComponent.children[i].componentId === childId) { 278 | [tempNode] = currentComponent.children.splice(i, 1); 279 | nameAndCodeLinkedToComponentId = clone( 280 | state.nameAndCodeLinkedToComponentId 281 | ); 282 | delete nameAndCodeLinkedToComponentId[childId]; 283 | if (tempNode.children && tempNode.children.length > 0) { 284 | nameAndCodeLinkedToComponentId = deleteChildrenInNameAndCodeLinkedToComponentId( 285 | tempNode.children, 286 | nameAndCodeLinkedToComponentId 287 | ); 288 | } 289 | } 290 | } 291 | displaySubTreeDropDown = Object.assign({}, state.displaySubTreeDropDown); 292 | if (displaySubTreeDropDown[`${childId}`]) { 293 | delete displaySubTreeDropDown[`${childId}`]; 294 | }; 295 | deletePropertiesInsideOfSubTree(tempNode, displaySubTreeDropDown); 296 | updatedState = updateTree(state, currentComponent); 297 | return { 298 | ...state, 299 | ...updatedState, 300 | nameAndCodeLinkedToComponentId, 301 | displaySubTreeDropDown 302 | }; 303 | 304 | case types.USE_TEMPLATES: 305 | let templates = [...action.payload.templates]; 306 | nameAndCodeLinkedToComponentId = clone( 307 | state.nameAndCodeLinkedToComponentId 308 | ); 309 | if (!nameAndCodeLinkedToComponentId['0']) { 310 | nameAndCodeLinkedToComponentId['0'] = templates[0]; 311 | } 312 | return { 313 | ...state, 314 | nameAndCodeLinkedToComponentId, 315 | templates 316 | }; 317 | case types.SET_TEMPLATES_FOR_COMPONENT: 318 | nameAndCodeLinkedToComponentId = clone( 319 | state.nameAndCodeLinkedToComponentId 320 | ); 321 | nameAndCodeLinkedToComponentId[ 322 | action.payload.currentComponent.componentId 323 | ] = action.payload.template; 324 | history = clone(state.history); 325 | history.value.nameAndCodeLinkedToComponentId[ 326 | action.payload.currentComponent.componentId 327 | ] = action.payload.template; 328 | return { 329 | ...state, 330 | history, 331 | nameAndCodeLinkedToComponentId 332 | }; 333 | case types.ZOOM_BY_CHANGING_X_AND_Y: 334 | translate = Object.assign({}, state.translate); 335 | translate.x += action.payload.x; 336 | translate.y += action.payload.y; 337 | return { 338 | ...state, 339 | translate 340 | }; 341 | case types.CHANGE_DISPLAY_HORIZONTAL_OR_VERTICAL: 342 | return { 343 | ...state, 344 | orientation: action.payload 345 | }; 346 | case types.UPDATE_STATE_WITH_LOCAL_STORAGE: 347 | data = action.payload.data; 348 | currentComponent = action.payload.currentComponent; 349 | nameAndCodeLinkedToComponentId = 350 | action.payload.nameAndCodeLinkedToComponentId; 351 | lastId = action.payload.lastId; 352 | history = action.payload.history 353 | displaySubTreeDropDown = action.payload.displaySubTreeDropDown 354 | defaultNameCount = lastId - 1; 355 | 356 | return { 357 | ...state, 358 | data, 359 | currentComponent, 360 | nameAndCodeLinkedToComponentId, 361 | lastId, 362 | history, 363 | defaultNameCount, 364 | displaySubTreeDropDown 365 | }; 366 | case types.RESET_ENTIRE_TREE: 367 | localStorage.clear(); 368 | location.reload(true); 369 | return { 370 | ...state 371 | }; 372 | // file tree toggle 373 | case types.SHOW_FILE_TREE: 374 | const newToggleFileTree = state.toggleFileTree; 375 | return { 376 | ...state, 377 | toggleFileTree: !newToggleFileTree 378 | }; 379 | case types.SET_TIMEOUT_ID: 380 | return { 381 | ...state, 382 | recentTimeoutId: action.payload 383 | } 384 | case types.SHOW_SUBTREE: 385 | //recursively find the node with matching componentId with action payload passed in (number), once found clone the node (and potentially its children) and set it to tempNodeForSubTree 386 | if (action.payload === undefined) { 387 | currentlyDisplayedSubTreeId = state.currentlyDisplayedSubTreeId 388 | } else { 389 | currentlyDisplayedSubTreeId = action.payload; 390 | } 391 | (function findComponentIdNode(id, data) { 392 | if (!data) return; 393 | if (data.componentId === id) { 394 | currentSubTreeDisplayToUser = clone(data); 395 | return; 396 | } 397 | if (data.children) { 398 | data.children.forEach(node => { 399 | return findComponentIdNode(id, node); 400 | }); 401 | } 402 | }(currentlyDisplayedSubTreeId, state.data)); 403 | return { 404 | ...state, 405 | currentSubTreeDisplayToUser, 406 | currentlyDisplayedSubTreeId 407 | } 408 | case types.ADD_OR_DELETE_NEW_SUB_TREE: 409 | //checking of the checkbox is checked, if so go ahead and shallow clone subtree object and insert new componentId as key and name as value 410 | if (action.payload.isChecked) { 411 | displaySubTreeDropDown = Object.assign({}, state.displaySubTreeDropDown); 412 | displaySubTreeDropDown[action.payload.componentId] = action.payload.name; 413 | } else { 414 | displaySubTreeDropDown = Object.assign({}, state.displaySubTreeDropDown); 415 | for (let keys in displaySubTreeDropDown) { 416 | if (+keys === action.payload.componentId) { 417 | delete displaySubTreeDropDown[keys]; 418 | } 419 | } 420 | } 421 | return { 422 | ...state, 423 | displaySubTreeDropDown 424 | } 425 | case types.DELETE_SUBTREE_DROPDOWN_ITEM: 426 | displaySubTreeDropDown = Object.assign({}, state.displaySubTreeDropDown); 427 | findSubTreeAndDeleteAllPropertiesInObjectRelatedToSubTree(+action.payload, state.data, displaySubTreeDropDown); 428 | return { 429 | ...state, 430 | displaySubTreeDropDown 431 | } 432 | default: 433 | return state; 434 | } 435 | }; 436 | 437 | export default mainReducer; 438 | -------------------------------------------------------------------------------- /client/assets/styles/styles.css.map: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "mappings": "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", 4 | "sources": [ 5 | "styles.scss", 6 | "partials/_general.scss", 7 | "partials/_landing-page.scss", 8 | "partials/_application.scss", 9 | "partials/_topnav-container.scss", 10 | "partials/_panel-container.scss", 11 | "partials/_visual-container.scss", 12 | "partials/_easter-egg.scss" 13 | ], 14 | "names": [], 15 | "file": "styles.css" 16 | } --------------------------------------------------------------------------------