feat(project-view): optimize component loading and enhance configuration
- Introduced lazy loading for project view components and chart components to reduce initial bundle size. - Centralized Ant Design imports in a new `antd-imports.ts` file for better tree-shaking and maintainability. - Updated project view header and task list components to utilize centralized imports, improving consistency and performance. - Enhanced project view constants to streamline component rendering and improve user experience.
This commit is contained in:
25
worklenz-frontend/src/components/charts/chart-loader.tsx
Normal file
25
worklenz-frontend/src/components/charts/chart-loader.tsx
Normal file
@@ -0,0 +1,25 @@
|
||||
import React, { Suspense } from 'react';
|
||||
import { Spin } from 'antd';
|
||||
|
||||
// Lazy load chart components to reduce initial bundle size
|
||||
const LazyBar = React.lazy(() => import('react-chartjs-2').then(module => ({ default: module.Bar })));
|
||||
const LazyDoughnut = React.lazy(() => import('react-chartjs-2').then(module => ({ default: module.Doughnut })));
|
||||
|
||||
interface ChartLoaderProps {
|
||||
type: 'bar' | 'doughnut';
|
||||
data: any;
|
||||
options?: any;
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
const ChartLoader: React.FC<ChartLoaderProps> = ({ type, ...props }) => {
|
||||
const ChartComponent = type === 'bar' ? LazyBar : LazyDoughnut;
|
||||
|
||||
return (
|
||||
<Suspense fallback={<Spin size="large" />}>
|
||||
<ChartComponent {...props} />
|
||||
</Suspense>
|
||||
);
|
||||
};
|
||||
|
||||
export default ChartLoader;
|
||||
@@ -1,12 +1,12 @@
|
||||
import React, { ReactNode } from 'react';
|
||||
import ProjectViewInsights from '@/pages/projects/projectView/insights/project-view-insights';
|
||||
import ProjectViewFiles from '@/pages/projects/projectView/files/project-view-files';
|
||||
import ProjectViewMembers from '@/pages/projects/projectView/members/project-view-members';
|
||||
import ProjectViewUpdates from '@/pages/projects/project-view-1/updates/project-view-updates';
|
||||
import ProjectViewTaskList from '@/pages/projects/projectView/taskList/project-view-task-list';
|
||||
import ProjectViewBoard from '@/pages/projects/projectView/board/project-view-board';
|
||||
import ProjectViewEnhancedTasks from '@/pages/projects/projectView/enhancedTasks/project-view-enhanced-tasks';
|
||||
import ProjectViewEnhancedBoard from '@/pages/projects/projectView/enhancedBoard/project-view-enhanced-board';
|
||||
|
||||
// Lazy load all project view components to reduce initial bundle size
|
||||
const ProjectViewInsights = React.lazy(() => import('@/pages/projects/projectView/insights/project-view-insights'));
|
||||
const ProjectViewFiles = React.lazy(() => import('@/pages/projects/projectView/files/project-view-files'));
|
||||
const ProjectViewMembers = React.lazy(() => import('@/pages/projects/projectView/members/project-view-members'));
|
||||
const ProjectViewUpdates = React.lazy(() => import('@/pages/projects/project-view-1/updates/project-view-updates'));
|
||||
const ProjectViewEnhancedTasks = React.lazy(() => import('@/pages/projects/projectView/enhancedTasks/project-view-enhanced-tasks'));
|
||||
const ProjectViewEnhancedBoard = React.lazy(() => import('@/pages/projects/projectView/enhancedBoard/project-view-enhanced-board'));
|
||||
|
||||
// type of a tab items
|
||||
type TabItems = {
|
||||
@@ -28,57 +28,31 @@ export const tabItems: TabItems[] = [
|
||||
},
|
||||
{
|
||||
index: 1,
|
||||
key: 'task-list-v1',
|
||||
label: 'Task List v1',
|
||||
isPinned: true,
|
||||
element: React.createElement(ProjectViewTaskList),
|
||||
},
|
||||
{
|
||||
index: 2,
|
||||
key: 'board',
|
||||
label: 'Board',
|
||||
isPinned: true,
|
||||
element: React.createElement(ProjectViewEnhancedBoard),
|
||||
},
|
||||
{
|
||||
index: 3,
|
||||
key: 'board-v1',
|
||||
label: 'Board v1',
|
||||
isPinned: true,
|
||||
element: React.createElement(ProjectViewBoard),
|
||||
},
|
||||
// {
|
||||
// index: 3,
|
||||
// key: 'workload',
|
||||
// label: 'Workload',
|
||||
// element: React.createElement(ProjectViewWorkload),
|
||||
// },
|
||||
// {
|
||||
// index: 4,
|
||||
// key: 'roadmap',
|
||||
// label: 'Roadmap',
|
||||
// element: React.createElement(ProjectViewRoadmap),
|
||||
// },
|
||||
{
|
||||
index: 5,
|
||||
index: 2,
|
||||
key: 'project-insights-member-overview',
|
||||
label: 'Insights',
|
||||
element: React.createElement(ProjectViewInsights),
|
||||
},
|
||||
{
|
||||
index: 6,
|
||||
index: 3,
|
||||
key: 'all-attachments',
|
||||
label: 'Files',
|
||||
element: React.createElement(ProjectViewFiles),
|
||||
},
|
||||
{
|
||||
index: 7,
|
||||
index: 4,
|
||||
key: 'members',
|
||||
label: 'Members',
|
||||
element: React.createElement(ProjectViewMembers),
|
||||
},
|
||||
{
|
||||
index: 8,
|
||||
index: 5,
|
||||
key: 'updates',
|
||||
label: 'Updates',
|
||||
element: React.createElement(ProjectViewUpdates),
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
import {
|
||||
import {
|
||||
Button,
|
||||
Dropdown,
|
||||
Flex,
|
||||
Tag,
|
||||
Tooltip,
|
||||
Typography,
|
||||
ArrowLeftOutlined,
|
||||
BellFilled,
|
||||
BellOutlined,
|
||||
@@ -9,10 +15,9 @@ import {
|
||||
SaveOutlined,
|
||||
SettingOutlined,
|
||||
SyncOutlined,
|
||||
UsergroupAddOutlined,
|
||||
} from '@ant-design/icons';
|
||||
UsergroupAddOutlined
|
||||
} from '@/shared/antd-imports';
|
||||
import { PageHeader } from '@ant-design/pro-components';
|
||||
import { Button, Dropdown, Flex, Tag, Tooltip, Typography } from 'antd';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
|
||||
@@ -1,9 +1,20 @@
|
||||
import React, { useEffect, useState, useMemo, useCallback } from 'react';
|
||||
import { PushpinFilled, PushpinOutlined, QuestionCircleOutlined } from '@ant-design/icons';
|
||||
import { Badge, Button, ConfigProvider, Flex, Tabs, TabsProps, Tooltip } from 'antd';
|
||||
import { useLocation, useNavigate, useParams, useSearchParams } from 'react-router-dom';
|
||||
import { createPortal } from 'react-dom';
|
||||
|
||||
// Centralized Ant Design imports
|
||||
import {
|
||||
Button,
|
||||
ConfigProvider,
|
||||
Flex,
|
||||
Tooltip,
|
||||
Badge,
|
||||
Tabs,
|
||||
PushpinFilled,
|
||||
PushpinOutlined,
|
||||
type TabsProps
|
||||
} from '@/shared/antd-imports';
|
||||
|
||||
import { useAppDispatch } from '@/hooks/useAppDispatch';
|
||||
import { useAppSelector } from '@/hooks/useAppSelector';
|
||||
import { getProject, setProjectId, setProjectView } from '@/features/project/project.slice';
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useEffect, useState, useMemo, lazy, Suspense } from 'react';
|
||||
import { Empty } from '@/shared/antd-imports';
|
||||
import Flex from 'antd/es/flex';
|
||||
import Skeleton from 'antd/es/skeleton';
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
@@ -10,7 +11,6 @@ import { useAppDispatch } from '@/hooks/useAppDispatch';
|
||||
import { fetchTaskGroups, fetchTaskListColumns } from '@/features/tasks/tasks.slice';
|
||||
import { fetchStatusesCategories } from '@/features/taskAttributes/taskStatusSlice';
|
||||
import { fetchPhasesByProjectId } from '@/features/projects/singleProject/phase/phases.slice';
|
||||
import { Empty } from 'antd';
|
||||
import useTabSearchParam from '@/hooks/useTabSearchParam';
|
||||
|
||||
const ProjectViewTaskList = () => {
|
||||
|
||||
198
worklenz-frontend/src/shared/antd-imports.ts
Normal file
198
worklenz-frontend/src/shared/antd-imports.ts
Normal file
@@ -0,0 +1,198 @@
|
||||
/**
|
||||
* Optimized Ant Design imports for maximum tree-shaking
|
||||
*
|
||||
* This file provides:
|
||||
* - Granular imports from antd/es for better tree-shaking
|
||||
* - Only commonly used components to reduce bundle size
|
||||
* - Separate icon imports to avoid loading entire icon set
|
||||
*/
|
||||
|
||||
// Core Components - Import as default exports for better tree-shaking
|
||||
import Button from 'antd/es/button';
|
||||
import Input from 'antd/es/input';
|
||||
import Select from 'antd/es/select';
|
||||
import Typography from 'antd/es/typography';
|
||||
import Card from 'antd/es/card';
|
||||
import Spin from 'antd/es/spin';
|
||||
import Empty from 'antd/es/empty';
|
||||
import Space from 'antd/es/space';
|
||||
import Tooltip from 'antd/es/tooltip';
|
||||
import Badge from 'antd/es/badge';
|
||||
import Popconfirm from 'antd/es/popconfirm';
|
||||
import Checkbox from 'antd/es/checkbox';
|
||||
import Dropdown from 'antd/es/dropdown';
|
||||
import Menu from 'antd/es/menu';
|
||||
import Modal from 'antd/es/modal';
|
||||
import Tag from 'antd/es/tag';
|
||||
import Avatar from 'antd/es/avatar';
|
||||
import List from 'antd/es/list';
|
||||
import Table from 'antd/es/table';
|
||||
import Flex from 'antd/es/flex';
|
||||
import Divider from 'antd/es/divider';
|
||||
import Progress from 'antd/es/progress';
|
||||
import Result from 'antd/es/result';
|
||||
import Skeleton from 'antd/es/skeleton';
|
||||
import Alert from 'antd/es/alert';
|
||||
import Tabs from 'antd/es/tabs';
|
||||
import ConfigProvider from 'antd/es/config-provider';
|
||||
|
||||
// Date & Time Components
|
||||
import DatePicker from 'antd/es/date-picker';
|
||||
import TimePicker from 'antd/es/time-picker';
|
||||
|
||||
// Form Components
|
||||
import Form from 'antd/es/form';
|
||||
import InputNumber from 'antd/es/input-number';
|
||||
|
||||
// Layout Components
|
||||
import Row from 'antd/es/row';
|
||||
import Col from 'antd/es/col';
|
||||
import Layout from 'antd/es/layout';
|
||||
import Drawer from 'antd/es/drawer';
|
||||
|
||||
// Message and Notification - Import separately
|
||||
import message from 'antd/es/message';
|
||||
import notification from 'antd/es/notification';
|
||||
|
||||
// Theme
|
||||
import theme from 'antd/es/theme';
|
||||
|
||||
// Re-export all components
|
||||
export {
|
||||
Button,
|
||||
Input,
|
||||
Select,
|
||||
Typography,
|
||||
Card,
|
||||
Spin,
|
||||
Empty,
|
||||
Space,
|
||||
Tooltip,
|
||||
Badge,
|
||||
Popconfirm,
|
||||
Checkbox,
|
||||
Dropdown,
|
||||
Menu,
|
||||
Modal,
|
||||
Tag,
|
||||
Avatar,
|
||||
List,
|
||||
Table,
|
||||
Flex,
|
||||
Divider,
|
||||
Progress,
|
||||
Result,
|
||||
Skeleton,
|
||||
Alert,
|
||||
Tabs,
|
||||
ConfigProvider,
|
||||
DatePicker,
|
||||
TimePicker,
|
||||
Form,
|
||||
InputNumber,
|
||||
Row,
|
||||
Col,
|
||||
Layout,
|
||||
Drawer,
|
||||
message,
|
||||
notification,
|
||||
theme
|
||||
};
|
||||
|
||||
// Icons - Import only commonly used ones
|
||||
export {
|
||||
EditOutlined,
|
||||
DeleteOutlined,
|
||||
PlusOutlined,
|
||||
MoreOutlined,
|
||||
CheckOutlined,
|
||||
CloseOutlined,
|
||||
CalendarOutlined,
|
||||
ClockCircleOutlined,
|
||||
UserOutlined,
|
||||
TeamOutlined,
|
||||
TagOutlined,
|
||||
BarsOutlined,
|
||||
AppstoreOutlined,
|
||||
FilterOutlined,
|
||||
SearchOutlined,
|
||||
SettingOutlined,
|
||||
DownOutlined,
|
||||
RightOutlined,
|
||||
LeftOutlined,
|
||||
UpOutlined,
|
||||
ArrowLeftOutlined,
|
||||
BellFilled,
|
||||
BellOutlined,
|
||||
SaveOutlined,
|
||||
SyncOutlined,
|
||||
PushpinFilled,
|
||||
PushpinOutlined,
|
||||
UsergroupAddOutlined,
|
||||
ImportOutlined
|
||||
} from '@ant-design/icons';
|
||||
|
||||
// TypeScript Types - Import only commonly used ones
|
||||
export type {
|
||||
ButtonProps,
|
||||
InputProps,
|
||||
InputRef,
|
||||
SelectProps,
|
||||
TypographyProps,
|
||||
CardProps,
|
||||
TooltipProps,
|
||||
DropdownProps,
|
||||
MenuProps,
|
||||
DatePickerProps,
|
||||
FormProps,
|
||||
FormInstance,
|
||||
FlexProps,
|
||||
TabsProps,
|
||||
TableProps,
|
||||
TableColumnsType
|
||||
} from 'antd';
|
||||
|
||||
// Dayjs
|
||||
export { default as dayjs } from 'dayjs';
|
||||
export type { Dayjs } from 'dayjs';
|
||||
|
||||
// Optimized message utilities
|
||||
export const appMessage = {
|
||||
success: (content: string) => message.success(content),
|
||||
error: (content: string) => message.error(content),
|
||||
warning: (content: string) => message.warning(content),
|
||||
info: (content: string) => message.info(content),
|
||||
loading: (content: string) => message.loading(content),
|
||||
};
|
||||
|
||||
export const appNotification = {
|
||||
success: (config: any) => notification.success(config),
|
||||
error: (config: any) => notification.error(config),
|
||||
warning: (config: any) => notification.warning(config),
|
||||
info: (config: any) => notification.info(config),
|
||||
};
|
||||
|
||||
// Default configurations
|
||||
export const antdConfig = {
|
||||
datePickerDefaults: {
|
||||
format: 'MMM DD, YYYY',
|
||||
placeholder: 'Set Date',
|
||||
size: 'small' as const,
|
||||
},
|
||||
buttonDefaults: {
|
||||
size: 'small' as const,
|
||||
},
|
||||
inputDefaults: {
|
||||
size: 'small' as const,
|
||||
},
|
||||
selectDefaults: {
|
||||
size: 'small' as const,
|
||||
showSearch: true,
|
||||
},
|
||||
};
|
||||
|
||||
export default {
|
||||
config: antdConfig,
|
||||
message: appMessage,
|
||||
notification: appNotification,
|
||||
};
|
||||
Reference in New Issue
Block a user