219 lines
6.5 KiB
TypeScript
219 lines
6.5 KiB
TypeScript
/**
|
|
* @author Martin Karkowski
|
|
* @email m.karkowski@zema.de
|
|
* @create date 2021-02-11 08:02:28
|
|
* @modify date 2021-02-11 13:45:57
|
|
* @desc [description]
|
|
*/
|
|
|
|
import React from "react";
|
|
import { Alert, Col, Container, Row, Table } from "react-bootstrap";
|
|
import {
|
|
nopeDispatcherManager
|
|
} from "../../lib/dispatcher/nopeDispatcherManager";
|
|
import { ENopeDispatcherStatus } from "../../lib/types/nope/nopeDispatcher.interface";
|
|
import { INopeObserver } from "../../lib/types/nope/nopeObservable.interface";
|
|
import { StatusBadgeComponent } from "./generic/StatusBadge";
|
|
import { InstanceDetailsComponent, InstanceDetailsState } from "./instance/InstanceDetails";
|
|
|
|
export class InstanceOverviewComponent extends React.Component<
|
|
{ dispatcher: nopeDispatcherManager; maxItemsInRow?: 2 | 3 | 4, renderDetails?: boolean },
|
|
{ connected: boolean; instances: InstanceDetailsState[][], maxItemsInRow: number }
|
|
> {
|
|
/**
|
|
* List containing Observables
|
|
*
|
|
* @private
|
|
* @type {INopeObserver[]}
|
|
* @memberof InstanceOverviewComponent
|
|
*/
|
|
private _observer: INopeObserver[] = [];
|
|
|
|
/**
|
|
* Function, which will be used to refresh the Nodes.
|
|
*/
|
|
private _refresh() {
|
|
if (this.props.dispatcher?.getHostInfos) {
|
|
// Get the connected Flag
|
|
const connected = this.props.dispatcher.communicator.connected.getContent();
|
|
const computingNodes = this.props.dispatcher.getHostInfos();
|
|
const computingNodesAsList = Object.getOwnPropertyNames(computingNodes).map(key => computingNodes[key]);
|
|
const allInstances = this.props.dispatcher.availableInstances.getContent();
|
|
console.log(allInstances.length);
|
|
const mappingIndexToName = new Map<string,number>();
|
|
const instances: InstanceDetailsState[] = allInstances.map((item,idx) => {
|
|
|
|
mappingIndexToName.set(item.identifier,idx);
|
|
|
|
return Object.assign({
|
|
status: ENopeDispatcherStatus.HEALTHY,
|
|
dispatchers: [],
|
|
redundant: false,
|
|
}, item);
|
|
});
|
|
|
|
for (const node of computingNodesAsList){
|
|
for (const instance of node.instances){
|
|
if (mappingIndexToName.has(instance.identifier)){
|
|
// Add the Dispatcher, update the Status of the Component
|
|
instances[mappingIndexToName.get(instance.identifier)].status = Math.max(instances[mappingIndexToName.get(instance.identifier)].status, instance.status);
|
|
instances[mappingIndexToName.get(instance.identifier)].dispatchers.push(instance.dispatcher);
|
|
instances[mappingIndexToName.get(instance.identifier)].redundant = instances[mappingIndexToName.get(instance.identifier)].dispatchers.length > 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
const renderingInstances: InstanceDetailsState[][] = [];
|
|
|
|
const maxItems = this.props.renderDetails
|
|
? this.props.maxItemsInRow || 2
|
|
: instances.length * 2 ;
|
|
|
|
// Function to Split the Dispatcher Array into an array containing max 3 elements.
|
|
for (let i = 0; i < instances.length; i = i + maxItems) {
|
|
renderingInstances.push(instances.slice(i, i + maxItems));
|
|
}
|
|
|
|
this.setState({
|
|
instances: renderingInstances,
|
|
connected,
|
|
maxItemsInRow: maxItems
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Function will be called if the Item has been rendered sucessfully.
|
|
*/
|
|
public componentDidMount(): void {
|
|
if (this.props.dispatcher?.getHostInfos) {
|
|
// Subscribe to the Instances.
|
|
const _this = this;
|
|
|
|
this._observer.push(
|
|
this.props.dispatcher.availableInstances.subscribe(() => {
|
|
console.log("HERE");
|
|
_this._refresh();
|
|
})
|
|
);
|
|
|
|
this._observer.push(
|
|
this.props.dispatcher.externalDispatchers.subscribe(() => {
|
|
console.log("HERE");
|
|
_this._refresh();
|
|
})
|
|
);
|
|
|
|
this._observer.push(
|
|
this.props.dispatcher.communicator.connected.subscribe(() => {
|
|
_this._refresh();
|
|
})
|
|
);
|
|
|
|
// Render the Elements
|
|
this._refresh();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Function, that will be called before the network fails.
|
|
*/
|
|
public componentWillUnmount(): void {
|
|
// Call the unmount
|
|
for (const _observer of this._observer) {
|
|
_observer.unsubscribe();
|
|
}
|
|
}
|
|
|
|
constructor(props) {
|
|
super(props);
|
|
this.state = {
|
|
connected: false,
|
|
instances: [],
|
|
maxItemsInRow: 1
|
|
};
|
|
}
|
|
|
|
public render() {
|
|
if (this.state.connected) {
|
|
|
|
if (this.props.renderDetails) {
|
|
const sm = Math.round(12 / this.state.maxItemsInRow);
|
|
return (
|
|
<Container>
|
|
{this.state.instances.map((row, idx_01) => {
|
|
return (
|
|
<Row
|
|
key={idx_01}
|
|
style={{ paddingTop: "0.5rem", paddingBottom: "0.5rem" }}
|
|
>
|
|
{row.map((item, idx_02) => {
|
|
return (
|
|
<Col key={`${idx_01}_${idx_02}`} sm={sm}>
|
|
<InstanceDetailsComponent description={item} renderDetails={true}></InstanceDetailsComponent>
|
|
</Col>
|
|
);
|
|
})}
|
|
</Row>
|
|
);
|
|
})}
|
|
</Container>
|
|
);
|
|
}
|
|
|
|
if (this.state.instances.length > 0) {
|
|
return (
|
|
<Table striped bordered hover>
|
|
<thead>
|
|
<tr>
|
|
<th>Name</th>
|
|
<th>Type</th>
|
|
<th>Status</th>
|
|
<th>Redundant</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{this.state.instances[0].map((item, idx) => (
|
|
<tr key={idx}>
|
|
<td>{item.identifier}</td>
|
|
<td><code>{item.type}</code></td>
|
|
<td>
|
|
<StatusBadgeComponent
|
|
status={item.status}
|
|
></StatusBadgeComponent>
|
|
</td>
|
|
<td>
|
|
{item.redundant.toString()}
|
|
</td>
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</Table>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<Alert variant={"warning"}>
|
|
No Instance Found <b>:'(</b>
|
|
</Alert>
|
|
);
|
|
|
|
|
|
|
|
|
|
} else {
|
|
return (
|
|
<>
|
|
<Alert variant={"danger"}>
|
|
Not able to connect to the Backend <b>:'(</b>
|
|
</Alert>
|
|
<p>
|
|
Please start a Nope-Backend with the following command:{" "}
|
|
<code>nope run -c io-server</code>
|
|
</p>
|
|
</>
|
|
);
|
|
}
|
|
}
|
|
}
|