diff --git a/public/example_report.pdf b/public/example_report.pdf index 3510aa0..fc7270a 100644 Binary files a/public/example_report.pdf and b/public/example_report.pdf differ diff --git a/src/migration-wizard/steps/discovery/ReportTable.tsx b/src/migration-wizard/steps/discovery/ReportTable.tsx index 7370229..b20505f 100644 --- a/src/migration-wizard/steps/discovery/ReportTable.tsx +++ b/src/migration-wizard/steps/discovery/ReportTable.tsx @@ -8,11 +8,13 @@ export namespace ReportTable { data: DataList; fields: Array; style?: React.CSSProperties; + withoutBorder?: boolean; }; } export function ReportTable( props: ReportTable.Props, + withoutBorder = false ): React.ReactNode { const { columns, data, fields, style } = props; @@ -20,15 +22,15 @@ export function ReportTable( - + {columns.map((name, index) => ( @@ -37,9 +39,9 @@ export function ReportTable( {data.map((item, idx) => ( - + {fields.map((f, fieldIdx) => ( -
{name}
+ {' '} {item[f] === '' || item[f] === undefined ? '-' diff --git a/src/migration-wizard/steps/discovery/assessment-report/Dashboard.css b/src/migration-wizard/steps/discovery/assessment-report/Dashboard.css new file mode 100644 index 0000000..cc4086c --- /dev/null +++ b/src/migration-wizard/steps/discovery/assessment-report/Dashboard.css @@ -0,0 +1,54 @@ +.dashboard-card-clip { + clip-path: inset(0 round 10px); + background: #fff; + height: 100%; + width: 100%; + } + .dashboard-card-scroll { + height: 100%; + min-height: 300px; + max-height: 500px; + overflow: auto; + display: flex; + flex-direction: column; + } +.dashboard-equal-height-row { + display: flex; + gap: var(--pf-global--gutter); + align-items: stretch; +} + +.dashboard-equal-height { + display: flex; + flex-direction: column; + flex: 1 1 0; + height: 100%; +} +.pf-v5-c-card { + height: 100%; + display: flex; + flex-direction: column; + border-radius: 10px !important; +} +.dashboard-card { + border: 1px solid #d2d2d2 !important; + border-radius: 10px; + box-shadow: 0 2px 8px rgba(0,0,0,0.08); + min-height: 280px; + max-height: 340px; + height: 100%; + display: flex; + flex-direction: column; + justify-content: space-between; +} +.dashboard-card-border { + border: 1px solid #d2d2d2 !important; + border-radius: 10px; + box-shadow: 0 2px 8px rgba(0,0,0,0.08); +} +.dashboard-card-print { + height: 100%; +} +.table-without-border { + border: none !important; +} \ No newline at end of file diff --git a/src/migration-wizard/steps/discovery/assessment-report/Dashboard.tsx b/src/migration-wizard/steps/discovery/assessment-report/Dashboard.tsx index f218cfa..c0b7d7a 100644 --- a/src/migration-wizard/steps/discovery/assessment-report/Dashboard.tsx +++ b/src/migration-wizard/steps/discovery/assessment-report/Dashboard.tsx @@ -19,6 +19,8 @@ import { StorageOverview } from './StorageOverview'; import { OSDistribution } from './OSDistribution'; import { Datastores } from './Datastores'; +import './Dashboard.css'; + interface Props { infra: Infra; cpuCores: VMResourceBreakdown; @@ -27,70 +29,66 @@ interface Props { isExportMode?: boolean; } - - -const getCardStyle = (isExportMode?: boolean): React.CSSProperties => - isExportMode - ? { } - : { - height: '400px', - overflow: 'auto', - }; - -export const Dashboard: React.FC = ({ infra, cpuCores, ramGB, vms, isExportMode }) => { - - return( - - - - - - - - -
+export const Dashboard: React.FC = ({ + infra, + cpuCores, + ramGB, + vms, + isExportMode, +}) => { + return ( + + + + + + + + -
-
- -
- -
-
-
-
- - - -
+ + + + + + + + + -
-
- -
- -
-
-
-
-
- - - - - -
) + + + + + + + + + + + + + + + + + ); }; diff --git a/src/migration-wizard/steps/discovery/assessment-report/Datastores.tsx b/src/migration-wizard/steps/discovery/assessment-report/Datastores.tsx index 2743b9f..2bee8ff 100644 --- a/src/migration-wizard/steps/discovery/assessment-report/Datastores.tsx +++ b/src/migration-wizard/steps/discovery/assessment-report/Datastores.tsx @@ -3,35 +3,50 @@ import { Card, CardBody, CardTitle, + Icon, Progress, } from '@patternfly/react-core'; import { Datastore } from '@migration-planner-ui/api-client/models'; import { ReportTable } from '../ReportTable'; - +import { ExclamationCircleIcon, CheckCircleIcon } from '@patternfly/react-icons'; +import { global_danger_color_100 as globalDangerColor100 } from '@patternfly/react-tokens/dist/js/global_danger_color_100'; +import { global_success_color_100 as globalSuccessColor100 } from '@patternfly/react-tokens/dist/js/global_success_color_100'; interface DatastoresProps { - datastores: Datastore[]; - isExportMode: boolean; - } - - export const Datastores: React.FC = ({ - datastores, - isExportMode = false, - }) => { - const tableWidth = isExportMode ? "100%" : "55rem"; + datastores: Datastore[]; + isExportMode: boolean; +} + +export const Datastores: React.FC = ({ + datastores, + isExportMode = false, +}) => { + const tableWidth = isExportMode ? '100%' : '55rem'; + const tableHeight = isExportMode ? '100%' : '250px'; return ( - - Datastores - + + + Datastores + + +
data={datastores.map((ds) => ({ ...ds, usage: ( -
+
), + hardwareAcceleratedMoveDisplay: ds.hardwareAcceleratedMove ? ( + + + + ) : ( + + + + ), }))} - columns={[ "Type", "Vendor", "Storage offload support", "Protocol type", "Model", "Total capacity", "Usage %"]} - fields={["type", "vendor", "hardwareAcceleratedMove", "protocolType", "model", "totalCapacityGB", , "usage"]} + columns={[ + 'Type', + 'Vendor', + 'Storage offload support', + 'Protocol type', + 'Model', + 'Total capacity', + 'Usage %', + ]} + fields={[ + 'type', + 'vendor', + 'hardwareAcceleratedMoveDisplay', + 'protocolType', + 'model', + 'totalCapacityGB', + , + 'usage', + ]} style={{ width: tableWidth }} + withoutBorder /> - - +
+ + ); }; diff --git a/src/migration-wizard/steps/discovery/assessment-report/InfastructureOverview.tsx b/src/migration-wizard/steps/discovery/assessment-report/InfastructureOverview.tsx index a233800..7969807 100644 --- a/src/migration-wizard/steps/discovery/assessment-report/InfastructureOverview.tsx +++ b/src/migration-wizard/steps/discovery/assessment-report/InfastructureOverview.tsx @@ -14,25 +14,25 @@ interface Props { export const InfrastructureOverview: React.FC = ({ infra, cpuCores, ramGB}) => ( - + Clusters {infra.totalClusters} - + Hosts {infra.totalHosts} - + CPU Cores {cpuCores.total} - + Total Memory {Humanize.fileSize(ramGB.total * 1024 ** 3, 0)} diff --git a/src/migration-wizard/steps/discovery/assessment-report/NetworkTopology.tsx b/src/migration-wizard/steps/discovery/assessment-report/NetworkTopology.tsx index 86810b7..6fc719d 100644 --- a/src/migration-wizard/steps/discovery/assessment-report/NetworkTopology.tsx +++ b/src/migration-wizard/steps/discovery/assessment-report/NetworkTopology.tsx @@ -1,29 +1,34 @@ import React from 'react'; -import { - Card, - CardBody, - CardTitle, -} from '@patternfly/react-core'; +import { Card, CardBody, CardTitle } from '@patternfly/react-core'; import { InfraNetworksInner } from '@migration-planner-ui/api-client/models'; import { ReportTable } from '../ReportTable'; import NetworkIcon from '@patternfly/react-icons/dist/esm/icons/network-icon'; interface NetworkTopologyProps { - networks: InfraNetworksInner[] + networks: InfraNetworksInner[]; + isExportMode?: boolean; } -export const NetworkTopology: React.FC = ({networks}) => { - +export const NetworkTopology: React.FC = ({ + networks, + isExportMode=false +}) => { + const tableHeight = isExportMode ? '100%': '250px'; return ( - - Network Topology - + + + Network Topology + + +
data={networks} columns={['Name', 'Type', 'VlanId']} fields={['name', 'type', 'vlanId']} - /> - - + withoutBorder + /> +
+
+
); }; diff --git a/src/migration-wizard/steps/discovery/assessment-report/OSDistribution.tsx b/src/migration-wizard/steps/discovery/assessment-report/OSDistribution.tsx index eeb18dd..9b68b43 100644 --- a/src/migration-wizard/steps/discovery/assessment-report/OSDistribution.tsx +++ b/src/migration-wizard/steps/discovery/assessment-report/OSDistribution.tsx @@ -1,29 +1,65 @@ import React from 'react'; import { Card, CardBody, CardTitle } from '@patternfly/react-core'; - import { Chart, ChartAxis, ChartBar, ChartGroup, ChartLabel, - ChartLegend, ChartThemeColor, - ChartTooltip, } from '@patternfly/react-charts'; interface OSDistributionProps { osData: { [osName: string]: number; }; + isExportMode?: boolean; } -export const OSDistribution: React.FC = ({ osData }) => { +export const OSDistribution: React.FC = ({ osData, isExportMode = false }) => { + const tableHeight = isExportMode ? '100%' : '200px'; + return ( - + Operating Systems - +
+
+ + {'Supported'} +
+
+ + {'Unsupported'} +
+
+
+
+ +
); @@ -31,74 +67,71 @@ export const OSDistribution: React.FC = ({ osData }) => { interface OSBarChartProps { osData: { [osName: string]: number }; + isExportMode?: boolean; } -export const OSBarChart: React.FC = ({ osData }) => { +export const OSBarChart: React.FC = ({ osData, isExportMode }) => { const dataEntries = Object.entries(osData).filter(([os]) => os.trim() !== ''); - const sorted = dataEntries.sort(([, a], [, b]) => a - b); + const sorted = dataEntries.sort(([, a], [, b]) => a - b); + + const chartHeight = sorted.length * 35 + 100; + const chartWidth = 500; const chartData = sorted.map(([os, count]) => ({ x: os, y: count, label: `${count} VMs`, + fill: os.toLowerCase().includes('unsupported') ? '#d9534f' : '#28a745', })); - const chartHeight = sorted.length * 35 + 100; - return ( -
- - - - - - datum.label} - labelComponent={ - - } - /> - - - - + -
+ + + datum.fill, // usa el color definido por cada dato + }, + }} + labels={({ datum }) => datum.label} + labelComponent={ + + } + /> + + ); }; diff --git a/src/migration-wizard/steps/discovery/assessment-report/StorageOverview.tsx b/src/migration-wizard/steps/discovery/assessment-report/StorageOverview.tsx index 1a7ac55..de31be7 100644 --- a/src/migration-wizard/steps/discovery/assessment-report/StorageOverview.tsx +++ b/src/migration-wizard/steps/discovery/assessment-report/StorageOverview.tsx @@ -14,32 +14,24 @@ interface DiskHistogramProps { data: number[]; minValue: number; step: number; + isExportMode?: boolean; } export const StorageOverview: React.FC = ({ data, minValue, step, + isExportMode=false }) => { + const tableHeight = isExportMode ? '100%': '210px'; return ( - - Disks + + + Disks + -
-
- Disk Size Distribution -
- - {/* Leyenda */} -
+
Disk Size Distribution +
= ({ marginRight: 6, }} /> - {'Easy'} + {'Small'}
= ({ marginRight: 6, }} /> - {'Hard'} + {'Large'}
-
+
+ + +
+
); @@ -107,23 +105,23 @@ export const DiskUsageHistogram: React.FC = ({ const chartHeight = chartData.length * 35 + 100; return ( -
+ = ({ axis: { stroke: 'none' }, ticks: { stroke: 'none' }, grid: { stroke: 'none' }, + tickLabels: { fontSize: 12 }, }} /> @@ -142,7 +141,7 @@ export const DiskUsageHistogram: React.FC = ({ } style={{ @@ -155,10 +154,10 @@ export const DiskUsageHistogram: React.FC = ({ return '#d9534f'; }, }, + labels:{fontSize: 10} }} /> -
); }; diff --git a/src/migration-wizard/steps/discovery/assessment-report/VMMigrationStatus.tsx b/src/migration-wizard/steps/discovery/assessment-report/VMMigrationStatus.tsx index fa0dfd5..c313bdf 100644 --- a/src/migration-wizard/steps/discovery/assessment-report/VMMigrationStatus.tsx +++ b/src/migration-wizard/steps/discovery/assessment-report/VMMigrationStatus.tsx @@ -1,13 +1,6 @@ import React from 'react'; -import { - ChartDonut, - ChartLegend, -} from '@patternfly/react-charts'; -import { - Card, - CardBody, - CardTitle, -} from '@patternfly/react-core'; +import { ChartDonut, ChartLegend } from '@patternfly/react-charts'; +import { Card, CardBody, CardTitle } from '@patternfly/react-core'; import VirtualMachineIcon from '@patternfly/react-icons/dist/esm/icons/virtual-machine-icon'; interface VmMigrationStatusProps { @@ -15,10 +8,12 @@ interface VmMigrationStatusProps { migratable: number; nonMigratable: number; }; + isExportMode?: boolean; } export const VMMigrationStatus: React.FC = ({ data, + isExportMode=false }) => { const chartData = [ { x: 'Migratable', y: data.migratable }, @@ -26,32 +21,51 @@ export const VMMigrationStatus: React.FC = ({ ]; return ( - - VM Migration Status + + + VM Migration Status + -
- `${datum.x}: ${datum.y}`} - colorScale={['#28a745', '#dc3545']} // Verde y rojo personalizados - innerRadius={100} - constrainToVisibleArea - title={`${data.migratable + data.nonMigratable}`} - subTitle="VMs" - /> - + > + `${datum.x}: ${datum.y}`} + colorScale={['#28a745', '#dc3545']} + constrainToVisibleArea + title={`${data.migratable + data.nonMigratable}`} + subTitle="VMs" + /> +
+ +