Merge pull request #169 from Worklenz/imp/task-list-performance-fixes

Imp/task list performance fixes
This commit is contained in:
Chamika J
2025-06-21 18:53:55 +05:30
committed by GitHub
21 changed files with 1735 additions and 452 deletions

View File

@@ -1,7 +1,7 @@
import React, { useEffect } from 'react';
import { Layout, Typography, Card, Space, Alert } from 'antd';
import { useDispatch } from 'react-redux';
import TaskListBoard from '@/components/task-management/TaskListBoard';
import TaskListBoard from '@/components/task-management/task-list-board';
import { AppDispatch } from '@/app/store';
const { Header, Content } = Layout;

View File

@@ -1,4 +1,4 @@
import { useEffect } from 'react';
import { useEffect, memo, useMemo, useCallback } from 'react';
import { useMediaQuery } from 'react-responsive';
import Col from 'antd/es/col';
import Flex from 'antd/es/flex';
@@ -19,48 +19,72 @@ import { fetchProjectCategories } from '@/features/projects/lookups/projectCateg
import { fetchProjectHealth } from '@/features/projects/lookups/projectHealth/projectHealthSlice';
import { fetchProjects } from '@/features/home-page/home-page.slice';
import { createPortal } from 'react-dom';
import React from 'react';
import React, { Suspense } from 'react';
const DESKTOP_MIN_WIDTH = 1024;
const TASK_LIST_MIN_WIDTH = 500;
const SIDEBAR_MAX_WIDTH = 400;
// Lazy load heavy components
const TaskDrawer = React.lazy(() => import('@components/task-drawer/task-drawer'));
const HomePage = () => {
const HomePage = memo(() => {
const dispatch = useAppDispatch();
const isDesktop = useMediaQuery({ query: `(min-width: ${DESKTOP_MIN_WIDTH}px)` });
const isOwnerOrAdmin = useAuthService().isOwnerOrAdmin();
useDocumentTitle('Home');
useEffect(() => {
const fetchLookups = async () => {
const fetchPromises = [
dispatch(fetchProjectHealth()),
dispatch(fetchProjectCategories()),
dispatch(fetchProjectStatuses()),
dispatch(fetchProjects()),
].filter(Boolean);
// Memoize fetch function to prevent recreation on every render
const fetchLookups = useCallback(async () => {
const fetchPromises = [
dispatch(fetchProjectHealth()),
dispatch(fetchProjectCategories()),
dispatch(fetchProjectStatuses()),
dispatch(fetchProjects()),
].filter(Boolean);
await Promise.all(fetchPromises);
};
fetchLookups();
await Promise.all(fetchPromises);
}, [dispatch]);
const CreateProjectButtonComponent = () =>
isDesktop ? (
useEffect(() => {
fetchLookups();
}, [fetchLookups]);
// Memoize project drawer close handler
const handleProjectDrawerClose = useCallback(() => {}, []);
// Memoize desktop flex styles to prevent object recreation
const desktopFlexStyle = useMemo(() => ({
minWidth: TASK_LIST_MIN_WIDTH,
width: '100%'
}), []);
const sidebarFlexStyle = useMemo(() => ({
width: '100%',
maxWidth: SIDEBAR_MAX_WIDTH
}), []);
// Memoize components to prevent unnecessary re-renders
const CreateProjectButtonComponent = useMemo(() => {
if (!isOwnerOrAdmin) return null;
return isDesktop ? (
<div className="absolute right-0 top-1/2 -translate-y-1/2">
{isOwnerOrAdmin && <CreateProjectButton />}
<CreateProjectButton />
</div>
) : (
isOwnerOrAdmin && <CreateProjectButton />
<CreateProjectButton />
);
}, [isDesktop, isOwnerOrAdmin]);
const MainContent = () =>
isDesktop ? (
const MainContent = useMemo(() => {
return isDesktop ? (
<Flex gap={24} align="flex-start" className="w-full mt-12">
<Flex style={{ minWidth: TASK_LIST_MIN_WIDTH, width: '100%' }}>
<Flex style={desktopFlexStyle}>
<TasksList />
</Flex>
<Flex vertical gap={24} style={{ width: '100%', maxWidth: SIDEBAR_MAX_WIDTH }}>
<Flex vertical gap={24} style={sidebarFlexStyle}>
<TodoList />
<RecentAndFavouriteProjectList />
</Flex>
@@ -72,19 +96,31 @@ const HomePage = () => {
<RecentAndFavouriteProjectList />
</Flex>
);
}, [isDesktop, desktopFlexStyle, sidebarFlexStyle]);
return (
<div className="my-24 min-h-[90vh]">
<Col className="flex flex-col gap-6">
<GreetingWithTime />
<CreateProjectButtonComponent />
{CreateProjectButtonComponent}
</Col>
<MainContent />
{createPortal(<TaskDrawer />, document.body, 'home-task-drawer')}
{createPortal(<ProjectDrawer onClose={() => {}} />, document.body, 'project-drawer')}
{MainContent}
{/* Use Suspense for lazy-loaded components */}
<Suspense fallback={null}>
{createPortal(<TaskDrawer />, document.body, 'home-task-drawer')}
</Suspense>
{createPortal(
<ProjectDrawer onClose={handleProjectDrawerClose} />,
document.body,
'project-drawer'
)}
</div>
);
};
});
HomePage.displayName = 'HomePage';
export default HomePage;

View File

@@ -1,6 +1,6 @@
import React from 'react';
import { useAppSelector } from '@/hooks/useAppSelector';
import TaskListBoard from '@/components/task-management/TaskListBoard';
import TaskListBoard from '@/components/task-management/task-list-board';
const ProjectViewEnhancedTasks: React.FC = () => {
const { project } = useAppSelector(state => state.projectReducer);