Skip to content
Snippets Groups Projects
Commit 7e7064f5 authored by Carl Valdemar Ebbesen's avatar Carl Valdemar Ebbesen
Browse files

fix overview page

parent 45c7968a
No related branches found
No related tags found
No related merge requests found
...@@ -15,13 +15,13 @@ function App() { ...@@ -15,13 +15,13 @@ function App() {
<LandingPage/> <LandingPage/>
</Route> </Route>
<Route exact path={"/overview"}> <Route exact path={"/overview"}>
<OverviewPage buttons={["commits","Issues"]} links={["/commits","/issues"]}/> <OverviewPage/>
</Route> </Route>
<Route exact path={"/issues"}> <Route exact path={"/issue"}>
<OverviewPage buttons={["list","graphs"]} links={["/issuelist","/issuegraph"]}/> <OverviewPage/>
</Route> </Route>
<Route exact path={"/commits"}> <Route exact path={"/commit"}>
<OverviewPage buttons={["list","graphs"]} links={["/commitlist","/commitgraph"]}/> <OverviewPage/>
</Route> </Route>
<Route exact path={"/issuelist"}> <Route exact path={"/issuelist"}>
<IssuePage/> <IssuePage/>
......
src/assets/gitlab.jpeg

378 KiB

import axios from "axios";
const projectId = localStorage.getItem("projectId") ?? "11916"
const apiKey = localStorage.getItem("key") ?? "r74NY2kS_LprPFEobZxi";
const instance = axios.create({
baseURL: `https://gitlab.stud.idi.ntnu.no/api/v4/projects/${projectId}`,
headers: {"Authorization": `Bearer ${apiKey}`, "content_type":"application/json"},
})
export default instance;
\ No newline at end of file
.wrapper {
display: flex;
flex-direction: column;
align-items: center;
border-radius: 16px;
background-color: lightslategray;
padding: 15px;
}
\ No newline at end of file
import React from 'react';
import style from "./stats.module.css";
interface StatsBoxProps {
content: string[]
}
const StatsBox: React.FC<StatsBoxProps> = ({content }) => {
return (
<div className={style.wrapper}>
{content.map(element => <p key={element} style={{margin: "10px auto", padding: "10px auto"}}>{element}</p>)}
</div>
);
};
export default StatsBox;
\ No newline at end of file
body { body {
background-color: #e1f0f6; background-color: #e1f0f6;
font-family: Epilogue; font-family: Epilogue;
font-size: 2.5vw;
} }
.container { .container {
......
...@@ -8,7 +8,6 @@ import ClipLoader from "react-spinners/ClipLoader"; ...@@ -8,7 +8,6 @@ import ClipLoader from "react-spinners/ClipLoader";
const IssuePage = () => { const IssuePage = () => {
const {isLoading, error, data} = useGitlabApi(queryTypes.AllIssues) const {isLoading, error, data} = useGitlabApi(queryTypes.AllIssues)
console.log(data)
return ( return (
<div className={styles.container}> <div className={styles.container}>
<h1 className={styles.headline}> Issues </h1> <h1 className={styles.headline}> Issues </h1>
......
button{
width: 20%;
}
input{ .inputField{
width: 75%; width: 50%;
padding: 10px 15px; height: 30px;
margin-bottom: 10px; margin: 10px auto;
} }
.inputWrapper{ .inputWrapper{
position: absolute; width: 70%;
width: 400px; margin-left: 15%;
height: 300px; display: flex;
z-index: 15; flex-direction: column;
top: 50%;
left: 50%;
margin: -100px 0 0 -200px;
text-align: center;
} }
form { form {
margin-top: 50px; display: flex;
display: inline-block; flex-direction: column;
} }
.defaultButton { .defaultButton {
position: absolute; margin: auto;
top: 0; padding: 5px;
right: 0; cursor: pointer;
}
.submitButton {
background-color: lightgreen;
padding: 5px;
margin: auto;
cursor: pointer;
} }
\ No newline at end of file
import React, {FC, useEffect, useState} from "react" import React, { useEffect, useState} from "react"
import style from './landingPage.module.css'; import style from './landingPage.module.css';
import {useHistory} from 'react-router-dom'; import {useHistory} from 'react-router-dom';
import 'react-toastify/dist/ReactToastify.css'; import 'react-toastify/dist/ReactToastify.css';
...@@ -6,6 +6,7 @@ import { ToastContainer, toast } from 'react-toastify'; ...@@ -6,6 +6,7 @@ import { ToastContainer, toast } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css'; import 'react-toastify/dist/ReactToastify.css';
import { ConnectionTest, queryTypes } from "../../utils/queryType"; import { ConnectionTest, queryTypes } from "../../utils/queryType";
import { useGitlabApi } from "../../utils/gitlab_api_service"; import { useGitlabApi } from "../../utils/gitlab_api_service";
import visualization from "../../assets/gitlab.jpeg";
const LandingPage = () => { const LandingPage = () => {
...@@ -13,17 +14,18 @@ const LandingPage = () => { ...@@ -13,17 +14,18 @@ const LandingPage = () => {
const [key, setKey] = useState<string>(localStorage.getItem("key") ?? ""); const [key, setKey] = useState<string>(localStorage.getItem("key") ?? "");
const [projectId, setProjectId] = useState<string>(localStorage.getItem("projectId") ?? ""); const [projectId, setProjectId] = useState<string>(localStorage.getItem("projectId") ?? "");
const [query,setQuery] = useState<queryTypes>() const [query,setQuery] = useState<queryTypes>()
const {data,error} = useGitlabApi(query) const {data, isLoading,error} = useGitlabApi(query)
const [disableButton, setDisableButton] = useState<boolean>(true);
const toast_response = (type:string) => { const toast_response = (type:string) => {
if(type === "info"){ if(type === "info"){
toast.info("Trying to reieve repository data"); toast.info("Checking if key and projectId is correct");
} }
else if (type==="success") { else if (type==="success") {
toast.success("Repository data recieved!"); toast.success("Success! Found the repository");
} }
else { else {
toast.error("Could not get repository data. Try again"); toast.error("Could not find repository or wrong key. Try again");
} }
} }
...@@ -31,35 +33,52 @@ const LandingPage = () => { ...@@ -31,35 +33,52 @@ const LandingPage = () => {
localStorage.clear(); localStorage.clear();
history.push("/overview"); history.push("/overview");
} }
useEffect(()=>{
if(!(projectId && key)) return;
const timer = setTimeout(()=>{
setDisableButton(true)
localStorage.setItem("projectId", projectId);
localStorage.setItem("key", key);
toast_response("info")
setQuery(queryTypes.Access);
}, 300)
return () =>{
setQuery(undefined);
clearTimeout(timer);
}
}, [key, projectId]);
useEffect(() => { useEffect(() => {
if(!error && query) { if(!isLoading){
console.log(error)
if(error){
toast_response("error") toast_response("error")
setQuery(undefined)
} }
if(data as ConnectionTest && query) { else if(data as ConnectionTest) {
toast_response("success") toast_response("success")
history.push("/overview") setDisableButton(false);
} }
}, [data, error, history, query]); }
}, [data, error, isLoading]);
function handleSubmit(event: { preventDefault: () => void; }) { function handleSubmit(event: { preventDefault: () => void; }) {
event.preventDefault() event.preventDefault()
if (projectId && key) { history.push("/overview")
setQuery(queryTypes.Access) }
toast_response("info")
localStorage.setItem("projectId", projectId);
localStorage.setItem("key", key);
}}
return ( return (
<div className={style.inputWrapper}> <div className={style.inputWrapper}>
<img alt="visualization" src={visualization} style={{width: "80%", margin: "30px auto" }}/>
<button className={style.defaultButton} onClick={()=> setDefaultValues()}>set default values</button> <button className={style.defaultButton} onClick={()=> setDefaultValues()}>set default values</button>
<form onSubmit={handleSubmit}> <form onSubmit={handleSubmit}>
<input value = {projectId} type="Text" onChange={e => setProjectId(e.target.value)} id="ProjektIDInput" <input className={style.inputField} value = {projectId} type="Text" onChange={e => setProjectId(e.target.value)} id="ProjektIDInput"
placeholder="ProjectId" required/> placeholder="ProjectId" required/>
<input value = {key} type="Text" onChange={e => setKey(e.target.value)} id="KeyInput" <input className={style.inputField} value = {key} type="Text" onChange={e => setKey(e.target.value)} id="KeyInput"
placeholder="Key" required/> placeholder="Key" required/>
<button type="submit">GO!</button> <button className={style.submitButton} type="submit" disabled={disableButton}>Use values</button>
<ToastContainer /> <ToastContainer autoClose={3000} />
</form> </form>
</div> </div>
......
import React, {FC} from "react"
import {useHistory} from 'react-router-dom';
import style from './overview.module.css'; import style from './overview.module.css';
import React, { useState, useEffect } from 'react';
import { useHistory } from 'react-router';
import { useGitlabApi } from '../../utils/gitlab_api_service';
import { Languages, queryTypes } from '../../utils/queryType';
import StatsBox from '../../components/stats/statsBox';
import { ClipLoader } from 'react-spinners';
import { toast, ToastContainer } from 'react-toastify';
const OverviewPage = () => {
const slug = window.location.pathname;
const history = useHistory();
const {data, isLoading, error } = useGitlabApi(queryTypes.Languages);
interface IOverviewPage {
buttons: string[]
links: string[]
}
interface IButton {
name: string
link: string
}
const Button: FC<IButton> = (props) => {
let history = useHistory()
function handleClick() {
history.push(props.link)
}
return ( return (
<div className={style.button} onClick={handleClick}> <div className={style.wrapper}>
<h4> <h1>Stats:</h1>
{props.name} {isLoading ? <ClipLoader loading={isLoading}/> :
</h4> <StatsBox content={data as Languages ? Object.entries(data as Languages).map(element => `${element[0]}: ${element[1]} %`): ["Loading ..."] } />
</div>
)
} }
<h2 style={{marginTop: "50px"}}>More info:</h2>
const OverviewPage: FC<IOverviewPage> = (props) => { <div className={style.buttonWrapper}>
return ( <button className={style.button} onClick= {() => history.push(slug=== "/overview" ? "/issue" : `${slug}graph`)}>
<div className={style.outerWrapper}> {slug=== "/overview" ? "Issues" : "Graph"}
<div className={style.listwrapper}> </button>
<ul> <button className={style.button} onClick= {() => history.push(slug=== "/overview" ? "/commit" : `${slug}list`)}>
{props.buttons.map((element, index) => <li><Button name={element} link={props.links[index]}/></li>)} {slug=== "/overview" ? "Commits" : "List"}
</ul> </button>
</div> </div>
</div> </div>
) );
} };
export default OverviewPage; export default OverviewPage;
\ No newline at end of file
.wrapper {
display: flex;
flex-direction: column;
width: 100%;
align-items: center;
}
.button{ .buttonWrapper{
position: relative;
background: gold;
margin: auto auto 30px;
width: 80%;
display: flex; display: flex;
flex-direction: row;
justify-content: center; justify-content: center;
width: 100%;
height: 40%;
}
.button{
background: #8ECAE6;
cursor: pointer; cursor: pointer;
font-size: 200%; width: 250px;
height: 250px;
border-radius: 16px;
margin: 75px;
} }
.button:hover, .button:hover,
...@@ -15,34 +27,3 @@ ...@@ -15,34 +27,3 @@
box-shadow: 0 0.5em 0.5em -0.4em; box-shadow: 0 0.5em 0.5em -0.4em;
transform: translateY(-0.25em); transform: translateY(-0.25em);
} }
\ No newline at end of file
.listwrapper{
min-width: 500px;
margin: auto;
border: 5px solid black;
top: 25%;
width: 70%;
height: 100%;
padding: 10px;
display: flex;
align-items: center;
}
.outerWrapper{
border: 5px solid red;
margin: 0;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background-color: white;
}
ul {
padding: 0;
width: 100%;
list-style-type: none;
}
\ No newline at end of file
import { AxiosError } from "axios"; import axios, { AxiosError } from "axios";
import { useCallback, useEffect, useState } from "react"; import { useCallback, useEffect, useState } from "react";
import axios from "../axiosInstance"; import { Branch, Issue, Commit, ConnectionTest, queryTypes, Languages } from "./queryType";
import { Branch, Issue, Commit, ConnectionTest, queryTypes } from "./queryType";
export const useGitlabApi = (query: queryTypes|undefined) => { export const useGitlabApi = (query: queryTypes|undefined) => {
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<AxiosError | undefined>(); const [error, setError] = useState<AxiosError | undefined>();
const [data, setData] = useState<Issue[] | Commit[] | Branch[] | ConnectionTest>(); const [data, setData] = useState<Issue[] | Commit[] | Branch[] | ConnectionTest | Languages>();
const projectId = localStorage.getItem("projectId") ?? "11916"
const apiKey = localStorage.getItem("key") ?? "r74NY2kS_LprPFEobZxi";
const url = `https://gitlab.stud.idi.ntnu.no/api/v4/projects/${projectId}/${query}`;
const sendRequest = useCallback(async () => { const sendRequest = useCallback(async () => {
setIsLoading(true); setIsLoading(true);
setError(undefined); setError(undefined);
try{ try{
const response = await axios.get(`/${query}`); const response = await axios.get(url,
{headers: {"Authorization": `Bearer ${apiKey}`, "content_type":"application/json"}},);
setData(response.data); setData(response.data);
setIsLoading(false); setIsLoading(false);
} }
catch (e){ catch (e){
console.log(e); setError(e as AxiosError);
}}, [query]); setIsLoading(false);
}}, [apiKey, url]);
useEffect(() => { useEffect(() => {
if(!query) return; if(!query) return;
......
...@@ -3,15 +3,10 @@ export enum queryTypes { ...@@ -3,15 +3,10 @@ export enum queryTypes {
MergedBranches = "repository/merged_branches/", MergedBranches = "repository/merged_branches/",
AllCommits = "repository/commits/", AllCommits = "repository/commits/",
AllIssues = "issues/", AllIssues = "issues/",
issueStatistics = "issue_statistics/", Languages = "languages",
AllMembers = "members/",
Access="access_requests", Access="access_requests",
} }
export const getQueryString = (query: queryTypes, id: string = "") => {
return query.replace(':id', id);
};
export type User = { export type User = {
id: String, id: String,
name: String, name: String,
...@@ -49,5 +44,10 @@ export type Branch = { ...@@ -49,5 +44,10 @@ export type Branch = {
export type ConnectionTest = { export type ConnectionTest = {
};
export type Languages = {
Typescript: number,
CSS: number,
HTML: number,
} }
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment