diff --git a/src/renderer/components/+workloads-deployments/deployment-details.tsx b/src/renderer/components/+workloads-deployments/deployment-details.tsx index 641eae79e7..112953e63a 100644 --- a/src/renderer/components/+workloads-deployments/deployment-details.tsx +++ b/src/renderer/components/+workloads-deployments/deployment-details.tsx @@ -42,6 +42,8 @@ import { KubeObjectMeta } from "../kube-object/kube-object-meta"; import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry"; import { ResourceType } from "../cluster-settings/components/cluster-metrics-setting"; import { ClusterStore } from "../../../common/cluster-store"; +import { replicaSetStore } from "../+workloads-replicasets/replicasets.store"; +import { DeploymentReplicaSets } from "./deployment-replicasets"; interface Props extends KubeObjectDetailsProps { } @@ -55,6 +57,7 @@ export class DeploymentDetails extends React.Component { componentDidMount() { podsStore.reloadAll(); + replicaSetStore.reloadAll(); } componentWillUnmount() { @@ -69,6 +72,7 @@ export class DeploymentDetails extends React.Component { const nodeSelector = deployment.getNodeSelectors(); const selectors = deployment.getSelectors(); const childPods = deploymentStore.getChildPods(deployment); + const replicaSets = replicaSetStore.getReplicaSetsByOwner(deployment); const metrics = deploymentStore.metrics; const isMetricHidden = ClusterStore.getInstance().isMetricHidden(ResourceType.Deployment); @@ -131,6 +135,7 @@ export class DeploymentDetails extends React.Component { + ); diff --git a/src/renderer/components/+workloads-deployments/deployment-replicasets.scss b/src/renderer/components/+workloads-deployments/deployment-replicasets.scss new file mode 100644 index 0000000000..0c04f54709 --- /dev/null +++ b/src/renderer/components/+workloads-deployments/deployment-replicasets.scss @@ -0,0 +1,36 @@ +.DeploymentDetails { + .ReplicaSets { + position: relative; + min-height: 80px; + + .Table { + margin: 0 (-$margin * 3); + } + + .TableCell { + &:first-child { + margin-left: $margin; + } + + &:last-child { + margin-right: $margin; + } + + &.name { + flex-grow: 2; + } + + &.warning { + @include table-cell-warning; + } + + &.namespace { + flex-grow: 1.2; + } + + &.actions { + @include table-cell-action; + } + } + } +} diff --git a/src/renderer/components/+workloads-deployments/deployment-replicasets.tsx b/src/renderer/components/+workloads-deployments/deployment-replicasets.tsx new file mode 100644 index 0000000000..8fbce9564d --- /dev/null +++ b/src/renderer/components/+workloads-deployments/deployment-replicasets.tsx @@ -0,0 +1,119 @@ +/** + * Copyright (c) 2021 OpenLens Authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +import "./deployment-replicasets.scss"; + +import React from "react"; +import { observer } from "mobx-react"; +import { ReplicaSet } from "../../api/endpoints"; +import { KubeObjectMenu, KubeObjectMenuProps } from "../kube-object/kube-object-menu"; +import { Spinner } from "../spinner"; +import { prevDefault, stopPropagation } from "../../utils"; +import { DrawerTitle } from "../drawer"; +import { Table, TableCell, TableHead, TableRow } from "../table"; +import { KubeObjectStatusIcon } from "../kube-object-status-icon"; +import { replicaSetStore } from "../+workloads-replicasets/replicasets.store"; +import { showDetails } from "../kube-object"; + + +enum sortBy { + name = "name", + namespace = "namespace", + pods = "pods", + age = "age", +} + +interface Props { + replicaSets: ReplicaSet[]; +} + +@observer +export class DeploymentReplicaSets extends React.Component { + private sortingCallbacks = { + [sortBy.name]: (replicaSet: ReplicaSet) => replicaSet.getName(), + [sortBy.namespace]: (replicaSet: ReplicaSet) => replicaSet.getNs(), + [sortBy.age]: (replicaSet: ReplicaSet) => replicaSet.metadata.creationTimestamp, + [sortBy.pods]: (replicaSet: ReplicaSet) => this.getPodsLength(replicaSet), + }; + + getPodsLength(replicaSet: ReplicaSet) { + return replicaSetStore.getChildPods(replicaSet).length; + } + + render() { + const { replicaSets } = this.props; + + if (!replicaSets.length && !replicaSetStore.isLoaded) return ( +
+ ); + if (!replicaSets.length) return null; + + return ( +
+ + + + Name + + Namespace + Pods + Age + + + { + replicaSets.map(replica => { + return ( + showDetails(replica.selfLink, false))} + > + {replica.getName()} + + {replica.getNs()} + {this.getPodsLength(replica)} + {replica.getAge()} + + + + + ); + }) + } +
+
+ ); + } +} + +export function ReplicaSetMenu(props: KubeObjectMenuProps) { + return ( + + ); +}