Skip to content

Commit

Permalink
feat: add lazy loading
Browse files Browse the repository at this point in the history
  • Loading branch information
AKharytonchyk committed Nov 5, 2024
1 parent 8bc472e commit a62fcbb
Show file tree
Hide file tree
Showing 14 changed files with 96 additions and 43 deletions.
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"@emotion/styled": "^11.11.0",
"@mui/icons-material": "^5.15.14",
"@mui/material": "^5.15.14",
"@octokit/rest": "^21.0.0-beta.1",
"@octokit/rest": "^21.0.2",
"@tanstack/react-query": "^5.28.9",
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
Expand Down
2 changes: 1 addition & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ function App() {
const onLogin = React.useCallback(() => {
if (token) {
const octoKit = new GitService(
(import.meta as any).env.VITE_GITHUB_API_URL || "https://api.github.com/",
(import.meta as any).env.VITE_GITHUB_API_URL || "https://api.github.com",
token
);
octoKit.testAuthentication().then((user) => {
Expand Down
60 changes: 37 additions & 23 deletions src/components/Dashboard.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from "react";
import React, { Suspense, useEffect } from "react";
import { ConfigContext } from "../App";
import { PullRequest } from "../models/PullRequest";
import PullRequestCard from "./PullRequestCard";
Expand All @@ -7,32 +7,40 @@ import Grid2 from "@mui/material/Unstable_Grid2/Grid2";
import LandingPage from "../pages/LandingPage";
import { MultiselectFilter } from "./MultiselectFilter";
import { InputFilter } from "./InputFilter";
import { useQuery } from "@tanstack/react-query";
import { PRLoadingPage } from "../pages/PRLoadingPage";
import { useQueries } from "@tanstack/react-query";
import { Navigate } from "react-router-dom";
import PRLoadingPageLazy from "../pages/PrLoadingPage.lazy";

export const Dashboard: React.FC = () => {
const { octokit, repositorySettings } = React.useContext(ConfigContext);
const activeRepositories = React.useMemo(
() =>
Object.keys(repositorySettings)
.filter((key) => repositorySettings[key])
.sort(),
[repositorySettings]
const [activeRepositories, setActiveRepositories] = React.useState<string[]>(
[]
);

const { data = [], isLoading } = useQuery({
queryKey: ["pulls"],
queryFn: async () => {
if (octokit && activeRepositories.length) {
const pulls = await Promise.all(
activeRepositories.map((repo) => octokit.getPullRequests(repo))
);
useEffect(() => {
setActiveRepositories(
Object.keys(repositorySettings)
.filter((key) => repositorySettings[key])
.sort()
);
}, [repositorySettings]);

return pulls.flat()
}
const { data, pending } = useQueries({
queries: activeRepositories.map((repo) => ({
queryKey: ["pulls", repo],
queryFn: async () => {
if (octokit) {
return octokit.getPullRequests(repo);
}
},
enabled: octokit !== undefined,
})),
combine: (results) => {
return {
data: results.map((result) => result.data ?? [] as PullRequest[]).flat(),
pending: results.some((result) => result.isLoading),
};
},
enabled: octokit !== undefined && activeRepositories.length > 0,
});

const [filter, setFilter] = React.useState<string>("");
Expand Down Expand Up @@ -79,15 +87,19 @@ export const Dashboard: React.FC = () => {
});
}, [data, filter, includeLabels, excludeLabels]);

if (!localStorage.getItem("token")){
if (!localStorage.getItem("token")) {
return <Navigate to="/login" />;
}

return (
<Box padding={2} width={"calc(100vw - 2em)"}>
{isLoading && <PRLoadingPage />}
{!isLoading && data.length === 0 && <LandingPage />}
{data.length > 0 && (
{pending && data.length === 0 && (
<Suspense fallback={<div>Loading...</div>}>
<PRLoadingPageLazy />
</Suspense>
)}
{!pending && data.length === 0 && <LandingPage />}
{data.length > 0 && (
<>
<Box>
<InputFilter name="Filter" onChange={setFilter} size="small" />
Expand Down Expand Up @@ -117,3 +129,5 @@ export const Dashboard: React.FC = () => {
</Box>
);
};

export default Dashboard;
2 changes: 0 additions & 2 deletions src/components/PullRequestChecks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@ export const PullRequestChecks: React.FC<PullRequestChecksProps> = ({
[checks]
);

if (checks.length > 0 && checks.some(({ conclusion }) => conclusion !== 'success')) console.warn("checks", checks);

return (
<>
<Typography
Expand Down
32 changes: 23 additions & 9 deletions src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import React from "react";
import React, { Suspense } from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import { RouterProvider, createHashRouter } from "react-router-dom";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { ScopedCssBaseline } from "@mui/material";
import LandingPage from "./pages/LandingPage";
import { Dashboard } from "./components/Dashboard";
import { Coverage } from "./pages/Coverage";
import LandingPage from "./pages/LandingPage.lazy";
import Dashboard from "./pages/Dashboard.lazy";
import Coverage from "./pages/Coverage.lazy";

const router = createHashRouter([
{
Expand All @@ -17,18 +17,32 @@ const router = createHashRouter([
children: [
{
path: "/",
element: <Dashboard />,
element: (
<Suspense fallback={<div>Loading...</div>}>
<Dashboard />
</Suspense>
),
},
{
path: "/login",
element: <LandingPage />,
}, {
element: (
<Suspense fallback={<div>Loading...</div>}>
<LandingPage />
</Suspense>
),
},
{
path: "/coverage",
element: <Coverage />,
}
element: (
<Suspense fallback={<div>Loading...</div>}>
<Coverage />
</Suspense>
),
},
],
},
]);

const queryClient = new QueryClient();

const root = ReactDOM.createRoot(
Expand Down
5 changes: 5 additions & 0 deletions src/pages/Coverage.lazy.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { lazy } from "react";

const Coverage = lazy(() => import("./Coverage"));

export default Coverage;
2 changes: 2 additions & 0 deletions src/pages/Coverage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,5 @@ export const Coverage: React.FC = () => {
</Box>
);
};

export default Coverage;
5 changes: 5 additions & 0 deletions src/pages/Dashboard.lazy.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import React from 'react';

const DashboardLazy = React.lazy(() => import('../components/Dashboard'));

export default DashboardLazy;
5 changes: 5 additions & 0 deletions src/pages/LandingPage.lazy.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import React from "react";

const LandingPageLazy = React.lazy(() => import("./LandingPage"));

export default LandingPageLazy;
2 changes: 2 additions & 0 deletions src/pages/PRLoadingPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,5 @@ export const PRLoadingPage: React.FC = () => {
</Box>
);
}

export default PRLoadingPage;
5 changes: 5 additions & 0 deletions src/pages/PrLoadingPage.lazy.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import React from 'react';

const PRLoadingPageLazy = React.lazy(() => import('./PRLoadingPage'));

export default PRLoadingPageLazy;
2 changes: 1 addition & 1 deletion src/service/gitService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export class GitService {
private readonly octokit: Octokit;
constructor(baseUrl: string, token: string) {
this.octokit = new Octokit({
baseUrl,
baseUrl: !baseUrl.endsWith("/") ? baseUrl : baseUrl.substring(0, baseUrl.length - 1),
auth: token,
});
}
Expand Down
13 changes: 8 additions & 5 deletions src/utils/RateLimiterQueue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,20 @@ class RateLimiterQueue {
}, 60000);
}

async enqueue<T>(requestFunction: () => Promise<T>): Promise<T> {
async enqueue<T>(requestFunction: () => Promise<T>, force = false): Promise<T> {
return new Promise((resolve, reject) => {
this.queue.push(async () => {
const request = async () => {
try {
const result = await requestFunction();
resolve(result);
} catch (error) {
reject(error);
}
});
}

if(force) this.queue.unshift(request);
else this.queue.push(request);

if (!this.isProcessing) {
this.processQueue();
}
Expand All @@ -40,12 +44,11 @@ class RateLimiterQueue {
const requestFunction = this.queue.shift();
if (requestFunction) {
try {
await requestFunction();
await Promise.all([requestFunction(), this.sleep(this.delay)]);
console.debug(`Request processed. Queue size after: ${this.queue.length}`);
} catch (error) {
console.error("Error processing request:", error);
}
await this.sleep(this.delay);
}
}
this.isProcessing = false;
Expand Down

0 comments on commit a62fcbb

Please sign in to comment.