forked from BLC/sgeUpdated
278 lines
8.6 KiB
JavaScript
278 lines
8.6 KiB
JavaScript
import React, { useState, useEffect, useMemo } from "react";
|
|
import { MaterialReactTable } from "material-react-table";
|
|
import { useDispatch, useSelector } from "react-redux";
|
|
import { useTranslation } from "react-i18next";
|
|
import {
|
|
Card,
|
|
CardHeader,
|
|
CardTitle,
|
|
Alert,
|
|
Row,
|
|
Col,
|
|
Label,
|
|
} from "reactstrap";
|
|
import { getVMEmissionSummary } from "../../redux/actions/mainDataTables/index";
|
|
import { getDataCenters } from "../../redux/actions/dataCenter";
|
|
import { editNumbers } from "../../components/edit-numbers";
|
|
import Select from "react-select";
|
|
|
|
function MainDataTables() {
|
|
const { t } = useTranslation();
|
|
const dispatch = useDispatch();
|
|
const mainDataTablesStore = useSelector((state) => state.mainDataTables);
|
|
const dataCenterStore = useSelector((state) => state.dataCenter);
|
|
const [error, setError] = useState(null);
|
|
const [selectedDataCenter, setSelectedDataCenter] = useState(null);
|
|
const [dataCenterOptions, setDataCenterOptions] = useState([]);
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
// Fetch datacenters on component mount
|
|
useEffect(() => {
|
|
dispatch(getDataCenters());
|
|
}, [dispatch]);
|
|
|
|
// Update datacenter options when datacenters are loaded
|
|
useEffect(() => {
|
|
if (dataCenterStore?.dataCenters?.length > 0) {
|
|
const options = dataCenterStore.dataCenters.map((dataCenter) => ({
|
|
value: dataCenter.id,
|
|
label: dataCenter.dataCenter,
|
|
externalId: dataCenter.externalId,
|
|
}));
|
|
setDataCenterOptions(options);
|
|
}
|
|
}, [dataCenterStore?.dataCenters]);
|
|
|
|
// Fetch VM emission data when datacenter is selected
|
|
useEffect(() => {
|
|
if (selectedDataCenter?.value) {
|
|
const fetchData = async () => {
|
|
try {
|
|
setLoading(true);
|
|
setError(null);
|
|
await dispatch(getVMEmissionSummary(selectedDataCenter.value));
|
|
} catch (err) {
|
|
console.error("Error in MainDataTables:", err);
|
|
setError(err.message);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
fetchData();
|
|
}
|
|
}, [selectedDataCenter, dispatch]);
|
|
|
|
// Memoize columns to prevent re-renders
|
|
const columns = useMemo(
|
|
() => [
|
|
{
|
|
header: t("VM ID"),
|
|
accessorKey: "vmId",
|
|
size: 150,
|
|
Cell: ({ cell }) => <span>{cell.getValue() || "-"}</span>,
|
|
},
|
|
{
|
|
header: t("VM Name"),
|
|
accessorKey: "vmName",
|
|
size: 200,
|
|
Cell: ({ cell }) => <span>{cell.getValue() || "-"}</span>,
|
|
},
|
|
{
|
|
header: t("VM Power"),
|
|
accessorKey: "vmPower",
|
|
size: 120,
|
|
Cell: ({ cell }) => <span>{editNumbers(cell.getValue()) || "-"}</span>,
|
|
},
|
|
{
|
|
header: t("VM Status"),
|
|
accessorKey: "vmStatus",
|
|
size: 100,
|
|
Cell: ({ cell }) => <span>{cell.getValue() || "-"}</span>,
|
|
},
|
|
{
|
|
header: t("Total Emission"),
|
|
accessorKey: "totalEmission",
|
|
size: 150,
|
|
Cell: ({ cell }) => <span>{editNumbers(cell.getValue()) || "-"}</span>,
|
|
},
|
|
{
|
|
header: t("Physical Machine"),
|
|
accessorKey: "physicalMachine",
|
|
size: 150,
|
|
Cell: ({ cell }) => <span>{cell.getValue() || "-"}</span>,
|
|
},
|
|
{
|
|
header: t("Cloud System"),
|
|
accessorKey: "cloudSystem",
|
|
size: 150,
|
|
Cell: ({ cell }) => <span>{cell.getValue() || "-"}</span>,
|
|
},
|
|
{
|
|
header: t("Data Center"),
|
|
accessorKey: "dataCenter",
|
|
size: 150,
|
|
Cell: ({ cell }) => <span>{cell.getValue() || "-"}</span>,
|
|
},
|
|
{
|
|
header: "CO2",
|
|
accessorKey: "co2",
|
|
size: 100,
|
|
Cell: ({ cell }) => <span>{editNumbers(cell.getValue()) || "-"}</span>,
|
|
},
|
|
{
|
|
header: "CH4",
|
|
accessorKey: "ch4",
|
|
size: 100,
|
|
Cell: ({ cell }) => <span>{editNumbers(cell.getValue()) || "-"}</span>,
|
|
},
|
|
{
|
|
header: "N2O",
|
|
accessorKey: "n2o",
|
|
size: 100,
|
|
Cell: ({ cell }) => <span>{editNumbers(cell.getValue()) || "-"}</span>,
|
|
},
|
|
{
|
|
header: t("Created Date"),
|
|
accessorKey: "createdDate",
|
|
size: 180,
|
|
Cell: ({ cell }) => (
|
|
<span>
|
|
{cell.getValue() ? new Date(cell.getValue()).toLocaleString() : "-"}
|
|
</span>
|
|
),
|
|
sortable: true,
|
|
},
|
|
],
|
|
[t]
|
|
);
|
|
|
|
// Memoize table data to prevent unnecessary re-renders
|
|
const tableData = useMemo(() => {
|
|
const data = mainDataTablesStore?.vmEmissionSummary || [];
|
|
console.log("VM Emission data count:", data.length);
|
|
return data;
|
|
}, [mainDataTablesStore?.vmEmissionSummary]);
|
|
|
|
if (error) {
|
|
return (
|
|
<Alert color="danger" className="m-2">
|
|
Error loading data: {error}
|
|
</Alert>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div style={{ marginTop: "2%" }}>
|
|
<Card>
|
|
<CardHeader className="border-bottom">
|
|
<CardTitle tag="h4">{t("Raw Data")}</CardTitle>
|
|
{tableData.length > 0 && (
|
|
<small className="text-muted">
|
|
{tableData.length} records loaded
|
|
</small>
|
|
)}
|
|
</CardHeader>
|
|
|
|
{/* Datacenter Selection */}
|
|
<div className="p-3 border-bottom">
|
|
<Row>
|
|
<Col md="6">
|
|
<Label for="datacenter-select">{t("Data Center")}</Label>
|
|
<Select
|
|
id="datacenter-select"
|
|
value={selectedDataCenter}
|
|
onChange={setSelectedDataCenter}
|
|
options={dataCenterOptions}
|
|
placeholder={t("Select a data center...")}
|
|
isClearable
|
|
isSearchable
|
|
isLoading={dataCenterStore?.loading}
|
|
noOptionsMessage={() => t("No data centers available")}
|
|
styles={{
|
|
menu: (provided) => ({
|
|
...provided,
|
|
zIndex: 9999, // Ensure dropdown appears above other elements
|
|
}),
|
|
}}
|
|
menuPortalTarget={document.body} // Render dropdown in body to avoid container overflow
|
|
/>
|
|
</Col>
|
|
</Row>
|
|
</div>
|
|
|
|
{selectedDataCenter ? (
|
|
<MaterialReactTable
|
|
columns={columns}
|
|
data={tableData}
|
|
// Performance optimizations for large datasets
|
|
enableColumnFilters={true}
|
|
enableFilters={true}
|
|
enableGlobalFilter={true}
|
|
enablePagination={true}
|
|
enableColumnResizing={true} // Disable resizing for better performance
|
|
enableStickyHeader={true}
|
|
enableRowVirtualization={true} // Enable virtualization for large datasets
|
|
enableColumnVirtualization={false} // Keep columns visible
|
|
// Pagination settings for large datasets
|
|
initialState={{
|
|
pagination: {
|
|
pageSize: 100, // Reduce page size for better performance
|
|
pageIndex: 0,
|
|
},
|
|
sorting: [{ id: "createdDate", desc: true }],
|
|
density: "compact",
|
|
}}
|
|
// Performance-optimized table props
|
|
muiTableContainerProps={{
|
|
sx: {
|
|
maxHeight: "calc(100vh - 250px)",
|
|
minHeight: "400px",
|
|
},
|
|
}}
|
|
muiTableProps={{
|
|
sx: {
|
|
tableLayout: "fixed", // Better performance with fixed layout
|
|
},
|
|
}}
|
|
// Pagination options
|
|
muiTablePaginationProps={{
|
|
rowsPerPageOptions: [10, 25, 50, 100],
|
|
showFirstButton: true,
|
|
showLastButton: true,
|
|
}}
|
|
// Loading and error states
|
|
state={{
|
|
isLoading: loading || mainDataTablesStore?.loading,
|
|
showProgressBars: loading || mainDataTablesStore?.loading,
|
|
showSkeletons: loading || mainDataTablesStore?.loading,
|
|
}}
|
|
// Disable features that can slow down large tables
|
|
enableRowSelection={false}
|
|
enableColumnOrdering={true}
|
|
enableColumnDragging={false}
|
|
enableDensityToggle={false}
|
|
enableFullScreenToggle={false}
|
|
// Custom loading overlay
|
|
renderProgressBarCell={({ cell }) => (
|
|
<div
|
|
style={{
|
|
width: "100%",
|
|
height: "20px",
|
|
backgroundColor: "#f0f0f0",
|
|
}}
|
|
/>
|
|
)}
|
|
/>
|
|
) : (
|
|
<div className="p-4 text-center text-muted">
|
|
{t("Please select a data center to view raw data")}
|
|
</div>
|
|
)}
|
|
</Card>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export { MainDataTables };
|
|
export default MainDataTables;
|