From 1805871924c38b5265b9b4c562feef9b55a7a3e8 Mon Sep 17 00:00:00 2001 From: Eric Soderberg Date: Thu, 2 Jul 2020 12:03:02 -0700 Subject: [PATCH] Initial version --- .gitignore | 23 + README.md | 4 +- package.json | 37 + public/_redirects | 1 + public/index.html | 19 + public/manifest.json | 15 + public/robots.txt | 3 + public/shortcut-icon.png | Bin 0 -> 423 bytes src/App.js | 192 + src/App.test.js | 9 + src/data.json | 59 + src/index.js | 16 + src/serviceWorker.js | 141 + src/setupTests.js | 5 + yarn.lock | 11016 +++++++++++++++++++++++++++++++++++++ 15 files changed, 11539 insertions(+), 1 deletion(-) create mode 100644 .gitignore create mode 100644 package.json create mode 100644 public/_redirects create mode 100644 public/index.html create mode 100644 public/manifest.json create mode 100644 public/robots.txt create mode 100644 public/shortcut-icon.png create mode 100644 src/App.js create mode 100644 src/App.test.js create mode 100644 src/data.json create mode 100644 src/index.js create mode 100644 src/serviceWorker.js create mode 100644 src/setupTests.js create mode 100644 yarn.lock diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4d29575 --- /dev/null +++ b/.gitignore @@ -0,0 +1,23 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# production +/build + +# misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + +npm-debug.log* +yarn-debug.log* +yarn-error.log* diff --git a/README.md b/README.md index 063d27b..1626226 100644 --- a/README.md +++ b/README.md @@ -1 +1,3 @@ -# grommet-roadmap \ No newline at end of file +# grommet-roadmap + +A work in progress ... diff --git a/package.json b/package.json new file mode 100644 index 0000000..0df7216 --- /dev/null +++ b/package.json @@ -0,0 +1,37 @@ +{ + "name": "grommet-roadmap", + "version": "0.1.0", + "private": true, + "dependencies": { + "@testing-library/jest-dom": "^4.2.4", + "@testing-library/react": "^9.3.2", + "@testing-library/user-event": "^7.1.2", + "grommet": "^2.14.0", + "grommet-icons": "^4.4.0", + "react": "^16.13.1", + "react-dom": "^16.13.1", + "react-scripts": "3.4.1", + "styled-components": "^5.1.1" + }, + "scripts": { + "start": "react-scripts start", + "build": "react-scripts build", + "test": "react-scripts test", + "eject": "react-scripts eject" + }, + "eslintConfig": { + "extends": "react-app" + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + } +} diff --git a/public/_redirects b/public/_redirects new file mode 100644 index 0000000..17cd92f --- /dev/null +++ b/public/_redirects @@ -0,0 +1 @@ +/* /index.html 200 diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..a094add --- /dev/null +++ b/public/index.html @@ -0,0 +1,19 @@ + + + + + + + + + + Grommet Roadmap + + + +
+ + diff --git a/public/manifest.json b/public/manifest.json new file mode 100644 index 0000000..546b86f --- /dev/null +++ b/public/manifest.json @@ -0,0 +1,15 @@ +{ + "short_name": "Grommet Roadmap", + "name": "Grommet Roadmap", + "icons": [ + { + "src": "shortcut-icon.png", + "sizes": "64x64 32x32 24x24 16x16", + "type": "image/png" + } + ], + "start_url": ".", + "display": "standalone", + "theme_color": "#000000", + "background_color": "#ffffff" +} diff --git a/public/robots.txt b/public/robots.txt new file mode 100644 index 0000000..e9e57dc --- /dev/null +++ b/public/robots.txt @@ -0,0 +1,3 @@ +# https://www.robotstxt.org/robotstxt.html +User-agent: * +Disallow: diff --git a/public/shortcut-icon.png b/public/shortcut-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..5af0e008b8a192e40ea00fbd0662fc430f4be299 GIT binary patch literal 423 zcmV;Y0a*TtP)};*NV+@(hYZ5CQ>%#Ait3 z6KE|qY15^-;w#&&E1+p}M}j*K2? zh?=@KiRX|t&@uV|>8R87m5~pI8ZZ`Dhg>xfks~Dc+Oi1Xrf-C?8~Q!OCc>tCwFTx^ z06*UOWD_C6+{!HL(Wj_Min@LS` R3#tGB002ovPDHLkV1i0%xD5aR literal 0 HcmV?d00001 diff --git a/src/App.js b/src/App.js new file mode 100644 index 0000000..bb41b26 --- /dev/null +++ b/src/App.js @@ -0,0 +1,192 @@ +import React, { useEffect, useMemo, useState } from "react"; +import { + Box, + Button, + Grid, + Grommet, + Header, + Heading, + ResponsiveContext, + Text, +} from "grommet"; +import { Next, Previous, StatusGood, StatusWarning } from "grommet-icons"; +import { grommet } from "grommet/themes"; + +import data from "./data"; + +const addMonths = (date, months) => { + const result = new Date(date); + const years = Math.floor((date.getMonth() + months) / 12); + result.setFullYear(date.getFullYear() + years); + const targetMonth = (date.getMonth() + months) % 12; + result.setMonth(targetMonth < 0 ? 12 + targetMonth : targetMonth); + return result; +}; + +const subtractMonths = (date, months) => addMonths(date, -months); + +const sameMonth = (date1, date2) => { + const d1 = new Date(date1); + const d2 = new Date(date2); + return ( + d1.getFullYear() === d2.getFullYear() && d1.getMonth() === d2.getMonth() + ); +}; + +const Row = (props) => ; + +const Month = ({ date }) => ( + + {date.toLocaleString(undefined, { month: "long", year: 'numeric' })} + +); + +const Type = ({ name }) => ( + + {name} + +); + +const Item = ({ item: { name, status } }) => ( + + {name} + {status === "ok" ? ( + + ) : ( + + )} + +); + +function App() { + const [date, setDate] = useState(new Date()); + + useEffect(() => { + document.title = data.name; + }, []); + + // month oriented structure + // month -> types -> items + const months = useMemo( + () => + // fixed to three months for now + [date, addMonths(date, 1), addMonths(date, 2)].map((m) => { + const items = data.items.filter(({ target }) => sameMonth(m, target)); + return { + date: m, + types: Array.from(new Set(items.map((i) => i.type))).map((name) => ({ + name, + items: items.filter(({ type }) => type === name), + })), + }; + }), + [date] + ); + + // normalize data + // type -> month -> items + const types = useMemo(() => { + const items = data.items.filter(({ target }) => + months.some((m) => sameMonth(m.date, target)) + ); + return Array.from(new Set(items.map((i) => i.type))).map((name) => ({ + name, + months: months.map(({ date }) => ({ + date, + items: items.filter(({ target }) => sameMonth(date, target)), + })), + })); + }, [months]); // data never changes, yet + + const previous = ( +