1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Add persistent volumes info to storage class submenu (#2160)

Signed-off-by: vshakirova <vshakirova@mirantis.com>
This commit is contained in:
Violetta 2021-02-24 12:02:39 +04:00 committed by GitHub
parent 6876d774a5
commit 0d3505cfac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 145 additions and 1 deletions

View File

@ -70,6 +70,10 @@ export class PersistentVolume extends KubeObject {
getClaimRefName(): string { getClaimRefName(): string {
return this.spec.claimRef?.name ?? ""; return this.spec.claimRef?.name ?? "";
} }
getStorageClassName() {
return this.spec.storageClassName || "";
}
} }
export const persistentVolumeApi = new KubeApi({ export const persistentVolumeApi = new KubeApi({

View File

@ -10,14 +10,22 @@ import { KubeObjectDetailsProps } from "../kube-object";
import { StorageClass } from "../../api/endpoints"; import { StorageClass } from "../../api/endpoints";
import { KubeObjectMeta } from "../kube-object/kube-object-meta"; import { KubeObjectMeta } from "../kube-object/kube-object-meta";
import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry"; import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry";
import { storageClassStore } from "./storage-class.store";
import { VolumeDetailsList } from "../+storage-volumes/volume-details-list";
import { volumesStore } from "../+storage-volumes/volumes.store";
interface Props extends KubeObjectDetailsProps<StorageClass> { interface Props extends KubeObjectDetailsProps<StorageClass> {
} }
@observer @observer
export class StorageClassDetails extends React.Component<Props> { export class StorageClassDetails extends React.Component<Props> {
async componentDidMount() {
volumesStore.reloadAll();
}
render() { render() {
const { object: storageClass } = this.props; const { object: storageClass } = this.props;
const persistentVolumes = storageClassStore.getPersistentVolumes(storageClass);
if (!storageClass) return null; if (!storageClass) return null;
const { provisioner, parameters, mountOptions } = storageClass; const { provisioner, parameters, mountOptions } = storageClass;
@ -55,6 +63,7 @@ export class StorageClassDetails extends React.Component<Props> {
} }
</> </>
)} )}
<VolumeDetailsList persistentVolumes={persistentVolumes}/>
</div> </div>
); );
} }

View File

@ -2,10 +2,15 @@ import { KubeObjectStore } from "../../kube-object.store";
import { autobind } from "../../utils"; import { autobind } from "../../utils";
import { StorageClass, storageClassApi } from "../../api/endpoints/storage-class.api"; import { StorageClass, storageClassApi } from "../../api/endpoints/storage-class.api";
import { apiManager } from "../../api/api-manager"; import { apiManager } from "../../api/api-manager";
import { volumesStore } from "../+storage-volumes/volumes.store";
@autobind() @autobind()
export class StorageClassStore extends KubeObjectStore<StorageClass> { export class StorageClassStore extends KubeObjectStore<StorageClass> {
api = storageClassApi; api = storageClassApi;
getPersistentVolumes(storageClass: StorageClass) {
return volumesStore.getByStorageClass(storageClass);
}
} }
export const storageClassStore = new StorageClassStore(); export const storageClassStore = new StorageClassStore();

View File

@ -0,0 +1,31 @@
@import "../+storage/storage-mixins";
.VolumeDetailsList {
position: relative;
.Table {
margin: 0 (-$margin * 3);
&.virtual {
height: 500px; // applicable for 100+ items
}
}
.TableCell {
&:first-child {
margin-left: $margin;
}
&:last-child {
margin-right: $margin;
}
&.name {
flex-grow: 2;
}
&.status {
@include pv-status-colors;
}
}
}

View File

