import type { Transition, UIRouter } from '@uirouter/core'; import type { UIViewAddress } from '@uirouter/react'; import { useParentView, useRouter } from '@uirouter/react'; import React from 'react'; import type { Subscription } from 'rxjs'; import { Instance } from './Instance'; import type { IInstance } from '../domain'; export interface IInstancesProps { instances: IInstance[]; highlight?: string; } export interface IInstancesState { detailsInstanceId: string; } export const Instances = (props: IInstancesProps) => { const router = useRouter(); const uiview = useParentView(); return ; }; export interface IInstancesInternalProps extends IInstancesProps { router: UIRouter; uiview: UIViewAddress; } class InstancesInternal extends React.Component { private subscription: Subscription; constructor(props: IInstancesInternalProps) { super(props); this.state = { detailsInstanceId: null, }; } public componentDidMount() { this.subscription = this.props.router.globals.success$.subscribe(this.onStateChange); } public componentWillUnmount() { this.subscription.unsubscribe(); } private onStateChange = (transition: Transition) => { const isShowingDetails = !!/\.instanceDetails/.exec(transition.to().name); const detailsInstanceId = isShowingDetails ? transition.params().instanceId : null; this.setState({ detailsInstanceId }); }; public shouldComponentUpdate(nextProps: IInstancesInternalProps, nextState: IInstancesState) { const propsKeys: Array = ['instances', 'highlight']; if (propsKeys.some((key) => this.props[key] !== nextProps[key])) { return true; } if (this.state.detailsInstanceId !== nextState.detailsInstanceId) { const ids = nextProps.instances.map((x) => x.id); if (ids.includes(this.state.detailsInstanceId) || ids.includes(nextState.detailsInstanceId)) { return true; } } return false; } private handleInstanceClicked = (instance: IInstance) => { const { router, uiview } = this.props; const params = { instanceId: instance.id, provider: instance.cloudProvider || instance.provider }; const options = { relative: uiview.context }; router.stateService.go('.instanceDetails', params, options); }; private partitionInstances(): IInstance[][] { const partitions: IInstance[][] = []; const instances = (this.props.instances || []).sort( (a, b) => a.launchTime - b.launchTime || a.id.localeCompare(b.id), ); if (!instances.length) { return partitions; } let currentPartition: IInstance[] = []; let currentState = instances[0].healthState; instances.forEach((i) => { if (i.healthState !== currentState) { partitions.push(currentPartition); currentPartition = []; } currentPartition.push(i); currentState = i.healthState; }); partitions.push(currentPartition); return partitions; } public render() { const partitions = this.partitionInstances(); return (
{partitions.map((p, i) => ( {p.map((instance) => ( ))} ))}
); } }