Skip to content

Commit

Permalink
Initial version
Browse files Browse the repository at this point in the history
  • Loading branch information
ericsoderberghp committed Jul 2, 2020
1 parent 143c0bd commit 1805871
Show file tree
Hide file tree
Showing 15 changed files with 11,539 additions and 1 deletion.
23 changes: 23 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -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*
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
# grommet-roadmap
# grommet-roadmap

A work in progress ...
37 changes: 37 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -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"
]
}
}
1 change: 1 addition & 0 deletions public/_redirects
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/* /index.html 200
19 changes: 19 additions & 0 deletions public/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/shortcut-icon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta
name="description"
content="Roadmap"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/shortcut-icon.png" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<title>Grommet Roadmap</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>
15 changes: 15 additions & 0 deletions public/manifest.json
Original file line number Diff line number Diff line change
@@ -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"
}
3 changes: 3 additions & 0 deletions public/robots.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:
Binary file added public/shortcut-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
192 changes: 192 additions & 0 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -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) => <Grid columns={["1/3", "1/3", "1/3"]} {...props} />;

const Month = ({ date }) => (
<Heading level={2} size="small">
{date.toLocaleString(undefined, { month: "long", year: 'numeric' })}
</Heading>
);

const Type = ({ name }) => (
<Heading level={3} size="small">
{name}
</Heading>
);

const Item = ({ item: { name, status } }) => (
<Box
pad="small"
background="background-front"
margin="small"
round="xsmall"
direction="row"
align="center"
justify="between"
gap="small"
>
<Text>{name}</Text>
{status === "ok" ? (
<StatusGood color="status-ok" />
) : (
<StatusWarning color="status-warning" />
)}
</Box>
);

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 = (
<Button
icon={<Previous />}
hoverIndicator
onClick={() => setDate(subtractMonths(date, 1))}
/>
);

const next = (
<Button
icon={<Next />}
hoverIndicator
onClick={() => setDate(addMonths(date, 1))}
/>
);

return (
<Grommet full theme={grommet} background="background-back">
<ResponsiveContext.Consumer>
{(responsive) => (
<Grid columns={["flex", ["small", "xlarge"], "flex"]}>
<Box />
<Box margin={{ horizontal: "large" }}>
<Box alignSelf="center">
<Heading textAlign="center" size="small">{data.name}</Heading>
</Box>
{responsive === "small" ? (
<Box>
{months.slice(0, 1).map(({ date, types }) => (
<Box>
<Header>
{previous}
<Month date={date} />
{next}
</Header>
{types.map(({ name, items }) => (
<Box>
<Type name={name} />
{items.map((item) => (
<Item key={item.name} item={item} />
))}
</Box>
))}
</Box>
))}
</Box>
) : (
<Box>
<Row>
{months.map(({ date }, index) => (
<Box direction="row" align="center" justify="between">
{index === 0 ? previous : <Box />}
<Month key={date} date={date} />
{index === months.length - 1 ? next : <Box />}
</Box>
))}
</Row>
{Object.values(types).map(({ name, months }) => (
<Box key={name}>
<Type name={name} />
<Row>
{months.map(({ date, items }) => (
<Box key={date}>
{items.map((item) => (
<Item key={item.name} item={item} />
))}
</Box>
))}
</Row>
</Box>
))}
</Box>
)}
</Box>
<Box />
</Grid>
)}
</ResponsiveContext.Consumer>
</Grommet>
);
}

export default App;
9 changes: 9 additions & 0 deletions src/App.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import React from 'react';
import { render } from '@testing-library/react';
import App from './App';

test('renders learn react link', () => {
const { getByText } = render(<App />);
const linkElement = getByText(/learn react/i);
expect(linkElement).toBeInTheDocument();
});
59 changes: 59 additions & 0 deletions src/data.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
{
"name": "HPE Design System Roadmap",
"items": [
{
"name": "Data Visualization",
"type": "templates",
"target": "2020-09-25",
"status": "ok"
},
{
"name": "Tables",
"type": "templates",
"target": "2020-08-25",
"status": "ok"
},
{
"name": "Notifications",
"type": "templates",
"target": "2020-08-25",
"status": "ok"
},
{
"name": "Accessibility",
"type": "foundation",
"target": "2020-07-25",
"status": "ok"
},
{
"name": "Figma introduction",
"type": "training",
"target": "2020-08-25",
"status": "ok"
},
{
"name": "Designer sharing",
"type": "training",
"target": "2020-07-25",
"status": "ok"
},
{
"name": "Page Layouts",
"type": "templates",
"target": "2020-07-25",
"status": "ok"
},
{
"name": "Cards",
"type": "templates",
"target": "2020-07-25",
"status": "ok"
},
{
"name": "Lists",
"type": "templates",
"target": "2020-07-25",
"status": "ok"
}
]
}
16 changes: 16 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import * as serviceWorker from './serviceWorker';

ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();
Loading

0 comments on commit 1805871

Please sign in to comment.