mirror of
https://github.com/kjanat/livedash-node.git
synced 2026-01-16 14:12:10 +01:00
feat: add repository pattern, service layer architecture, and scheduler management
- Implement repository pattern for data access layer - Add comprehensive service layer for business logic - Create scheduler management system with health monitoring - Add bounded buffer utility for memory management - Enhance security audit logging with retention policies
This commit is contained in:
@ -32,19 +32,14 @@ function createDynamicComponent<T = object>(
|
||||
options?: {
|
||||
loading?: ComponentType;
|
||||
ssr?: boolean;
|
||||
suspense?: boolean;
|
||||
}
|
||||
) {
|
||||
const {
|
||||
loading: LoadingComponent = LoadingSpinner,
|
||||
ssr = true,
|
||||
suspense = false,
|
||||
} = options || {};
|
||||
const { loading: LoadingComponent = LoadingSpinner, ssr = true } =
|
||||
options || {};
|
||||
|
||||
return dynamic(importFunc, {
|
||||
loading: () => <LoadingComponent />,
|
||||
ssr,
|
||||
suspense,
|
||||
});
|
||||
}
|
||||
|
||||
@ -70,30 +65,33 @@ export const DynamicAreaChart = createDynamicComponent(
|
||||
);
|
||||
|
||||
// D3 components for data visualization (also heavy)
|
||||
export const DynamicWordCloud = createDynamicComponent(
|
||||
() =>
|
||||
import("../components/charts/WordCloud").then((mod) => ({
|
||||
default: mod.WordCloud,
|
||||
})),
|
||||
{ loading: LoadingSkeleton, ssr: false }
|
||||
);
|
||||
// TODO: Create WordCloud component
|
||||
// export const DynamicWordCloud = createDynamicComponent(
|
||||
// () =>
|
||||
// import("../components/charts/WordCloud").then((mod) => ({
|
||||
// default: mod.WordCloud,
|
||||
// })),
|
||||
// { loading: LoadingSkeleton, ssr: false }
|
||||
// );
|
||||
|
||||
export const DynamicTreeMap = createDynamicComponent(
|
||||
() =>
|
||||
import("../components/charts/TreeMap").then((mod) => ({
|
||||
default: mod.TreeMap,
|
||||
})),
|
||||
{ loading: LoadingSkeleton, ssr: false }
|
||||
);
|
||||
// TODO: Create TreeMap component
|
||||
// export const DynamicTreeMap = createDynamicComponent(
|
||||
// () =>
|
||||
// import("../components/charts/TreeMap").then((mod) => ({
|
||||
// default: mod.TreeMap,
|
||||
// })),
|
||||
// { loading: LoadingSkeleton, ssr: false }
|
||||
// );
|
||||
|
||||
// Map components (Leaflet is heavy)
|
||||
export const DynamicLeafletMap = createDynamicComponent(
|
||||
() =>
|
||||
import("../components/maps/LeafletMap").then((mod) => ({
|
||||
default: mod.LeafletMap,
|
||||
})),
|
||||
{ loading: LoadingSkeleton, ssr: false }
|
||||
);
|
||||
// TODO: Create LeafletMap component
|
||||
// export const DynamicLeafletMap = createDynamicComponent(
|
||||
// () =>
|
||||
// import("../components/maps/LeafletMap").then((mod) => ({
|
||||
// default: mod.LeafletMap,
|
||||
// })),
|
||||
// { loading: LoadingSkeleton, ssr: false }
|
||||
// );
|
||||
|
||||
// Admin panels (only loaded for admin users)
|
||||
export const DynamicAuditLogsPanel = createDynamicComponent(
|
||||
@ -104,95 +102,107 @@ export const DynamicAuditLogsPanel = createDynamicComponent(
|
||||
{ loading: LoadingSkeleton }
|
||||
);
|
||||
|
||||
export const DynamicSecurityMonitoring = createDynamicComponent(
|
||||
() =>
|
||||
import("../components/admin/SecurityMonitoring").then((mod) => ({
|
||||
default: mod.SecurityMonitoring,
|
||||
})),
|
||||
{ loading: LoadingSkeleton }
|
||||
);
|
||||
// TODO: Create SecurityMonitoring component
|
||||
// export const DynamicSecurityMonitoring = createDynamicComponent(
|
||||
// () =>
|
||||
// import("../components/admin/SecurityMonitoring").then((mod) => ({
|
||||
// default: mod.SecurityMonitoring,
|
||||
// })),
|
||||
// { loading: LoadingSkeleton }
|
||||
// );
|
||||
|
||||
// CSV processing components (only loaded when needed)
|
||||
export const DynamicCSVUploader = createDynamicComponent(
|
||||
() =>
|
||||
import("../components/csv/CSVUploader").then((mod) => ({
|
||||
default: mod.CSVUploader,
|
||||
})),
|
||||
{ loading: LoadingSpinner }
|
||||
);
|
||||
// TODO: Create CSVUploader component
|
||||
// export const DynamicCSVUploader = createDynamicComponent(
|
||||
// () =>
|
||||
// import("../components/csv/CSVUploader").then((mod) => ({
|
||||
// default: mod.CSVUploader,
|
||||
// })),
|
||||
// { loading: LoadingSpinner }
|
||||
// );
|
||||
|
||||
export const DynamicCSVProcessor = createDynamicComponent(
|
||||
() =>
|
||||
import("../components/csv/CSVProcessor").then((mod) => ({
|
||||
default: mod.CSVProcessor,
|
||||
})),
|
||||
{ loading: LoadingSpinner }
|
||||
);
|
||||
// TODO: Create CSVProcessor component
|
||||
// export const DynamicCSVProcessor = createDynamicComponent(
|
||||
// () =>
|
||||
// import("../components/csv/CSVProcessor").then((mod) => ({
|
||||
// default: mod.CSVProcessor,
|
||||
// })),
|
||||
// { loading: LoadingSpinner }
|
||||
// );
|
||||
|
||||
// Data table components (heavy when dealing with large datasets)
|
||||
export const DynamicDataTable = createDynamicComponent(
|
||||
() =>
|
||||
import("../components/tables/DataTable").then((mod) => ({
|
||||
default: mod.DataTable,
|
||||
})),
|
||||
{ loading: LoadingSkeleton }
|
||||
);
|
||||
// TODO: Create DataTable component
|
||||
// export const DynamicDataTable = createDynamicComponent(
|
||||
// () =>
|
||||
// import("../components/tables/DataTable").then((mod) => ({
|
||||
// default: mod.DataTable,
|
||||
// })),
|
||||
// { loading: LoadingSkeleton }
|
||||
// );
|
||||
|
||||
// Modal components (can be heavy with complex forms)
|
||||
export const DynamicUserInviteModal = createDynamicComponent(
|
||||
() =>
|
||||
import("../components/modals/UserInviteModal").then((mod) => ({
|
||||
default: mod.UserInviteModal,
|
||||
})),
|
||||
{ loading: LoadingSpinner }
|
||||
);
|
||||
// TODO: Create UserInviteModal component
|
||||
// export const DynamicUserInviteModal = createDynamicComponent(
|
||||
// () =>
|
||||
// import("../components/modals/UserInviteModal").then((mod) => ({
|
||||
// default: mod.UserInviteModal,
|
||||
// })),
|
||||
// { loading: LoadingSpinner }
|
||||
// );
|
||||
|
||||
export const DynamicCompanySettingsModal = createDynamicComponent(
|
||||
() =>
|
||||
import("../components/modals/CompanySettingsModal").then((mod) => ({
|
||||
default: mod.CompanySettingsModal,
|
||||
})),
|
||||
{ loading: LoadingSpinner }
|
||||
);
|
||||
// TODO: Create CompanySettingsModal component
|
||||
// export const DynamicCompanySettingsModal = createDynamicComponent(
|
||||
// () =>
|
||||
// import("../components/modals/CompanySettingsModal").then((mod) => ({
|
||||
// default: mod.CompanySettingsModal,
|
||||
// })),
|
||||
// { loading: LoadingSpinner }
|
||||
// );
|
||||
|
||||
// Text editor components (rich text editors are typically heavy)
|
||||
export const DynamicRichTextEditor = createDynamicComponent(
|
||||
() =>
|
||||
import("../components/editor/RichTextEditor").then((mod) => ({
|
||||
default: mod.RichTextEditor,
|
||||
})),
|
||||
{ loading: LoadingSpinner, ssr: false }
|
||||
);
|
||||
// TODO: Create RichTextEditor component
|
||||
// export const DynamicRichTextEditor = createDynamicComponent(
|
||||
// () =>
|
||||
// import("../components/editor/RichTextEditor").then((mod) => ({
|
||||
// default: mod.RichTextEditor,
|
||||
// })),
|
||||
// { loading: LoadingSpinner, ssr: false }
|
||||
// );
|
||||
|
||||
// PDF viewers and generators (heavy libraries)
|
||||
export const DynamicPDFViewer = createDynamicComponent(
|
||||
() =>
|
||||
import("../components/pdf/PDFViewer").then((mod) => ({
|
||||
default: mod.PDFViewer,
|
||||
})),
|
||||
{ loading: LoadingSpinner, ssr: false }
|
||||
);
|
||||
// TODO: Create PDFViewer component
|
||||
// export const DynamicPDFViewer = createDynamicComponent(
|
||||
// () =>
|
||||
// import("../components/pdf/PDFViewer").then((mod) => ({
|
||||
// default: mod.PDFViewer,
|
||||
// })),
|
||||
// { loading: LoadingSpinner, ssr: false }
|
||||
// );
|
||||
|
||||
// Animation libraries (Framer Motion, Lottie, etc.)
|
||||
export const DynamicAnimatedComponent = createDynamicComponent(
|
||||
() =>
|
||||
import("../components/animations/AnimatedComponent").then((mod) => ({
|
||||
default: mod.AnimatedComponent,
|
||||
})),
|
||||
{ loading: LoadingSpinner, ssr: false }
|
||||
);
|
||||
// TODO: Create AnimatedComponent
|
||||
// export const DynamicAnimatedComponent = createDynamicComponent(
|
||||
// () =>
|
||||
// import("../components/animations/AnimatedComponent").then((mod) => ({
|
||||
// default: mod.AnimatedComponent,
|
||||
// })),
|
||||
// { loading: LoadingSpinner, ssr: false }
|
||||
// );
|
||||
|
||||
// React wrapper for React.lazy with Suspense
|
||||
export function createLazyComponent<T = object>(
|
||||
export function createLazyComponent<
|
||||
T extends Record<string, any> = Record<string, any>,
|
||||
>(
|
||||
importFunc: () => Promise<{ default: ComponentType<T> }>,
|
||||
_fallback: ComponentType = LoadingSpinner
|
||||
fallback: ComponentType = LoadingSpinner
|
||||
) {
|
||||
const LazyComponent = lazy(importFunc);
|
||||
const FallbackComponent = fallback;
|
||||
|
||||
return function WrappedComponent(props: T) {
|
||||
return (
|
||||
<Suspense fallback={<fallback />}>
|
||||
<LazyComponent {...props} />
|
||||
<Suspense fallback={<FallbackComponent />}>
|
||||
<LazyComponent {...(props as T)} />
|
||||
</Suspense>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user