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

cleanup varient rendering

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton 2022-03-11 10:33:41 -05:00
parent 2d544615e5
commit 35418cae12
6 changed files with 94 additions and 85 deletions

View File

@ -393,7 +393,7 @@
"ts-jest": "26.5.6", "ts-jest": "26.5.6",
"ts-loader": "^9.2.6", "ts-loader": "^9.2.6",
"ts-node": "^10.7.0", "ts-node": "^10.7.0",
"type-fest": "^1.4.0", "type-fest": "^2.12.0",
"typed-emitter": "^1.4.0", "typed-emitter": "^1.4.0",
"typedoc": "0.22.10", "typedoc": "0.22.10",
"typedoc-plugin-markdown": "^3.11.12", "typedoc-plugin-markdown": "^3.11.12",

View File

@ -28,26 +28,23 @@ interface RuleGroup {
@observer @observer
export class PodSecurityPolicyDetails extends React.Component<PodSecurityPolicyDetailsProps> { export class PodSecurityPolicyDetails extends React.Component<PodSecurityPolicyDetailsProps> {
renderRuleGroup( title: React.ReactNode, group: RuleGroup) { renderRuleGroup = (title: React.ReactNode, { rule, ranges }: RuleGroup) => (
if (!group) return null; <>
const { rule, ranges } = group; <DrawerTitle>{title}</DrawerTitle>
<DrawerItem name="Rule">
return ( {rule}
<> </DrawerItem>
<DrawerTitle title={title}/> {ranges && (
<DrawerItem name="Rule"> <DrawerItem name="Ranges (Min-Max)" labelsOnly>
{rule} {ranges.map(({ min, max }, index) => (
<Badge
key={index}
label={`${min} - ${max}`} />
))}
</DrawerItem> </DrawerItem>
{ranges && ( )}
<DrawerItem name="Ranges (Min-Max)" labelsOnly> </>
{ranges.map(({ min, max }, index) => { );
return <Badge key={index} label={`${min} - ${max}`}/>;
})}
</DrawerItem>
)}
</>
);
}
render() { render() {
const { object: psp } = this.props; const { object: psp } = this.props;
@ -179,10 +176,10 @@ export class PodSecurityPolicyDetails extends React.Component<PodSecurityPolicyD
</> </>
)} )}
{this.renderRuleGroup("Fs Group", fsGroup)} {fsGroup && this.renderRuleGroup("Fs Group", fsGroup)}
{this.renderRuleGroup("Run As Group", runAsGroup)} {runAsGroup && this.renderRuleGroup("Run As Group", runAsGroup)}
{this.renderRuleGroup("Run As User", runAsUser)} {runAsUser && this.renderRuleGroup("Run As User", runAsUser)}
{this.renderRuleGroup("Supplemental Groups", supplementalGroups)} {supplementalGroups && this.renderRuleGroup("Supplemental Groups", supplementalGroups)}
{runtimeClass && ( {runtimeClass && (
<> <>

View File

@ -7,9 +7,11 @@ import jsyaml from "js-yaml";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import React from "react"; import React from "react";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import type { RequireAllOrNone } from "type-fest";
import { configMapApi, Pod, PodVolume, PodVolumeKind, PodVolumeVariants, pvcApi, SecretReference, secretsApi } from "../../../common/k8s-api/endpoints"; import { configMapApi, Pod, PodVolume, PodVolumeKind, PodVolumeVariants, pvcApi, SecretReference, secretsApi } from "../../../common/k8s-api/endpoints";
import type { KubeApi } from "../../../common/k8s-api/kube-api"; import type { KubeApi } from "../../../common/k8s-api/kube-api";
import type { KubeObject, LocalObjectReference } from "../../../common/k8s-api/kube-object"; import type { KubeObject, LocalObjectReference } from "../../../common/k8s-api/kube-object";
import { entries } from "../../utils";
import { DrawerItem, DrawerItemLabels, DrawerTitle } from "../drawer"; import { DrawerItem, DrawerItemLabels, DrawerTitle } from "../drawer";
import { Icon } from "../icon"; import { Icon } from "../icon";
import { getDetailsUrl } from "../kube-detail-params"; import { getDetailsUrl } from "../kube-detail-params";
@ -36,7 +38,7 @@ function renderLocalRef(pod: Pod, title: string, ref: LocalObjectReference | Sec
* *
*/ */
type PodVolumeVariantRenderers = { type PodVolumeVariantRenderers = {
[Key in keyof PodVolumeVariants]: (variant: PodVolumeVariants[Key], opts: VariantOptions) => React.ReactNode; [Key in keyof PodVolumeVariants]: (variant: PodVolumeVariants[Key], opts: VariantOptions) => React.ReactChild;
}; };
const volumeRenderers: PodVolumeVariantRenderers = { const volumeRenderers: PodVolumeVariantRenderers = {
@ -583,23 +585,28 @@ const deprecatedVolumeTypes = new Set<PodVolumeKind>([
"storageos", "storageos",
]); ]);
function getVolumeType(volume: PodVolume): PodVolumeKind | undefined { interface VolumeRendererPair {
const keys = new Set(Object.keys(volume)); kind: PodVolumeKind;
render: () => React.ReactChild;
}
keys.delete("name"); // This key is not a kind field function getVolumeType(pod: Pod, volume: PodVolume): RequireAllOrNone<VolumeRendererPair, keyof VolumeRendererPair> {
for (const [kind, varient] of entries(volume)) {
for (const key of keys) { if (kind === "name") {
// skip other random keys continue; // This key is not a kind field
if (key in volumeRenderers) {
const kind = key as PodVolumeKind;
if (volume[kind] && typeof volume[kind] === "object") {
return kind;
}
} }
if (!varient || typeof varient !== "object") {
continue;
}
return {
kind,
render: () => volumeRenderers[kind](varient as never, { pod, volumeName: volume.name }),
};
} }
return undefined; return {};
} }
export const PodVolumes = observer(({ pod }: PodVolumesProps) => { export const PodVolumes = observer(({ pod }: PodVolumesProps) => {
@ -608,9 +615,10 @@ export const PodVolumes = observer(({ pod }: PodVolumesProps) => {
} }
const renderVolume = (volume: PodVolume) => { const renderVolume = (volume: PodVolume) => {
const type = getVolumeType(volume); const { kind, render } = getVolumeType(pod, volume);
const isDeprecated = deprecatedVolumeTypes.has(type); const isDeprecated = deprecatedVolumeTypes.has(kind);
const renderVolume = volumeRenderers[type];
console.log(volume, render);
return ( return (
<div key={volume.name} className="volume"> <div key={volume.name} className="volume">
@ -619,23 +627,17 @@ export const PodVolumes = observer(({ pod }: PodVolumesProps) => {
<span>{volume.name}</span> <span>{volume.name}</span>
</div> </div>
{ {
renderVolume kind
? ( ? (
<> <>
<DrawerItem name="Type"> <DrawerItem name="Kind">
{type} {kind}
{isDeprecated && <Icon title="Deprecated" material="warning_amber" />} {isDeprecated && <Icon title="Deprecated" material="warning_amber" />}
</DrawerItem> </DrawerItem>
{renderVolume(volume[type] as any, { pod, volumeName: volume.name })} {render?.()}
</> </>
) )
: type : <p>Error! Unknown pod volume kind</p>
? (
<DrawerItem name="Type">
{type}
</DrawerItem>
)
: <p>Error! Unknown pod volume kind</p>
} }
</div> </div>
); );

View File

@ -11,7 +11,7 @@ import { disposeOnUnmount, observer } from "mobx-react";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { observable, reaction, makeObservable } from "mobx"; import { observable, reaction, makeObservable } from "mobx";
import { type IPodMetrics, nodesApi, Pod, getMetricsForPods } from "../../../common/k8s-api/endpoints"; import { type IPodMetrics, nodesApi, Pod, getMetricsForPods } from "../../../common/k8s-api/endpoints";
import { DrawerItem, DrawerSection } from "../drawer"; import { DrawerItem, DrawerTitle } from "../drawer";
import { Badge } from "../badge"; import { Badge } from "../badge";
import { boundMethod, cssNames, toJS } from "../../utils"; import { boundMethod, cssNames, toJS } from "../../utils";
import { PodDetailsContainer } from "./pod-details-container"; import { PodDetailsContainer } from "./pod-details-container";
@ -79,6 +79,7 @@ export class PodDetails extends React.Component<PodDetailsProps> {
const nodeSelector = pod.getNodeSelectors(); const nodeSelector = pod.getNodeSelectors();
const isMetricHidden = getActiveClusterEntity()?.isMetricHidden(ClusterMetricsResourceType.Pod); const isMetricHidden = getActiveClusterEntity()?.isMetricHidden(ClusterMetricsResourceType.Pod);
const initContainers = pod.getInitContainers(); const initContainers = pod.getInitContainers();
const containers = pod.getContainers();
return ( return (
<div className="PodDetails"> <div className="PodDetails">
@ -138,22 +139,28 @@ export class PodDetails extends React.Component<PodDetailsProps> {
<PodDetailsSecrets pod={pod}/> <PodDetailsSecrets pod={pod}/>
</DrawerItem> </DrawerItem>
<DrawerSection title="Init Containers" hidden={initContainers.length === 0}> {initContainers.length > 0 && (
{initContainers.map(c => <PodDetailsContainer key={c.name} pod={pod} container={c} />)} <>
</DrawerSection> <DrawerTitle>Init Containers</DrawerTitle>
{initContainers.map(container => (
<DrawerSection title="Containers">
{
pod.getContainers().map(container => (
<PodDetailsContainer <PodDetailsContainer
key={container.name} key={container.name}
pod={pod} pod={pod}
container={container} container={container}
metrics={getItemMetrics(toJS(this.containerMetrics), container.name)}
/> />
)) ))}
} </>
</DrawerSection> )}
<DrawerTitle>Containers</DrawerTitle>
{containers.map(container => (
<PodDetailsContainer
key={container.name}
pod={pod}
container={container}
metrics={getItemMetrics(toJS(this.containerMetrics), container.name)}
/>
))}
<PodVolumes pod={pod} /> <PodVolumes pod={pod} />
</div> </div>

View File

@ -7,29 +7,32 @@ import "./drawer-item.scss";
import React from "react"; import React from "react";
import { cssNames, displayBooleans } from "../../utils"; import { cssNames, displayBooleans } from "../../utils";
export interface DrawerItemProps extends React.HTMLAttributes<any> { export interface DrawerItemProps extends React.HTMLAttributes<HTMLDivElement> {
name: React.ReactNode; name: React.ReactNode;
className?: string;
title?: string; title?: string;
labelsOnly?: boolean; labelsOnly?: boolean;
hidden?: boolean; hidden?: boolean;
renderBoolean?: boolean; // show "true" or "false" for all of the children elements are "typeof boolean" renderBoolean?: boolean; // show "true" or "false" for all of the children elements are "typeof boolean"
} }
export class DrawerItem extends React.Component<DrawerItemProps> { export function DrawerItem({
render() { name,
const { name, title, labelsOnly, children, hidden, className, renderBoolean, ...elemProps } = this.props; title,
labelsOnly,
if (hidden) return null; children,
hidden,
const classNames = cssNames("DrawerItem", className, { labelsOnly }); className,
const content = displayBooleans(renderBoolean, children); renderBoolean,
...elemProps
return ( }: DrawerItemProps) {
<div {...elemProps} className={classNames} title={title}> if (!hidden) {
<span className="name">{name}</span> return null;
<span className="value">{content}</span>
</div>
);
} }
return (
<div {...elemProps} className={cssNames("DrawerItem", className, { labelsOnly })} title={title}>
<span className="name">{name}</span>
<span className="value">{displayBooleans(renderBoolean, children)}</span>
</div>
);
} }

View File

@ -13211,10 +13211,10 @@ type-fest@^0.8.1:
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d"
integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==
type-fest@^1.4.0: type-fest@^2.12.0:
version "1.4.0" version "2.12.0"
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-1.4.0.tgz#e9fb813fe3bf1744ec359d55d1affefa76f14be1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.12.0.tgz#ce342f58cab9114912f54b493d60ab39c3fc82b6"
integrity sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA== integrity sha512-Qe5GRT+n/4GoqCNGGVp5Snapg1Omq3V7irBJB3EaKsp7HWDo5Gv2d/67gfNyV+d5EXD+x/RF5l1h4yJ7qNkcGA==
type-is@~1.6.18: type-is@~1.6.18:
version "1.6.18" version "1.6.18"