diff --git a/src/about/About.js b/src/about/About.js
index 8efd630..66792b2 100644
--- a/src/about/About.js
+++ b/src/about/About.js
@@ -4,58 +4,56 @@
import React from "react";
import { Box, Link, Typography } from "@material-ui/core";
-const About = () => {
- return (
-
-
- About
+const About = () => (
+
+
+ About
+
+
+ An open source gitlab linting utility.
+
+
+
+
+ Contribute
-
- An open source gitlab linting utility.
+
+ Fork the repository and send your pull-requests.
+
+ -
+ Frontend:
+
+ https://github.com/globocom/gitlab-lint-react
+
+
+ -
+ Backend:
+
+ https://github.com/globocom/gitlab-lint
+
+
+
+
-
-
- Contribute
-
-
- Fork the repository and send your pull-requests.
-
-
- -
- Frontend:
-
- https://github.com/globocom/gitlab-lint-react
-
-
- -
- Backend:
-
- https://github.com/globocom/gitlab-lint
-
-
-
-
-
-
-
- License
-
-
- By contributing to gitlab-lint, you agree that your contributions will
- be licensed under its BSD 3-Clause license.
-
-
-
- );
-};
+
+
+ License
+
+
+ By contributing to gitlab-lint, you agree that your contributions will
+ be licensed under its BSD 3-Clause license.
+
+
+
+);
export default About;
diff --git a/src/dashboard/Dashboard.js b/src/dashboard/Dashboard.js
index ab735cc..30fac4b 100644
--- a/src/dashboard/Dashboard.js
+++ b/src/dashboard/Dashboard.js
@@ -1,30 +1,19 @@
// Copyright (c) 2021, Marcelo Jorge Vieira
// Licensed under the BSD 3-Clause License
-import React, { useState, useEffect } from "react";
-
-import GitlabLintHttpClient from "../GitlabLintHttpClient";
+import React from "react";
+import useFetch from "../hooks/useFetch";
import Loading from "../Loading";
import Numbers from "./Numbers";
import Stats from "./Stats";
const Dashboard = () => {
- const [rows, setData] = useState({});
- const fetchData = () => {
- GitlabLintHttpClient("GET_ALL", { entity: "stats" })
- .then((data) => {
- setData(data.data);
- })
- .catch((err) => console.error(err));
- };
-
- useEffect(() => {
- fetchData();
- }, []);
+ const { data: rows, loading } = useFetch({
+ method: "GET_ALL",
+ entity: "stats",
+ });
- if (Object.keys(rows).length === 0 && rows.constructor === Object) {
- return ;
- }
+ if (loading) return ;
return (
diff --git a/src/hooks/useFetch.js b/src/hooks/useFetch.js
new file mode 100644
index 0000000..3430c5e
--- /dev/null
+++ b/src/hooks/useFetch.js
@@ -0,0 +1,40 @@
+import { useState, useEffect, useCallback } from "react";
+import GitlabLintHttpClient from "../GitlabLintHttpClient";
+
+function useFetch({ method, entity, id = null, params = {} }) {
+ const [data, setData] = useState(null);
+ const [loading, setLoading] = useState(true);
+ const [error, setError] = useState(null);
+
+ const fetchData = useCallback(
+ (overrideParams = {}) => {
+ setLoading(true);
+ setError(null);
+
+ const payload = {
+ entity,
+ ...(id && { id }),
+ ...params,
+ ...overrideParams,
+ };
+
+ GitlabLintHttpClient(method, payload)
+ .then((res) => setData(res.data))
+ .catch((err) => {
+ setError(
+ err.response?.data?.errors?._all || err.message || "Unknown error"
+ );
+ })
+ .finally(() => setLoading(false));
+ },
+ [method, entity, id, JSON.stringify(params)]
+ );
+
+ useEffect(() => {
+ fetchData();
+ }, [fetchData]);
+
+ return { data, loading, error, refetch: fetchData };
+}
+
+export default useFetch;
diff --git a/src/levels/Levels.js b/src/levels/Levels.js
index 8c0c663..92c8908 100644
--- a/src/levels/Levels.js
+++ b/src/levels/Levels.js
@@ -1,8 +1,9 @@
// Copyright (c) 2021, Marcelo Jorge Vieira
// Licensed under the BSD 3-Clause License
-import React, { useState, useEffect } from "react";
+import React from "react";
import { makeStyles } from "@material-ui/core/styles";
+import useFetch from "../hooks/useFetch";
import {
Card,
CardContent,
@@ -12,7 +13,6 @@ import {
} from "@material-ui/core";
import Loading from "../Loading";
-import GitlabLintHttpClient from "../GitlabLintHttpClient";
import levelsStyle from "../theme";
const useStyles = makeStyles((theme) => ({
@@ -31,20 +31,12 @@ const useStyles = makeStyles((theme) => ({
const Levels = () => {
const classes = useStyles();
- const [rows, setData] = useState({});
- const fetchData = () => {
- GitlabLintHttpClient("GET_ALL", { entity: "levels" })
- .then((data) => {
- setData(data.data);
- })
- .catch((err) => console.error(err));
- };
+ const { data: rows, loading } = useFetch({
+ method: "GET_ALL",
+ entity: "levels",
+ });
- useEffect(() => {
- fetchData();
- }, []);
-
- if (Object.keys(rows).length === 0 && rows.constructor === Object) {
+ if (loading) {
return ;
}
diff --git a/src/projects/Project.js b/src/projects/Project.js
index c622c67..9304131 100644
--- a/src/projects/Project.js
+++ b/src/projects/Project.js
@@ -1,7 +1,7 @@
// Copyright (c) 2021, Marcelo Jorge Vieira
// Licensed under the BSD 3-Clause License
-import React, { useState, useEffect, useCallback } from "react";
+import React from "react";
import { Link as RouterLink, useParams } from "react-router-dom";
import {
Box,
@@ -12,47 +12,33 @@ import {
ListItem,
Typography,
} from "@material-ui/core";
+import Loading from "../Loading";
+import useFetch from "../hooks/useFetch";
-import GitlabLintHttpClient from "../GitlabLintHttpClient";
import RuleTitle from "../rules/RuleTitle";
import ProjectTitle from "./ProjectTitle";
const Project = () => {
- const [rows, setData] = useState({});
- const [errorMessage, setErrorMessage] = useState({});
const { id } = useParams();
- const fetchData = useCallback(() => {
- GitlabLintHttpClient("GET_ONE", { entity: "projects", id: id })
- .then((data) => {
- setData(data.data);
- })
- .catch((err) => {
- setErrorMessage({
- status: err.response.status,
- message: err.response.data.errors["_all"],
- });
- console.error(err);
- console.error(err.response);
- });
- }, [id]);
+ const {
+ data: rows,
+ loading,
+ error,
+ } = useFetch({
+ method: "GET_ONE",
+ entity: "projects",
+ id,
+ });
- useEffect(() => {
- fetchData();
- }, [fetchData]);
+ if (loading) {
+ return ;
+ }
- if (Object.keys(rows).length === 0 && rows.constructor === Object) {
+ if (error) {
let messageTitle = "Error";
- if (errorMessage.status === 404) {
+ if (error.status === 404) {
messageTitle = "Project not found";
}
- return (
- <>
-
- {messageTitle}
-
- {errorMessage.message}
- >
- );
}
return (
diff --git a/src/rules/Rule.js b/src/rules/Rule.js
index 724e096..8ae902e 100644
--- a/src/rules/Rule.js
+++ b/src/rules/Rule.js
@@ -1,10 +1,9 @@
// Copyright (c) 2021, Marcelo Jorge Vieira
// Licensed under the BSD 3-Clause License
-import React, { useState, useEffect, useCallback } from "react";
+import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import { Link as RouterLink, useParams } from "react-router-dom";
-
import {
Box,
Breadcrumbs,
@@ -16,9 +15,9 @@ import {
Typography,
} from "@material-ui/core";
-import GitlabLintHttpClient from "../GitlabLintHttpClient";
import Loading from "../Loading";
import RuleTitle from "./RuleTitle";
+import useFetch from "../hooks/useFetch";
const useStyles = makeStyles((theme) => ({
ruleDescription: {
@@ -62,19 +61,17 @@ const RuleProjects = ({ projects }) => {
const Rule = () => {
const classes = useStyles();
- const [rows, setData] = useState({});
const { id } = useParams();
- const fetchData = useCallback(() => {
- GitlabLintHttpClient("GET_ONE", { entity: "rules", id: id })
- .then((data) => {
- setData(data.data);
- })
- .catch((err) => console.error(err));
- }, [id]);
- useEffect(() => {
- fetchData();
- }, [fetchData]);
+ const { data: rows, loading } = useFetch({
+ method: "GET_ONE",
+ entity: "rules",
+ id,
+ });
+
+ if (loading) {
+ return ;
+ }
if (Object.keys(rows).length === 0 && rows.constructor === Object) {
return ;
diff --git a/src/rules/Rules.js b/src/rules/Rules.js
index 281a081..36fb1dd 100644
--- a/src/rules/Rules.js
+++ b/src/rules/Rules.js
@@ -1,7 +1,7 @@
// Copyright (c) 2021, Marcelo Jorge Vieira
// Licensed under the BSD 3-Clause License
-import React, { useState, useEffect } from "react";
+import React from "react";
import { Link } from "react-router-dom";
import { makeStyles } from "@material-ui/core/styles";
import {
@@ -15,9 +15,9 @@ import {
Typography,
} from "@material-ui/core";
-import GitlabLintHttpClient from "../GitlabLintHttpClient";
import Loading from "../Loading";
import levelsStyles from "../theme";
+import useFetch from "../hooks/useFetch";
const useStyles = makeStyles((theme) => ({
root: {
@@ -31,20 +31,12 @@ const useStyles = makeStyles((theme) => ({
const Rules = () => {
const classes = useStyles();
- const [rows, setData] = useState({});
- const fetchData = () => {
- GitlabLintHttpClient("GET_ALL", { entity: "rules" })
- .then((data) => {
- setData(data.data);
- })
- .catch((err) => console.error(err));
- };
+ const { data: rows, loading } = useFetch({
+ method: "GET_ALL",
+ entity: "rules",
+ });
- useEffect(() => {
- fetchData();
- }, []);
-
- if (Object.keys(rows).length === 0 && rows.constructor === Object) {
+ if (loading) {
return ;
}