From edfdcca800de55a4177e4c5d2b2108920fba299b Mon Sep 17 00:00:00 2001 From: Marten Veldthuis <marten@veldthuis.com> Date: Thu, 4 Jun 2020 19:40:45 +0200 Subject: [PATCH] add initial dashboard for issues --- .vscode/launch.json | 15 ++++++ package.json | 2 + src/App.tsx | 58 +++++++-------------- src/GitlabIssues.css | 3 ++ src/GitlabIssues.tsx | 121 +++++++++++++++++++++++++++++++++++++++++++ src/Setup.tsx | 19 +++++++ yarn.lock | 5 ++ 7 files changed, 183 insertions(+), 40 deletions(-) create mode 100644 .vscode/launch.json create mode 100644 src/GitlabIssues.css create mode 100644 src/GitlabIssues.tsx create mode 100644 src/Setup.tsx diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..4ac8283 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "chrome", + "request": "launch", + "name": "Launch Chrome against localhost", + "url": "http://localhost:3001", + "webRoot": "${workspaceFolder}" + } + ] +} diff --git a/package.json b/package.json index d864e1a..1225eef 100644 --- a/package.json +++ b/package.json @@ -7,12 +7,14 @@ "@testing-library/jest-dom": "^4.2.4", "@testing-library/react": "^9.3.2", "@testing-library/user-event": "^7.1.2", + "@types/classnames": "^2.2.10", "@types/jest": "^24.0.0", "@types/node": "^12.0.0", "@types/react": "^16.9.0", "@types/react-dom": "^16.9.0", "@types/react-router-dom": "^5.1.5", "antd": "^4.3.1", + "classnames": "^2.2.6", "react": "^16.13.1", "react-dom": "^16.13.1", "react-router-dom": "^5.2.0", diff --git a/src/App.tsx b/src/App.tsx index ff89260..a31e432 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,27 +1,27 @@ import React from "react"; import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom"; -import { Button } from "antd"; +import { Button, Menu } from "antd"; import logo from "./logo.svg"; import "./App.css"; import * as gitlab from "./gitlab"; +import { GitlabIssues } from "./GitlabIssues"; +import { Setup } from "./Setup"; -function App() { +const App: React.FunctionComponent = (props) => { return ( <Router> - <div> - <nav> - <ul> - <li> - <Link to="/">Home</Link> - </li> - <li> - <Link to="/Setup">Setup</Link> - </li> - <li> - <Link to="/issues">Issues</Link> - </li> - </ul> - </nav> + <div className="app"> + <Menu mode="horizontal"> + <Menu.Item> + <Link to="/">Home</Link> + </Menu.Item> + <Menu.Item> + <Link to="/Setup">Setup</Link> + </Menu.Item> + <Menu.Item> + <Link to="/issues">Issues</Link> + </Menu.Item> + </Menu> {/* A <Switch> looks through its children <Route>s and renders the first one that matches the current URL. */} @@ -39,36 +39,14 @@ function App() { </div> </Router> ); -} +}; -function Home() { +const Home: React.FunctionComponent = () => { return ( <h2> <Button type="primary">Button</Button> </h2> ); -} - -const Setup: React.FunctionComponent = () => { - const [token, setToken] = React.useState(() => gitlab.getToken()); - const updateToken = (token: string) => { - setToken(token); - gitlab.setToken(token); - }; - - return ( - <div> - <h2>Setup</h2> - <input - value={token || ""} - onChange={(e) => updateToken(e.target.value)} - /> - </div> - ); }; -function GitlabIssues() { - return <h2>Issues</h2>; -} - export default App; diff --git a/src/GitlabIssues.css b/src/GitlabIssues.css new file mode 100644 index 0000000..f77fc9b --- /dev/null +++ b/src/GitlabIssues.css @@ -0,0 +1,3 @@ +.needsWork a:link { + color: #888; +} \ No newline at end of file diff --git a/src/GitlabIssues.tsx b/src/GitlabIssues.tsx new file mode 100644 index 0000000..5d896e6 --- /dev/null +++ b/src/GitlabIssues.tsx @@ -0,0 +1,121 @@ +import React, { useEffect, useState } from "react"; +import { Row, Col, Divider, Affix } from "antd"; +import { client } from "./gitlab"; +import classNames from "classnames"; +import "./GitlabIssues.css"; + +interface User { + id: number; + username: string; +} + +const users: User[] = [ + { id: 12, username: "marten" }, + { id: 11, username: "henk" }, + { id: 7, username: "jornvandebeek" }, + { id: 8, username: "arnold" }, +]; +const colWidth = 24 / users.length; + +export const GitlabIssues: React.FunctionComponent = () => { + return ( + <div> + <Affix> + <Row> + {users.map((user) => ( + <Col span={colWidth}>{user.username}</Col> + ))} + </Row> + </Affix> + <Divider> + <h2>MRs Ready</h2> + </Divider> + + <Row> + {users.map((user) => ( + <Col span={colWidth}> + <UserMergeRequests user={user} /> + </Col> + ))} + </Row> + + <Divider> + <h2>Issues Assigned</h2> + </Divider> + + <Row> + {users.map((user) => ( + <Col span={colWidth}> + <UserIssues user={user} /> + </Col> + ))} + </Row> + </div> + ); +}; + +const UserMergeRequests: React.FunctionComponent<{ user: User }> = ({ + user, +}) => { + const [issues, setIssues] = useState<any>([]); + + useEffect(() => { + const fetchResults = async () => { + const result = await client.MergeRequests.all({ + groupId: 6, + state: "opened", + wip: "no", + authorId: user.id, + scope: "all", + maxPages: 2, + }); + setIssues(result); + }; + fetchResults(); + }, []); + + return ( + <div> + <ul> + {issues.map((issue: any) => ( + <li + className={classNames({ + needsWork: !issue.blocking_discussions_resolved, + })} + > + <a href={issue.web_url}>{issue.title}</a> + </li> + ))} + </ul> + </div> + ); +}; + +const UserIssues: React.FunctionComponent<{ user: User }> = ({ user }) => { + const [issues, setIssues] = useState<any>([]); + + useEffect(() => { + const fetchResults = async () => { + const result = await client.Issues.all({ + assigneeId: user.id, + scope: "all", + state: "opened", + }); + console.log(result); + setIssues(result); + }; + fetchResults(); + }, []); + + return ( + <div> + <ul> + {issues.map((issue: any) => ( + <li> + <a href={issue.web_url}>{issue.title}</a> + </li> + ))} + </ul> + </div> + ); +}; diff --git a/src/Setup.tsx b/src/Setup.tsx new file mode 100644 index 0000000..d7104c8 --- /dev/null +++ b/src/Setup.tsx @@ -0,0 +1,19 @@ +import React from "react"; +import * as gitlab from "./gitlab"; + +export const Setup: React.FunctionComponent = () => { + const [token, setToken] = React.useState(() => gitlab.getToken()); + const updateToken = (token: string) => { + setToken(token); + gitlab.setToken(token); + }; + return ( + <div> + <h2>Setup</h2> + <input + value={token || ""} + onChange={(e) => updateToken(e.target.value)} + /> + </div> + ); +}; diff --git a/yarn.lock b/yarn.lock index 5759f80..23ec1de 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1549,6 +1549,11 @@ dependencies: "@babel/types" "^7.3.0" +"@types/classnames@^2.2.10": + version "2.2.10" + resolved "https://registry.yarnpkg.com/@types/classnames/-/classnames-2.2.10.tgz#cc658ca319b6355399efc1f5b9e818f1a24bf999" + integrity sha512-1UzDldn9GfYYEsWWnn/P4wkTlkZDH7lDb0wBMGbtIQc9zXEQq7FlKBdZUn6OBqD8sKZZ2RQO2mAjGpXiDGoRmQ== + "@types/color-name@^1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" -- GitLab