/* 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;