From a9b3c9cafac5215fa54914537d2df29421deb18e Mon Sep 17 00:00:00 2001 From: Martin Wittlinger Date: Sat, 22 Jul 2023 16:35:57 +0200 Subject: [PATCH] feat(react): Change dashboard UI to new table (#876) --- .github/workflows/docker-publish.yml | 6 +- frontend/.prettierrc.json | 6 + frontend/package-lock.json | 35 +++- frontend/package.json | 7 +- frontend/src/Keycloak.tsx | 10 +- frontend/src/PrivateRoute.tsx | 23 ++- frontend/src/ProjectData.tsx | 115 +++++++----- frontend/src/component/AddProjectCard.tsx | 20 ++- frontend/src/component/BadSmellList.tsx | 152 +++++++++++----- frontend/src/component/BadSmellTree.tsx | 176 ++++++++++++------ frontend/src/component/DashBoardCard.tsx | 43 +++-- frontend/src/component/DashBoardItem.tsx | 56 +++--- frontend/src/component/HashSelector.tsx | 28 ++- frontend/src/component/Headline.tsx | 17 +- frontend/src/component/JavaCodeBlock.tsx | 12 +- frontend/src/component/LoginButton.tsx | 16 +- frontend/src/component/ProjectCard.tsx | 98 ++++++---- frontend/src/component/ProjectList.tsx | 28 +-- frontend/src/component/ProjectTable.tsx | 186 +++++++++++++++++++ frontend/src/component/StyledDivider.tsx | 19 +- frontend/src/data/AnalyzerStatus.tsx | 9 + frontend/src/data/BadSmell.tsx | 20 +-- frontend/src/data/GitHubCommit.tsx | 6 + frontend/src/data/Position.tsx | 14 +- frontend/src/data/Project.tsx | 5 +- frontend/src/data/ProjectConfig.tsx | 6 +- frontend/src/data/RuleID.tsx | 4 +- frontend/src/index.tsx | 74 ++++---- frontend/src/pages/Aboutpage.tsx | 8 +- frontend/src/pages/AddProjectView.tsx | 105 ++++++----- frontend/src/pages/DashBoard.tsx | 52 +++--- frontend/src/pages/LandingPage.tsx | 8 +- frontend/src/pages/PageLayout.tsx | 70 +++++--- frontend/src/pages/ProjectConfigView.tsx | 42 +++-- frontend/src/pages/RefactorView.tsx | 206 +++++++++++++++------- frontend/src/pages/Resultview.tsx | 161 +++++++++-------- frontend/src/pages/StatisticsPage.tsx | 63 ++++--- frontend/src/styled/FancyText.tsx | 12 +- 38 files changed, 1288 insertions(+), 630 deletions(-) create mode 100644 frontend/.prettierrc.json create mode 100644 frontend/src/component/ProjectTable.tsx create mode 100644 frontend/src/data/AnalyzerStatus.tsx create mode 100644 frontend/src/data/GitHubCommit.tsx diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 91f29ceb1..0d155c639 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -40,6 +40,10 @@ jobs: uses: gradle/gradle-build-action@915a66c096a03101667f9df2e56c9efef558b165 # v2 with: gradle-version: release-candidate + - name: Setup Node.js + uses: actions/setup-node@v2 + with: + node-version: '18.4' - uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3 with: distribution: 'temurin' @@ -53,7 +57,7 @@ jobs: cosign-release: 'v1.13.1' # Build Quarkus - name: Build - run: cd ./github-bot/ && gradle assemble + run: cd ./github-bot/ && gradle assemble --stacktrace --info # Workaround: https://github.com/docker/build-push-action/issues/461 - name: Setup Docker buildx uses: docker/setup-buildx-action@4c0219f9ac95b02789c1075625400b2acbff50b1 diff --git a/frontend/.prettierrc.json b/frontend/.prettierrc.json new file mode 100644 index 000000000..1dc716459 --- /dev/null +++ b/frontend/.prettierrc.json @@ -0,0 +1,6 @@ +{ + "trailingComma": "es5", + "tabWidth": 2, + "semi": true, + "singleQuote": true +} \ No newline at end of file diff --git a/frontend/package-lock.json b/frontend/package-lock.json index a706f34fc..18d6a99a1 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -11,6 +11,7 @@ "@apollo/client": "3.7.17", "@emotion/react": "11.11.1", "@emotion/styled": "11.11.0", + "@js-joda/core": "^5.5.3", "@mui/icons-material": "5.14.1", "@mui/lab": "5.0.0-alpha.137", "@mui/material": "5.14.1", @@ -38,7 +39,8 @@ "web-vitals": "3.4.0" }, "devDependencies": { - "@types/babel__core": "^7.1.20" + "@types/babel__core": "^7.1.20", + "prettier": "^3.0.0" } }, "node_modules/@adobe/css-tools": { @@ -3804,6 +3806,11 @@ "@jridgewell/sourcemap-codec": "1.4.14" } }, + "node_modules/@js-joda/core": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/@js-joda/core/-/core-5.5.3.tgz", + "integrity": "sha512-7dqNYwG8gCt4hfg5PKgM7xLEcgSBcx/UgC92OMnhMmvAnq11QzDFPrxUkNR/u5kn17WWLZ8beZ4A3Qrz4pZcmQ==" + }, "node_modules/@leichtgewicht/ip-codec": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", @@ -17274,6 +17281,21 @@ "node": ">= 0.8.0" } }, + "node_modules/prettier": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.0.tgz", + "integrity": "sha512-zBf5eHpwHOGPC47h0zrPyNn+eAEIdEzfywMoYn2XPi0P44Zp0tSq64rq0xAREh4auw2cJZHo9QUob+NqCQky4g==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/pretty-bytes": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", @@ -23649,6 +23671,11 @@ "@jridgewell/sourcemap-codec": "1.4.14" } }, + "@js-joda/core": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/@js-joda/core/-/core-5.5.3.tgz", + "integrity": "sha512-7dqNYwG8gCt4hfg5PKgM7xLEcgSBcx/UgC92OMnhMmvAnq11QzDFPrxUkNR/u5kn17WWLZ8beZ4A3Qrz4pZcmQ==" + }, "@leichtgewicht/ip-codec": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", @@ -33151,6 +33178,12 @@ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==" }, + "prettier": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.0.tgz", + "integrity": "sha512-zBf5eHpwHOGPC47h0zrPyNn+eAEIdEzfywMoYn2XPi0P44Zp0tSq64rq0xAREh4auw2cJZHo9QUob+NqCQky4g==", + "dev": true + }, "pretty-bytes": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index fc5cf0fd1..1757a4254 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -6,6 +6,7 @@ "@apollo/client": "3.7.17", "@emotion/react": "11.11.1", "@emotion/styled": "11.11.0", + "@js-joda/core": "^5.5.3", "@mui/icons-material": "5.14.1", "@mui/lab": "5.0.0-alpha.137", "@mui/material": "5.14.1", @@ -36,7 +37,8 @@ "start": "react-scripts --openssl-legacy-provider start", "build": "react-scripts build", "test": "react-scripts test", - "eject": "react-scripts eject" + "eject": "react-scripts eject", + "prettier": "prettier --write \"src/**/*.tsx\"" }, "eslintConfig": { "extends": [ @@ -57,6 +59,7 @@ ] }, "devDependencies": { - "@types/babel__core": "^7.1.20" + "@types/babel__core": "^7.1.20", + "prettier": "^3.0.0" } } diff --git a/frontend/src/Keycloak.tsx b/frontend/src/Keycloak.tsx index 2c35405d2..04fd25d11 100644 --- a/frontend/src/Keycloak.tsx +++ b/frontend/src/Keycloak.tsx @@ -1,8 +1,8 @@ -import Keycloak from "keycloak-js"; +import Keycloak from 'keycloak-js'; const keycloak = new Keycloak({ - url: "https://auth.keksdose.xyz", - realm: "laughing-train", - clientId: "laughing-train", + url: 'https://auth.keksdose.xyz', + realm: 'laughing-train', + clientId: 'laughing-train', }); -export default keycloak; \ No newline at end of file +export default keycloak; diff --git a/frontend/src/PrivateRoute.tsx b/frontend/src/PrivateRoute.tsx index 475558b8a..00972c847 100644 --- a/frontend/src/PrivateRoute.tsx +++ b/frontend/src/PrivateRoute.tsx @@ -1,13 +1,22 @@ -import { Alert, Typography } from "@mui/material"; -import { useKeycloak } from "@react-keycloak/web"; +import { Alert, Typography } from '@mui/material'; +import { useKeycloak } from '@react-keycloak/web'; -const PrivateRoute = (child: any ) => { +const PrivateRoute = (child: any) => { const { keycloak } = useKeycloak(); const isLoggedIn = keycloak.authenticated; - return isLoggedIn ? child.children : <> - You are not logged in. Please log in to access this page. - ; + return isLoggedIn ? ( + child.children + ) : ( + <> + + {' '} + + You are not logged in. Please log in to access this page. + + + + ); }; -export default PrivateRoute; \ No newline at end of file +export default PrivateRoute; diff --git a/frontend/src/ProjectData.tsx b/frontend/src/ProjectData.tsx index 2c9e4693f..cb146e85e 100644 --- a/frontend/src/ProjectData.tsx +++ b/frontend/src/ProjectData.tsx @@ -1,64 +1,70 @@ -import { gql} from '@apollo/client'; +import { gql } from '@apollo/client'; import { BadSmell } from './data/BadSmell'; import { Project } from './data/Project'; - - - - export const fetchProjectQuery = gql` query getProjects { - getProjects { - projectName - projectUrl - commitHashes - } -} + getProjects { + projectName + projectUrl + commitHashes + commits { + analyzerStatuses { + analyzerName + commitHash + localDateTime + numberOfIssues + status + } + commitHash + } + } + } `; export const fetchAvailableRefactorings = gql` query getAvailableRefactorings { - availableRefactorings { - ruleId { - id + availableRefactorings { + ruleId { + id + } } - } -} + } `; export const fetchBadSmellsforHashQuery = gql` query getBadSmellsForHash($hash: String) { - byCommitHash(commitHash: $hash) { - identifier - ruleID - messageMarkdown - snippet - filePath - position { - startLine + byCommitHash(commitHash: $hash) { + identifier + ruleID + messageMarkdown + snippet + filePath + position { + startLine + } } } -} `; export const addprojectQuery = gql` mutation addProject($projectName: String!, $projectUrl: String!) { - addProject(projectName: $projectName, projectUrl: $projectUrl) { - projectName - projectUrl + addProject(projectName: $projectName, projectUrl: $projectUrl) { + projectName + projectUrl + } } -} `; export const refactorQuery = gql` mutation refactor($badSmellIdentifier: [String]) { - refactor(badSmellIdentifier: $badSmellIdentifier) -} + refactor(badSmellIdentifier: $badSmellIdentifier) + } `; export const loginQuery = gql` - query login($notNeeded : String) { - login(notNeeded : $notNeeded) -} + query login($notNeeded: String) { + login(notNeeded: $notNeeded) + } `; -export function filterDuplicates(params:Project[]) { +export function filterDuplicates(params: Project[]) { return params; } export function filterDuplicateBadSmells(params: BadSmell[]) { @@ -68,24 +74,41 @@ export function filterDuplicateBadSmells(params: BadSmell[]) { params = params.filter((badSmell) => { return badSmell.snippet != null; }); - const ids = params.map(o => o.snippet) - const filtered = params.filter(({ snippet }, index) => !ids.includes(snippet, index + 1)); + const ids = params.map((o) => o.snippet); + const filtered = params.filter( + ({ snippet }, index) => !ids.includes(snippet, index + 1) + ); return filtered; } export const fetchProjectConfigQuery = gql` query getProjectConfig($projectUrl: String!) { - getProjectConfig(projectUrl: $projectUrl) { - projectUrl - sourceFolder + getProjectConfig(projectUrl: $projectUrl) { + projectUrl + sourceFolder + } } -} `; export const addProjectConfigQuery = gql` mutation addProjectConfig($projectConfig: ProjectConfig!) { - addProjectConfig(projectConfig: $projectConfig) { - projectUrl - sourceFolder + addProjectConfig(projectConfig: $projectConfig) { + projectUrl + sourceFolder + } } -} -`; \ No newline at end of file +`; + +export const getGitHubCommitsQuery = gql` + query getGitHubCommitsForProject($projectName: String!) { + getGitHubCommitsForProject(projectName: $projectName) { + analyzerStatuses { + analyzerName + commitHash + localDateTime + numberOfIssues + status + } + commitHash + } + } +`; diff --git a/frontend/src/component/AddProjectCard.tsx b/frontend/src/component/AddProjectCard.tsx index f102a56d9..8567a3f61 100644 --- a/frontend/src/component/AddProjectCard.tsx +++ b/frontend/src/component/AddProjectCard.tsx @@ -1,16 +1,24 @@ -import { Card, CardMedia, Typography } from "@mui/material"; -import React from "react"; -import { BiPlus } from "react-icons/bi"; -import { useNavigate } from "react-router"; +import { Card, CardMedia, Typography } from '@mui/material'; +import React from 'react'; +import { BiPlus } from 'react-icons/bi'; +import { useNavigate } from 'react-router'; export function AddProjectCard() { const navigate = useNavigate(); return ( - navigate("/mutation/addproject")} sx={{ display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center" }}> + navigate('/mutation/addproject')} + sx={{ + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + justifyContent: 'center', + }} + > Add Project ); -} \ No newline at end of file +} diff --git a/frontend/src/component/BadSmellList.tsx b/frontend/src/component/BadSmellList.tsx index 113df8802..5e47ad7ee 100644 --- a/frontend/src/component/BadSmellList.tsx +++ b/frontend/src/component/BadSmellList.tsx @@ -1,22 +1,30 @@ - import { useQuery } from '@apollo/client'; -import { Accordion, AccordionDetails, AccordionSummary, Box, Card, CircularProgress, Divider, Link, Stack, Typography } from '@mui/material'; +import { + Accordion, + AccordionDetails, + AccordionSummary, + Box, + Card, + CircularProgress, + Divider, + Link, + Stack, + Typography, +} from '@mui/material'; import { BadSmell } from '../data/BadSmell'; -import { Project } from "../data/Project"; +import { Project } from '../data/Project'; import { fetchBadSmellsforHashQuery } from '../ProjectData'; import JavaCodeBlock from './JavaCodeBlock'; import React, { useMemo, useState } from 'react'; import { StyledDivider } from './StyledDivider'; - - export default function BadSmellList(project: Project) { - const [badSmellFilter] = useState([""]); + const [badSmellFilter] = useState(['']); const { data, error, loading } = useQuery(fetchBadSmellsforHashQuery, { variables: { - hash: project.commitHashes[0] - } + hash: project.commitHashes[0], + }, }); const filteredBadSmells = useMemo(() => { if (!data) { @@ -36,52 +44,69 @@ export default function BadSmellList(project: Project) { console.error(error); } if (loading) { - return + return ; } return (
- Bad Smells + + Bad Smells +
- - + + - +
); } - -function BadSmellBlocks({ badSmells, project }: { badSmells: BadSmell[]; project: Project }) { - return <> - {CodeBlocks(badSmells, project)} - +function BadSmellBlocks({ + badSmells, + project, +}: { + badSmells: BadSmell[]; + project: Project; +}) { + return <>{CodeBlocks(badSmells, project)}; } function CodeBlocks(params: BadSmell[], project: Project) { return Array.from(groupByRuleID(params)).map((badSmell) => { return (
- - {badSmell[0]} {badSmell[1].length} + + + {badSmell[0]} {badSmell[1].length} + - - + + {badSmell[1].map((badSmell) => { return ( - - - {badSmell.messageMarkdown} + + + + {badSmell.messageMarkdown} + - + ); })} @@ -89,14 +114,20 @@ function CodeBlocks(params: BadSmell[], project: Project) {
- ) + ); }); } - function createGithubLink(badSmell: BadSmell, project: Project) { - return project.projectUrl + "/tree/" + project.commitHashes[0] + "/" + badSmell.filePath + "#L" + badSmell.position.startLine; - + return ( + project.projectUrl + + '/tree/' + + project.commitHashes[0] + + '/' + + badSmell.filePath + + '#L' + + badSmell.position.startLine + ); } function groupByRuleID(projects: BadSmell[]): Map { @@ -114,22 +145,45 @@ function groupByRuleID(projects: BadSmell[]): Map { } function BadSmellCardHeader(badSmell: BadSmell) { - return (<> - - {badSmell.ruleID} - {badSmell.identifier} - - ); + return ( + <> + + + {badSmell.ruleID} + + + {badSmell.identifier} + + + + ); } -function BadSmellCardFooter({ badSmell, project }: { badSmell: BadSmell; project: Project; }) { - return (<> - - In file {badSmell.filePath} at line {badSmell.position.startLine} - {GitHubLink(badSmell, project)} - ); +function BadSmellCardFooter({ + badSmell, + project, +}: { + badSmell: BadSmell; + project: Project; +}) { + return ( + <> + + + In file {badSmell.filePath} at line {badSmell.position.startLine} + + {GitHubLink(badSmell, project)} + + ); } function GitHubLink(badSmell: BadSmell, project: Project) { - return See on GitHub; + return ( + + See on GitHub + + ); } - diff --git a/frontend/src/component/BadSmellTree.tsx b/frontend/src/component/BadSmellTree.tsx index 4d6ba8006..d732a190f 100644 --- a/frontend/src/component/BadSmellTree.tsx +++ b/frontend/src/component/BadSmellTree.tsx @@ -1,24 +1,36 @@ -import { Box, Button, Card, CardActionArea, Divider, Stack, Typography } from "@mui/material"; -import React from "react"; -import { BadSmell } from "../data/BadSmell"; +import { + Box, + Button, + Card, + CardActionArea, + Divider, + Stack, + Typography, +} from '@mui/material'; +import React from 'react'; +import { BadSmell } from '../data/BadSmell'; import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; import ChevronRightIcon from '@mui/icons-material/ChevronRight'; import TreeView from '@mui/lab/TreeView'; import TreeItem from '@mui/lab/TreeItem'; -import JavaCodeBlock from "./JavaCodeBlock"; +import JavaCodeBlock from './JavaCodeBlock'; -export function BadSmellTreeView({ badSmell, selector }: { badSmell: BadSmell[]; selector: (selected: [string]) => void; }) { +export function BadSmellTreeView({ + badSmell, + selector, +}: { + badSmell: BadSmell[]; + selector: (selected: [string]) => void; +}) { const [expanded, setExpanded] = React.useState([]); const handleToggle = (event: React.SyntheticEvent, nodeIds: string[]) => { setExpanded(nodeIds); }; - - const handleExpandClick = () => { setExpanded((oldExpanded) => - oldExpanded.length === 0 ? ['1', '5', '6', '7'] : [], + oldExpanded.length === 0 ? ['1', '5', '6', '7'] : [] ); }; @@ -37,22 +49,38 @@ export function BadSmellTreeView({ badSmell, selector }: { badSmell: BadSmell[]; onNodeToggle={handleToggle} multiSelect > - {convertBadSmellToTree(badSmell).map((temp) => printChildren(temp, selector))} + {convertBadSmellToTree(badSmell).map((temp) => + printChildren(temp, selector) + )} ); } -function printChildren(node: TreeNode, setSelected : (selected: [string]) => void) { +function printChildren( + node: TreeNode, + setSelected: (selected: [string]) => void +) { if (node.children.length === 0) { - return - {CodeBlocks(node.badSmell, setSelected)} - + return ( + + {CodeBlocks(node.badSmell, setSelected)} + + ); } else { - return - {node.children.map((child) => printChildren(child, setSelected))} + return ( + + {node.children.map((child) => printChildren(child, setSelected))} + ); } - } type TreeNode = { @@ -60,70 +88,102 @@ type TreeNode = { label: string; children: TreeNode[]; badSmell: BadSmell[]; -} +}; // convert an array of badsmell with filePath to a filetree. Each node has his foldername as name and upper folders as parent. function convertBadSmellToTree(badSmell: BadSmell[]): TreeNode[] { const result: TreeNode[] = []; badSmell.forEach((badSmell) => { const filePath = badSmell.filePath; - const folders = filePath.split("/"); + const folders = filePath.split('/'); for (let index = 0; index < folders.length; index++) { const element = folders[index]; - const parent = index === 0 ? "" : folders.slice(0, index).join("/"); - if (!result.some((temp) => temp.parent === parent && temp.label === element)) { - result.push({ parent: parent, label: element, children: [], badSmell: [] }); + const parent = index === 0 ? '' : folders.slice(0, index).join('/'); + if ( + !result.some((temp) => temp.parent === parent && temp.label === element) + ) { + result.push({ + parent: parent, + label: element, + children: [], + badSmell: [], + }); } } }); result.forEach((temp) => { - result.find((temp2) => temp2.parent + "/" + temp2.label === temp.parent)?.children.push(temp); + result + .find((temp2) => temp2.parent + '/' + temp2.label === temp.parent) + ?.children.push(temp); result.find((temp2) => temp2.label === temp.parent)?.children.push(temp); }); badSmell.forEach((badSmell) => { const filePath = badSmell.filePath; - result.find((temp) => temp.parent + "/" + temp.label === filePath)?.badSmell.push(badSmell); + result + .find((temp) => temp.parent + '/' + temp.label === filePath) + ?.badSmell.push(badSmell); }); - return result.filter((temp) => temp.parent === ""); - + return result.filter((temp) => temp.parent === ''); } -function CodeBlocks(params: BadSmell[], setSelected: (selected: [string]) => void) { - return ( -
- - {params.map((badSmell) => { - return ( - - setSelected([badSmell.identifier])}> - - {badSmell.messageMarkdown} - - - - - ); - })} - -
- ); +function CodeBlocks( + params: BadSmell[], + setSelected: (selected: [string]) => void +) { + return ( +
+ + {params.map((badSmell) => { + return ( + + setSelected([badSmell.identifier])} + > + + + {badSmell.messageMarkdown} + + + + + + ); + })} + +
+ ); } function BadSmellCardHeader(badSmell: BadSmell) { - return (<> - - {badSmell.ruleID} - {badSmell.identifier} - ); + return ( + <> + + + {badSmell.ruleID} + + + {badSmell.identifier} + + {' '} + + ); } function BlackDivider() { - return (); + return ( + + ); } function OrangeDivider() { - return ; + return ; } diff --git a/frontend/src/component/DashBoardCard.tsx b/frontend/src/component/DashBoardCard.tsx index 6999cfa87..f75ca6d1c 100644 --- a/frontend/src/component/DashBoardCard.tsx +++ b/frontend/src/component/DashBoardCard.tsx @@ -1,22 +1,37 @@ -import { CardActionArea, Card, CardMedia, CardContent, Typography } from "@mui/material"; -import Avatar from "react-avatar"; -import { Project } from "../data/Project"; -import React from "react"; -import { useNavigate } from "react-router"; +import { + CardActionArea, + Card, + CardMedia, + CardContent, + Typography, +} from '@mui/material'; +import Avatar from 'react-avatar'; +import { Project } from '../data/Project'; +import React from 'react'; +import { useNavigate } from 'react-router'; export function DashBoardCard(project: Project) { const navigate = useNavigate(); return ( navigate(toLink(project))}> - + - - + + {project.projectName} - {urlToGitHubHandle(project.projectUrl)} + + {urlToGitHubHandle(project.projectUrl)} + @@ -24,13 +39,13 @@ export function DashBoardCard(project: Project) { } function urlToGitHubHandle(params: string) { if (params === undefined) { - return ""; + return ''; } - let url = params.split("/"); + let url = params.split('/'); // the first pop return the projectname - url.pop() + url.pop(); return url.pop(); } function toLink(project: Project): string { - return "/resultview/" + project.projectName; -} \ No newline at end of file + return '/resultview/' + project.projectName; +} diff --git a/frontend/src/component/DashBoardItem.tsx b/frontend/src/component/DashBoardItem.tsx index 9b8af593a..3299f0e16 100644 --- a/frontend/src/component/DashBoardItem.tsx +++ b/frontend/src/component/DashBoardItem.tsx @@ -1,36 +1,44 @@ -import { Card, CardActionArea, Typography } from "@mui/material"; -import { Box } from "@mui/system"; -import Avatar from "react-avatar"; -import { useNavigate } from "react-router"; -import { Project } from "../data/Project"; +import { Card, CardActionArea, Typography } from '@mui/material'; +import { Box } from '@mui/system'; +import Avatar from 'react-avatar'; +import { useNavigate } from 'react-router'; +import { Project } from '../data/Project'; function DashBoardItem(project: Project) { const navigate = useNavigate(); - return <> - - navigate(toLink(project))}> - - - {project.projectName} - {project.projectUrl} - - - {project.commitHashes.length} Commits - - - - + return ( + <> + + navigate(toLink(project))}> + + + + {project.projectName}{' '} + + + {project.projectUrl}{' '} + + + + + {project.commitHashes.length} Commits + + + + + + ); } function toLink(project: Project): string { - return "/resultview/" + project.projectName; + return '/resultview/' + project.projectName; } function urlToGitHubHandle(params: string) { if (params === undefined) { - return ""; + return ''; } - let url = params.split("/"); + let url = params.split('/'); // the first pop return the projectname - url.pop() + url.pop(); return url.pop(); } -export default DashBoardItem; \ No newline at end of file +export default DashBoardItem; diff --git a/frontend/src/component/HashSelector.tsx b/frontend/src/component/HashSelector.tsx index 4f82132a6..2809f7567 100644 --- a/frontend/src/component/HashSelector.tsx +++ b/frontend/src/component/HashSelector.tsx @@ -1,7 +1,14 @@ -import { Button, FormControl, InputLabel, MenuItem, Select, Typography } from "@mui/material"; -import React, { useState } from "react"; -import { useNavigate } from "react-router"; -import { Project } from "../data/Project"; +import { + Button, + FormControl, + InputLabel, + MenuItem, + Select, + Typography, +} from '@mui/material'; +import React, { useState } from 'react'; +import { useNavigate } from 'react-router'; +import { Project } from '../data/Project'; function HashSelector(project: Project) { const navigate = useNavigate(); @@ -12,7 +19,9 @@ function HashSelector(project: Project) { Choose a hash to view the results
- + Commit Hash