From b7274aa051362557120f2c0d87fdf6e14e516e32 Mon Sep 17 00:00:00 2001 From: Jasper Dansercoer Date: Fri, 17 May 2019 09:40:34 +0200 Subject: [PATCH 1/6] First version of grouping routes --- client/src/components/RouteList/index.js | 157 ++++++++++++++++++----- 1 file changed, 123 insertions(+), 34 deletions(-) diff --git a/client/src/components/RouteList/index.js b/client/src/components/RouteList/index.js index 6735aa3..ebf3233 100644 --- a/client/src/components/RouteList/index.js +++ b/client/src/components/RouteList/index.js @@ -1,7 +1,14 @@ import React, { useState } from "react"; import url from "url"; +import _ from "lodash"; +import styled from "styled-components"; + import { MOCKIT_SERVER_URL } from "../../utils/consts"; +const Wrapper = styled.div` + padding-left: 20px; +`; + const openRoute = route => { return () => { window.open(url.resolve(MOCKIT_SERVER_URL, route), "_blank"); @@ -9,7 +16,10 @@ const openRoute = route => { }; const RouteItem = function({ title, value }) { - const buildAriaLabel = label => (label ? `route-${title.toLowerCase()}-${label}` : `route-${title.toLowerCase()}`); + const buildAriaLabel = label => + label + ? `route-${title.toLowerCase()}-${label}` + : `route-${title.toLowerCase()}`; return (
@@ -26,7 +36,11 @@ const RouteItem = function({ title, value }) { }; const Routes = function(props) { - const { onRouteEdit = () => {}, onRouteDelete = () => {}, routes = [] } = props; + const { + onRouteEdit = () => {}, + onRouteDelete = () => {}, + routes = [] + } = props; const editRoute = item => { return event => { @@ -42,40 +56,115 @@ const Routes = function(props) { }; }; - return ( - <> - {routes.length === 0 &&

No routes found. Click "Add Route" to get started.

} - {routes.map(item => { - const { delay = 0, route, statusCode, httpMethod, disabled = false } = item; - const routeClassName = disabled ? "disabled" : ""; - return ( -
-
-
- -
-
-
- ); - })} +
+ {_.size(_.omit(item, fieldsInRoute)) > 0 && + renderLevel(_.omit(item, fieldsInRoute), index + 1)} + + ); + } + + console.log(item); + + return ( + + {_.size(_.omit(item, fieldsInRoute)) > 0 && + renderLevel( + _.omit(item, fieldsInRoute), + index, + titleFromParent ? `${titleFromParent}/${key}` : key + )} + + ); + })} + + ); + }; + + return ( + <> + {routes.length === 0 && ( +

+ No routes found. Click "Add Route" to get started. +

+ )} + {renderLevel(groupedRoutes, 0)} ); }; From 50d69b7581e34d94951db2e5f4c66fde06e1dfb0 Mon Sep 17 00:00:00 2001 From: Jasper Dansercoer Date: Fri, 17 May 2019 15:41:12 +0200 Subject: [PATCH 2/6] Switched to new calculation of groups and styled them --- client/src/App.js | 5 +- client/src/components/RouteList/Route.js | 68 ++++ client/src/components/RouteList/RouteItem.js | 23 ++ client/src/components/RouteList/index.js | 308 ++++++++++--------- client/src/scss/App.scss | 1 - 5 files changed, 259 insertions(+), 146 deletions(-) create mode 100644 client/src/components/RouteList/Route.js create mode 100644 client/src/components/RouteList/RouteItem.js diff --git a/client/src/App.js b/client/src/App.js index 4cd7413..b107742 100755 --- a/client/src/App.js +++ b/client/src/App.js @@ -14,10 +14,7 @@ import { settings, routes } from "./config/routes.json"; import "./scss/index.scss"; export default function({ settings: propSettings }) { - useScrollReval([ - { selector: ".hero .title, .card, .subtitle " }, - { selector: ".route", options: { duration: 750, distance: "40px", easing: "cubic-bezier(0.5, -0.01, 0, 1.005)", interval: 64, origin: "bottom", viewFactor: 0.32 } } - ]); + useScrollReval([{ selector: ".hero .title, .card, .subtitle " }]); const [selectedRoute, setSelectedRoute] = useState(); const [routeToBeRemoved, setRouteToBeRemoved] = useState(); diff --git a/client/src/components/RouteList/Route.js b/client/src/components/RouteList/Route.js new file mode 100644 index 0000000..08a4248 --- /dev/null +++ b/client/src/components/RouteList/Route.js @@ -0,0 +1,68 @@ +import React from "react"; +import url from "url"; +import RouteItem from "./RouteItem"; + +import { MOCKIT_SERVER_URL } from "../../utils/consts"; + +const Route = ({ routeItem, onRouteDelete, onRouteEdit }) => { + const { + delay = 0, + route, + statusCode, + httpMethod, + disabled = false + } = routeItem; + const routeClassName = disabled ? "disabled" : ""; + + const openRoute = route => { + return () => { + window.open(url.resolve(MOCKIT_SERVER_URL, route), "_blank"); + }; + }; + + const editRoute = event => { + event.stopPropagation(); + onRouteEdit(routeItem); + }; + + const deleteRoute = event => { + event.stopPropagation(); + onRouteDelete(routeItem); + }; + + return ( +
+
+ +
+
+ ); +}; + +export default Route; diff --git a/client/src/components/RouteList/RouteItem.js b/client/src/components/RouteList/RouteItem.js new file mode 100644 index 0000000..b174e40 --- /dev/null +++ b/client/src/components/RouteList/RouteItem.js @@ -0,0 +1,23 @@ +import React from "react"; + +const RouteItem = ({ title, value }) => { + const buildAriaLabel = label => + label + ? `route-${title.toLowerCase()}-${label}` + : `route-${title.toLowerCase()}`; + + return ( +
+
+

+ {title} +

+

+ {value} +

+
+
+ ); +}; + +export default RouteItem; diff --git a/client/src/components/RouteList/index.js b/client/src/components/RouteList/index.js index ebf3233..2bf11f6 100644 --- a/client/src/components/RouteList/index.js +++ b/client/src/components/RouteList/index.js @@ -1,171 +1,197 @@ -import React, { useState } from "react"; -import url from "url"; +import React, { useMemo } from "react"; import _ from "lodash"; import styled from "styled-components"; +import Route from "./Route"; -import { MOCKIT_SERVER_URL } from "../../utils/consts"; - -const Wrapper = styled.div` +const Wrapper = styled.details` padding-left: 20px; `; -const openRoute = route => { - return () => { - window.open(url.resolve(MOCKIT_SERVER_URL, route), "_blank"); - }; -}; - -const RouteItem = function({ title, value }) { - const buildAriaLabel = label => - label - ? `route-${title.toLowerCase()}-${label}` - : `route-${title.toLowerCase()}`; - - return ( -
-
-

- {title} -

-

- {value} -

-
-
- ); -}; - -const Routes = function(props) { - const { - onRouteEdit = () => {}, - onRouteDelete = () => {}, - routes = [] - } = props; - - const editRoute = item => { - return event => { - event.stopPropagation(); - onRouteEdit(item); - }; - }; - - const deleteRoute = item => { - return event => { - event.stopPropagation(); - onRouteDelete(item); - }; - }; - - const orderedRoutes = _.orderBy(routes, route => { - return route.route.split("/").length; - }); - const groupedRoutes = {}; - - orderedRoutes.forEach(route => { - const paths = route.route.split("/"); - - _.set(groupedRoutes, paths.slice(1, paths.length), { ...route }); - // paths.forEach() - }); +const RouteTitle = styled.summary` + color: #1d1d1d; + font-weight: 600; + cursor: pointer; + font-size: 1.3em; + padding-left: 50px; + position: relative; + + &:before { + position: absolute; + content: " "; + height: 2px; + background-color: #209cee; + left: 0; + right: 0; + top: 50%; + transform: translateY(-50%); + z-index: -1; + } + + &:focus { + outline: none; + } + + &::-webkit-details-marker { + background: white; + padding-right: 10px; + padding-left: 10px; + } +`; - console.log(groupedRoutes); +const RouteTitleText = styled.span` + background-color: white; + padding-right: 10px; + margin-left: -10px; +`; - const renderLevel = (routes, index, titleFromParent) => { - const fieldsInRoute = [ - "id", - "route", - "payload", - "httpMethod", - "statusCode", - "delay", - "disabled" - ]; +const Routes = function({ routes, ...props }) { + const groupedRoutes = useMemo(() => { + // This function takes all the routes and groupes them by paths. + // Parent routes get a children object containing their direct children. + // Children in their turn can also have children. + // + // An example of grouped routes would be + // { + // user: { + // id: "1f4dfdf3-5712-48b7-9310-6314f8ee2adc", + // route: "/user", + // payload: { + // httpMethod: "get", + // newRoute: true, + // Money: 100 + // }, + // httpMethod: "POST", + // statusCode: "201", + // delay: "500", + // children: { + // login: { + // id: "1f4dfdf3-5712-48b7-9310-6314f8ee2adc", + // route: "/user/get/it/now", + // payload: { + // httpMethod: "get", + // newRoute: true, + // Money: 100 + // }, + // httpMethod: "POST", + // statusCode: "201", + // delay: "500" + // } + // } + // }, + // fruit: { + // id: "1f4dfdf3-5712-48b7-9310-6314f8ee2add", + // route: "/fruit", + // payload: { + // httpMethod: "get", + // newRoute: true, + // Money: 100 + // }, + // httpMethod: "POST", + // statusCode: "201", + // delay: "0", + // disabled: true, + // children: {} + // }, + // cart: { + // children: { + // purchase: { + // children: { + // vise: { + // id: "1f4dfdf3-5712-48b7-9310-6314f8ee2add", + // route: "/nothing/more/deleted", + // payload: { + // httpMethod: "get", + // newRoute: true, + // Money: 100 + // }, + // httpMethod: "POST", + // statusCode: "201", + // delay: "0" + // } + // } + // } + // } + // } + // } + + // We need to order routes by route length. Otherwise, if a deeper router would appear + // before a a shallower route, the shallow route would overwrite the deep route + // when using _.set + const orderedRoutes = _.orderBy(routes, route => { + return route.route.split("/").length; + }); + + const routesObject = {}; + orderedRoutes.forEach(route => { + const paths = route.route.split("/"); + const routeDepth = paths.length; + const parentPath = paths.slice(1, paths.length - 1); + const lastLevel = paths[paths.length - 1]; + + // routes with a depth lower than three are the first-level routes since all routes + // start with a slash, so their split path becomes ['', 'path'] + if (routeDepth < 3) { + routesObject[lastLevel] = { + ...route, + children: {} + }; + } else { + let pathToChild = []; + parentPath.forEach((parent, index) => { + const currentLevelPath = parentPath.slice(0, index + 1); + const currentLevelPathWithChildren = []; + currentLevelPath.forEach(path => { + currentLevelPathWithChildren.push(path, "children"); + }); + pathToChild = currentLevelPathWithChildren; + }); + _.set(routesObject, [...pathToChild, lastLevel], { ...route }); + } + }); + + return routesObject; + }, [routes]); + + const renderLevel = (routes, index) => { return ( -
+ {_.map(routes, (item, key) => { - const { - delay = 0, - route, - statusCode, - httpMethod, - disabled = false - } = item; - const routeClassName = disabled ? "disabled" : ""; - - if (_.size(_.pick(item, fieldsInRoute)) > 0) { + if (_.size(_.omit(item, ["children"])) > 0) { return ( - -
- {titleFromParent}/{key} -
-
-
-
- -
-
-
- {_.size(_.omit(item, fieldsInRoute)) > 0 && - renderLevel(_.omit(item, fieldsInRoute), index + 1)} + + + /{key} + + + {_.size(item.children) > 0 && + renderLevel(item.children, index + 1)} ); } - console.log(item); - return ( - - {_.size(_.omit(item, fieldsInRoute)) > 0 && - renderLevel( - _.omit(item, fieldsInRoute), - index, - titleFromParent ? `${titleFromParent}/${key}` : key - )} + + + /{key} + + {_.size(item.children) > 0 && renderLevel(item.children, index)} ); })} -
+ ); }; return ( - <> - {routes.length === 0 && ( + + {routes.length === 0 ? (

No routes found. Click "Add Route" to get started.

+ ) : ( + renderLevel(groupedRoutes, 0) )} - {renderLevel(groupedRoutes, 0)} - +
); }; diff --git a/client/src/scss/App.scss b/client/src/scss/App.scss index 683730d..ad4cf52 100644 --- a/client/src/scss/App.scss +++ b/client/src/scss/App.scss @@ -54,7 +54,6 @@ main { } .hero .title, -.route, .subtitle { visibility: hidden; } From b229d3274ea6ead3abee5c712ae68b0d94fb4ddd Mon Sep 17 00:00:00 2001 From: Jasper Dansercoer Date: Fri, 17 May 2019 16:19:18 +0200 Subject: [PATCH 3/6] Added group routing based on togglable state --- client/package.json | 2 ++ client/src/components/RouteList/index.js | 24 ++++++++++++++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/client/package.json b/client/package.json index ffc211e..000bf17 100644 --- a/client/package.json +++ b/client/package.json @@ -6,12 +6,14 @@ "bulma": "^0.7.4", "bulma-extensions": "^6.2.4", "faker": "^4.1.0", + "lodash": "^4.17.11", "node-sass": "^4.11.0", "react": "v16.8.3", "react-dom": "v16.8.3", "react-json-editor-ajrm": "^2.5.9", "react-scripts": "3.0.0", "scrollreveal": "^4.0.5", + "styled-components": "^4.2.0", "uuid": "^3.3.2" }, "scripts": { diff --git a/client/src/components/RouteList/index.js b/client/src/components/RouteList/index.js index 2bf11f6..0288240 100644 --- a/client/src/components/RouteList/index.js +++ b/client/src/components/RouteList/index.js @@ -1,4 +1,4 @@ -import React, { useMemo } from "react"; +import React, { useMemo, useState } from "react"; import _ from "lodash"; import styled from "styled-components"; import Route from "./Route"; @@ -45,6 +45,8 @@ const RouteTitleText = styled.span` `; const Routes = function({ routes, ...props }) { + const [groupRoutes, setGroupRoutes] = useState(false); + const groupedRoutes = useMemo(() => { // This function takes all the routes and groupes them by paths. // Parent routes get a children object containing their direct children. @@ -184,12 +186,30 @@ const Routes = function({ routes, ...props }) { return ( +
+ { + setGroupRoutes(!groupRoutes); + }} + aria-label="feature-basic-auth-input" + /> + +
{routes.length === 0 ? (

No routes found. Click "Add Route" to get started.

- ) : ( + ) : groupRoutes ? ( renderLevel(groupedRoutes, 0) + ) : ( + _.map(routes, (route, key) => ( + + )) )}
); From 2b3219cf8c0e8643428c8b5c3cee4d90d70bd9c4 Mon Sep 17 00:00:00 2001 From: Jasper Dansercoer Date: Fri, 17 May 2019 16:28:20 +0200 Subject: [PATCH 4/6] Updated package-lock --- client/package-lock.json | 97 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/client/package-lock.json b/client/package-lock.json index c190260..63d37e8 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -932,6 +932,24 @@ "resolved": "https://registry.npmjs.org/@csstools/normalize.css/-/normalize.css-9.0.1.tgz", "integrity": "sha512-6It2EVfGskxZCQhuykrfnALg7oVeiI6KclWSmGDqB0AiInVrTGB9Jp9i4/Ad21u9Jde/voVQz6eFX/eSg/UsPA==" }, + "@emotion/is-prop-valid": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.7.3.tgz", + "integrity": "sha512-uxJqm/sqwXw3YPA5GXX365OBcJGFtxUVkB6WyezqFHlNe9jqUWH5ur2O2M8dGBz61kn1g3ZBlzUunFQXQIClhA==", + "requires": { + "@emotion/memoize": "0.7.1" + } + }, + "@emotion/memoize": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.1.tgz", + "integrity": "sha512-Qv4LTqO11jepd5Qmlp3M1YEjBumoTHcHFdgPTQ+sFlIL5myi/7xu/POwP7IRu6odBdmLXdtIs1D6TuW6kbwbbg==" + }, + "@emotion/unitless": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.3.tgz", + "integrity": "sha512-4zAPlpDEh2VwXswwr/t8xGNDGg8RQiPxtxZ3qQEXyQsBV39ptTdESCjuBvGze1nLMVrxmTIKmnO/nAV8Tqjjzg==" + }, "@jest/console": { "version": "24.7.1", "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.7.1.tgz", @@ -2185,6 +2203,22 @@ "resolved": "https://registry.npmjs.org/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.2.tgz", "integrity": "sha512-CxwvxrZ9OirpXQ201Ec57OmGhmI8/ui/GwTDy0hSp6CmRvgRC0pSair6Z04Ck+JStA0sMPZzSJ3uE4n17EXpPQ==" }, + "babel-plugin-styled-components": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-1.10.0.tgz", + "integrity": "sha512-sQVKG8irFXx14ZfaK1bBePirfkacl3j8nZwSZK+ZjsbnadRHKQTbhXbe/RB1vT6Vgkz45E+V95LBq4KqdhZUNw==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.0.0", + "@babel/helper-module-imports": "^7.0.0", + "babel-plugin-syntax-jsx": "^6.18.0", + "lodash": "^4.17.10" + } + }, + "babel-plugin-syntax-jsx": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", + "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=" + }, "babel-plugin-syntax-object-rest-spread": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", @@ -2728,6 +2762,11 @@ "map-obj": "^1.0.0" } }, + "camelize": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz", + "integrity": "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs=" + }, "caniuse-api": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", @@ -3792,6 +3831,11 @@ "postcss": "^7.0.5" } }, + "css-color-keywords": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", + "integrity": "sha1-/qJhbcZ2spYmhrOvjb2+GAskTgU=" + }, "css-color-names": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", @@ -3886,6 +3930,16 @@ "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==" }, + "css-to-react-native": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-2.3.1.tgz", + "integrity": "sha512-yO+oEx1Lf+hDKasqQRVrAvzMCz825Huh1VMlEEDlRWyAhFb/FWb6I0KpEF1PkyKQ7NEdcx9d5M2ZEWgJAsgPvQ==", + "requires": { + "camelize": "^1.0.0", + "css-color-keywords": "^1.0.0", + "postcss-value-parser": "^3.3.0" + } + }, "css-tree": { "version": "1.0.0-alpha.28", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.28.tgz", @@ -9107,6 +9161,11 @@ } } }, + "memoize-one": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.0.4.tgz", + "integrity": "sha512-P0z5IeAH6qHHGkJIXWw0xC2HNEgkx/9uWWBQw64FJj3/ol14VYdfVGWWr0fXfjhhv3TKVIqUq65os6O4GUNksA==" + }, "memory-fs": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", @@ -12943,6 +13002,34 @@ "schema-utils": "^1.0.0" } }, + "styled-components": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-4.2.0.tgz", + "integrity": "sha512-L/LzkL3ZbBhqIVHdR7DbYujy4tqvTNRfc+4JWDCYyhTatI+8CRRQUmdaR0+ARl03DWsfKLhjewll5uNLrqrl4A==", + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@emotion/is-prop-valid": "^0.7.3", + "@emotion/unitless": "^0.7.0", + "babel-plugin-styled-components": ">= 1", + "css-to-react-native": "^2.2.2", + "memoize-one": "^5.0.0", + "prop-types": "^15.5.4", + "react-is": "^16.6.0", + "stylis": "^3.5.0", + "stylis-rule-sheet": "^0.0.10", + "supports-color": "^5.5.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, "stylehacks": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-4.0.3.tgz", @@ -12965,6 +13052,16 @@ } } }, + "stylis": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-3.5.4.tgz", + "integrity": "sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q==" + }, + "stylis-rule-sheet": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stylis-rule-sheet/-/stylis-rule-sheet-0.0.10.tgz", + "integrity": "sha512-nTbZoaqoBnmK+ptANthb10ZRZOGC+EmTLLUxeYIuHNkEKcmKgXX1XWKkUBT2Ac4es3NybooPe0SmvKdhKJZAuw==" + }, "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", From 8cd172859aa98c63ae01e7a1cdcbb5880bfd048d Mon Sep 17 00:00:00 2001 From: David Boyne Date: Sun, 19 May 2019 20:18:19 +0100 Subject: [PATCH 5/6] DB - Moved some components around, added some tests and fixed jest running tests --- client/config-overrides.js | 6 + client/package-lock.json | 26 +++ client/package.json | 3 +- client/src/App.js | 12 +- .../{RouteList => Route}/RouteItem.js | 5 +- .../{RouteList/Route.js => Route/index.js} | 22 +- .../components/{RouteList => Route}/spec.js | 53 ++--- client/src/components/RouteList/index.js | 218 ------------------ client/src/components/RouteListGroup/index.js | 109 +++++++++ client/src/components/RouteListGroup/spec.js | 61 +++++ client/src/components/RouteListStack/index.js | 9 + client/src/components/RouteListStack/spec.js | 50 ++++ client/src/components/SettingsModal/index.js | 19 +- client/src/components/SettingsModal/spec.js | 15 ++ client/src/config/routes.json | 13 ++ client/src/spec.js | 4 +- 16 files changed, 348 insertions(+), 277 deletions(-) create mode 100644 client/config-overrides.js rename client/src/components/{RouteList => Route}/RouteItem.js (77%) rename client/src/components/{RouteList/Route.js => Route/index.js} (74%) rename client/src/components/{RouteList => Route}/spec.js (59%) delete mode 100644 client/src/components/RouteList/index.js create mode 100644 client/src/components/RouteListGroup/index.js create mode 100644 client/src/components/RouteListGroup/spec.js create mode 100644 client/src/components/RouteListStack/index.js create mode 100644 client/src/components/RouteListStack/spec.js diff --git a/client/config-overrides.js b/client/config-overrides.js new file mode 100644 index 0000000..a9fcefe --- /dev/null +++ b/client/config-overrides.js @@ -0,0 +1,6 @@ +module.exports = { + jest: function(config) { + config.testMatch.push("/src/**/{spec,test}.{js,jsx,ts,tsx}"); + return config; + } +}; diff --git a/client/package-lock.json b/client/package-lock.json index 63d37e8..e20baeb 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -11431,6 +11431,32 @@ "whatwg-fetch": "3.0.0" } }, + "react-app-rewired": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/react-app-rewired/-/react-app-rewired-2.1.3.tgz", + "integrity": "sha512-NXC2EsQrnEMV7xD70rHcBq0B4PSEzjY/K2m/e+GRgit2jZO/uZApnpCZSKvIX2leLRN69Sqf2id0VXZ1F62CDw==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.5", + "dotenv": "^6.2.0", + "semver": "^5.6.0" + }, + "dependencies": { + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + } + } + }, "react-dev-utils": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-9.0.0.tgz", diff --git a/client/package.json b/client/package.json index 000bf17..78fc1e7 100644 --- a/client/package.json +++ b/client/package.json @@ -19,7 +19,7 @@ "scripts": { "start": "react-scripts start", "build": "react-scripts build", - "test": "REACT_APP_MOCKIT_API_URL=localhost react-scripts test", + "test": "react-app-rewired test", "eject": "react-scripts eject" }, "jest": { @@ -42,6 +42,7 @@ "dom-testing-library": "^3.19.1", "jest-dom": "^3.1.3", "nock": "^10.0.6", + "react-app-rewired": "^2.1.3", "react-testing-library": "^6.1.2" } } diff --git a/client/src/App.js b/client/src/App.js index b107742..e1629ae 100755 --- a/client/src/App.js +++ b/client/src/App.js @@ -1,6 +1,7 @@ import React, { useState } from "react"; import useScrollReval from "./hooks/useScrollReveal"; -import RouteList from "./components/RouteList"; +import RouteListStack from "./components/RouteListStack"; +import RouteListGroup from "./components/RouteListGroup"; import Logo from "./components/Logo"; import { buildRoute, deleteRoute } from "./utils/routes-api"; @@ -20,7 +21,7 @@ export default function({ settings: propSettings }) { const [routeToBeRemoved, setRouteToBeRemoved] = useState(); const [settingsModalVisible, showSettingsModal] = useState(false); - const { features: { chaosMonkey = false } = {} } = propSettings || settings; + const { features: { chaosMonkey = false, groupedRoutes = false } = {} } = propSettings || settings; return ( <> @@ -70,8 +71,13 @@ export default function({ settings: propSettings }) {

The chaos monkey is enabled and causing havoc on all APIs...

)} + {routes.length === 0 &&

No routes found. Click "Add Route" to get started.

} - setSelectedRoute(route)} onRouteDelete={route => setRouteToBeRemoved(route)} /> + {groupedRoutes ? ( + setSelectedRoute(route)} onRouteDelete={route => setRouteToBeRemoved(route)} /> + ) : ( + setSelectedRoute(route)} onRouteDelete={route => setRouteToBeRemoved(route)} /> + )}