@ -0,0 +1,88 @@
import "./volume-details-list.scss";
import React from "react";
import { observer } from "mobx-react";
import { PersistentVolume } from "../../api/endpoints/persistent-volume.api";
import { autobind } from "../../../common/utils/autobind";
import { TableRow } from "../table/table-row";
import { cssNames, prevDefault } from "../../utils";
import { showDetails } from "../kube-object/kube-object-details";
import { TableCell } from "../table/table-cell";
import { Spinner } from "../spinner/spinner";
import { DrawerTitle } from "../drawer/drawer-title";
import { Table } from "../table/table";
import { TableHead } from "../table/table-head";
import { volumesStore } from "./volumes.store";
import kebabCase from "lodash/kebabCase";
interface Props {
persistentVolumes: PersistentVolume[];
}
enum sortBy {
name = "name",
status = "status",
capacity = "capacity",
}
@observer
export class VolumeDetailsList extends React.Component<Props> {
private sortingCallbacks = {
[sortBy.name]: (volume: PersistentVolume) => volume.getName(),
[sortBy.capacity]: (volume: PersistentVolume) => volume.getCapacity(),
[sortBy.status]: (volume: PersistentVolume) => volume.getStatus(),
};
@autobind()
getTableRow(uid: string) {
const { persistentVolumes } = this.props;
const volume = persistentVolumes.find(volume => volume.getId() === uid);
return (
<TableRow
key={volume.getId()}
sortItem={volume}
nowrap
onClick={prevDefault(() => showDetails(volume.selfLink, false))}
>
<TableCell className="name">{volume.getName()}</TableCell>
<TableCell className="capacity">{volume.getCapacity()}</TableCell>
<TableCell className={cssNames("status", kebabCase(volume.getStatus()))}>{volume.getStatus()}</TableCell>
</TableRow>
);
}
render() {
const { persistentVolumes } = this.props;
const virtual = persistentVolumes.length > 100;
if (!persistentVolumes.length) {
return !volumesStore.isLoaded && <Spinner center/>;
}
return (
<div className="VolumeDetailsList flex column">
<DrawerTitle title="Persistent Volumes"/>
<Table
items={persistentVolumes}
selectable
virtual={virtual}
sortable={this.sortingCallbacks}
sortByDefault={{ sortBy: sortBy.name, orderBy: "desc" }}
sortSyncWithUrl={false}
getTableRow={this.getTableRow}
className="box grow"
>
<TableHead>
<TableCell className="name" sortBy={sortBy.name}>Name</TableCell>
<TableCell className="capacity" sortBy={sortBy.capacity}>Capacity</TableCell>
<TableCell className="status" sortBy={sortBy.status}>Status</TableCell>
</TableHead>
{
!virtual && persistentVolumes.map(volume => this.getTableRow(volume.getId()))
}
</Table>
</div>
);
}
}

View File

@ -26,7 +26,7 @@
flex-grow: 3; flex-grow: 3;
} }
.status { &.status {
@include pv-status-colors; @include pv-status-colors;
} }

View File

@ -2,10 +2,17 @@ import { KubeObjectStore } from "../../kube-object.store";
import { autobind } from "../../utils"; import { autobind } from "../../utils";
import { PersistentVolume, persistentVolumeApi } from "../../api/endpoints/persistent-volume.api"; import { PersistentVolume, persistentVolumeApi } from "../../api/endpoints/persistent-volume.api";
import { apiManager } from "../../api/api-manager"; import { apiManager } from "../../api/api-manager";
import { StorageClass } from "../../api/endpoints/storage-class.api";
@autobind() @autobind()
export class PersistentVolumesStore extends KubeObjectStore<PersistentVolume> { export class PersistentVolumesStore extends KubeObjectStore<PersistentVolume> {
api = persistentVolumeApi; api = persistentVolumeApi;
getByStorageClass(storageClass: StorageClass): PersistentVolume[] {
return this.items.filter(volume =>
volume.getStorageClassName() === storageClass.getName()
);
}
} }
export const volumesStore = new PersistentVolumesStore(); export const volumesStore = new PersistentVolumesStore();