/*
Copyright (C) 2020 Cloudbase Solutions SRL
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
*/
import * as React from "react";
import { Collapse } from "react-collapse";
import { Link } from "react-router-dom";
import styled, { createGlobalStyle, css } from "styled-components";
import { DeploymentItem, ReplicaItem, TransferItem } from "@src/@types/MainItem";
import { MinionMachine, MinionPool } from "@src/@types/MinionPool";
import { ThemePalette, ThemeProps } from "@src/components/Theme";
import Arrow from "@src/components/ui/Arrow";
import DropdownLink from "@src/components/ui/Dropdowns/DropdownLink";
import { ItemReplicaBadge } from "@src/components/ui/Dropdowns/NotificationDropdown";
import StatusPill from "@src/components/ui/StatusComponents/StatusPill";
import DateUtils from "@src/utils/DateUtils";
import networkImage from "./images/network.svg";
const GlobalStyle = createGlobalStyle`
.ReactCollapse--collapse {
transition: height 0.4s ease-in-out;
}
`;
const Wrapper = styled.div``;
const NoMachines = styled.div`
text-align: center;
`;
const Header = styled.div`
display: flex;
align-items: center;
margin-bottom: 32px;
margin-left: 20px;
`;
const ArrowStyled = styled(Arrow)`
position: absolute;
left: -24px;
`;
const Row = styled.div`
position: relative;
padding: 8px 0;
border-top: 1px solid white;
transition: all ${ThemeProps.animations.swift};
&:last-child {
border-bottom: 0;
border-bottom-left-radius: ${ThemeProps.borderRadius};
border-bottom-right-radius: ${ThemeProps.borderRadius};
}
&:hover {
background: ${ThemePalette.grayscale[0]};
${ArrowStyled} {
opacity: 1;
}
}
cursor: pointer;
`;
const RowHeader = styled.div`
display: flex;
align-items: center;
padding: 0 16px;
`;
const RowHeaderColumn = styled.div`
display: flex;
align-items: center;
${ThemeProps.exactWidth("50%")}
`;
const HeaderName = styled.div`
overflow: hidden;
text-overflow: ellipsis;
${props => ThemeProps.exactWidth(`calc(100% - ${props.source ? 120 : 8}px)`)}
`;
const HeaderIcon = styled.div`
min-width: 16px;
min-height: 16px;
background: url("${networkImage}") center no-repeat;
margin-right: 16px;
`;
const HeaderFilter = styled.div``;
const HeaderText = styled.div`
margin-left: 16px;
`;
const RowBody = styled.div`
display: flex;
color: ${ThemePalette.grayscale[5]};
padding: 0 16px;
margin-top: 4px;
`;
const RowBodyColumn = styled.div`
margin-top: 8px;
&:first-child {
${ThemeProps.exactWidth("calc(50% - 70px)")}
margin-right: 88px;
}
&:last-child {
${ThemeProps.exactWidth("calc(50% - 16px)")}
}
`;
const RowBodyColumnValue = styled.div`
overflow-wrap: break-word;
`;
const MachinesWrapper = styled.div``;
const MachineWrapper = styled.div`
background: ${ThemePalette.grayscale[1]};
border-radius: ${ThemeProps.borderRadius};
`;
const MachineTitle = styled.div`
padding: 16px;
border-bottom: 1px solid #7f8795;
font-size: 16px;
`;
const MachineBody = styled.div`
padding: 16px;
`;
const MachineRow = styled.div<{ secondary?: boolean }>`
display: flex;
margin-bottom: 8px;
align-items: center;
${props =>
props.secondary
? css`
color: ${ThemePalette.grayscale[5]};
margin-bottom: 4px;
`
: ""}
`;
const ValueLink = styled(Link)`
display: flex;
color: ${ThemePalette.primary};
text-decoration: none;
cursor: pointer;
`;
type FilterType = "all" | "allocated" | "not-allocated";
type Props = {
item?: MinionPool | null;
replicas: ReplicaItem[];
deployments: DeploymentItem[];
};
type State = {
filterStatus: FilterType;
openedRows: string[];
};
class MinionPoolMachines extends React.Component {
state = {
filterStatus: "all" as FilterType,
openedRows: [],
};
get machines() {
return this.props.item?.minion_machines || [];
}
get filteredMachines() {
switch (this.state.filterStatus) {
case "all":
return this.machines;
case "allocated":
return this.machines.filter(
m =>
m.allocation_status === "ALLOCATED" ||
m.allocation_status === "AVAILABLE"
);
default:
return this.machines.filter(
m =>
m.allocation_status !== "ALLOCATED" &&
m.allocation_status !== "AVAILABLE"
);
}
}
handleRowClick(id: string) {
if (this.state.openedRows.find(i => i === id)) {
this.setState(prevState => ({
openedRows: prevState.openedRows.filter(i => i !== id),
}));
} else {
this.setState(prevState => ({
openedRows: [...prevState.openedRows, id],
}));
}
}
renderNoMachines() {
return (
There are no Minion Machines allocated to this Minion Pool
);
}
renderHeader() {
const plural = this.machines.length === 1 ? "" : "s";
return (
{
this.setState({
filterStatus: item.value as FilterType,
});
}}
/>
{this.machines.length} minion machine{plural},{" "}
{
this.machines.filter(
m =>
m.allocation_status === "ALLOCATED" ||
m.allocation_status === "AVAILABLE"
).length
}{" "}
allocated
);
}
renderConnectionInfo(machine: MinionMachine) {
const isOpened = Boolean(this.state.openedRows.find(i => i === machine.id));
return (
{
this.handleRowClick(machine.id);
}}
>
Connection Info
{Object.keys(machine.connection_info).map(prop => (
{prop}: {machine.connection_info[prop]}
))}
);
}
renderMachines() {
if (this.filteredMachines.length === 0) {
return No Minion Machines found;
}
return (
{this.filteredMachines.map(machine => {
const findTransferItem = (transferItems: TransferItem[]) =>
transferItems.find(i => i.id === machine.allocated_action);
const allocatedAction = machine.allocated_action
? findTransferItem(this.props.replicas) ||
findTransferItem(this.props.deployments)
: null;
return (
ID: {machine.id}
Allocation Status:{" "}
Power Status:{" "}
Created At:{" "}
{DateUtils.getLocalDate(machine.created_at).toFormat(
"yyyy-LL-dd HH:mm:ss"
)}
{machine.updated_at ? (
Updated At:{" "}
{DateUtils.getLocalDate(machine.updated_at).toFormat(
"yyyy-LL-dd HH:mm:ss"
)}
) : null}
{machine.last_used_at ? (
Last Used At:{" "}
{DateUtils.getLocalDate(machine.last_used_at).toFormat(
"yyyy-LL-dd HH:mm:ss"
)}
) : null}
{machine.allocated_action ? (
Allocated Action:
{allocatedAction ? (
<>
{allocatedAction.type === "replica" ? "TR" : "DE"}
{allocatedAction.instances[0]}
>
) : (
{machine.allocated_action}
)}
) : null}
{machine.connection_info
? this.renderConnectionInfo(machine)
: null}
);
})}
);
}
render() {
return (
{this.props.item?.minion_machines.length
? this.renderHeader()
: this.renderNoMachines()}
{this.props.item?.minion_machines.length ? this.renderMachines() : null}
);
}
}
export default MinionPoolMachines;