Lens app source code (#119)

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>
This commit is contained in:
Jari Kolehmainen authored and GitHub committed 2020-03-15 09:52:02 +02:00
1 parent 936cbd53d4
commit 1d0815abd2
797 files changed
+73714 -215

No files matched your search

@@ -0,0 +1,3 @@
export * from "./kube-object-details"
export * from "./kube-object-list-layout"
export * from "./kube-object-menu"
@@ -0,0 +1,3 @@
.KubeObjectDetails {
z-index: $zIndex-drawer + 1 !important;
}
@@ -0,0 +1,91 @@
import "./kube-object-details.scss"
import React from "react"
import { disposeOnUnmount, observer } from "mobx-react";
import { computed, observable, reaction } from "mobx";
import { Trans } from "@lingui/macro";
import { getDetails, hideDetails } from "../../navigation";
import { Drawer } from "../drawer";
import { KubeObject } from "../../api/kube-object";
import { Spinner } from "../spinner";
import { apiManager, ApiComponents } from "../../api/api-manager";
import { crdStore } from "../+custom-resources/crd.store";
import { CrdResourceDetails, CrdResourceMenu } from "../+custom-resources";
export interface KubeObjectDetailsProps<T = KubeObject> {
className?: string;
object: T;
}
@observer
export class KubeObjectDetails extends React.Component {
@observable isLoading = false;
@observable.ref loadingError: React.ReactNode;
@computed get path() {
return getDetails()
}
@computed get object() {
const store = apiManager.getStore(this.path);
if (store) {
return store.getByPath(this.path);
}
}
@computed get isCrdInstance() {
return !!crdStore.getByObject(this.object);
}
@disposeOnUnmount
loader = reaction(() => [
this.path,
this.object, // resource might be updated via watch-event or from already opened details
crdStore.items.length, // crd stores initialized after loading
], async () => {
this.loadingError = ""
const { path, object } = this;
if (!object) {
const store = apiManager.getStore(path);
if (store) {
this.isLoading = true
try {
await store.loadFromPath(path)
} catch (err) {
this.loadingError = <Trans>Resource loading has failed: <b>{err.toString()}</b></Trans>
} finally {
this.isLoading = false
}
}
}
})
render() {
const { object, isLoading, loadingError, isCrdInstance } = this;
const isOpen = !!(object || isLoading || loadingError);
let title = "";
let apiComponents: ApiComponents;
if (object) {
const { kind, getName, selfLink } = object;
title = `${kind}: ${getName()}`;
apiComponents = apiManager.getViews(selfLink);
if (isCrdInstance) {
apiComponents.Details = CrdResourceDetails
apiComponents.Menu = CrdResourceMenu
}
}
return (
<Drawer
className="KubeObjectDetails flex column"
open={isOpen}
title={title}
toolbar={apiComponents && apiComponents.Menu && <apiComponents.Menu object={object} toolbar/>}
onClose={hideDetails}
>
{isLoading && <Spinner center/>}
{loadingError && <div className="box center">{loadingError}</div>}
{apiComponents && apiComponents.Details && <apiComponents.Details object={object}/>}
</Drawer>
)
}
}
@@ -0,0 +1,40 @@
import React from "react";
import { computed } from "mobx";
import { observer } from "mobx-react";
import { cssNames } from "../../utils";
import { KubeObject } from "../../api/kube-object";
import { getSelectedDetails, showDetails } from "../../navigation";
import { ItemListLayout, ItemListLayoutProps } from "../item-object-list/item-list-layout";
import { KubeObjectStore } from "../../kube-object.store";
export interface KubeObjectListLayoutProps extends ItemListLayoutProps {
store: KubeObjectStore;
}
@observer
export class KubeObjectListLayout extends React.Component<KubeObjectListLayoutProps> {
@computed get selectedItem() {
return this.props.store.getByPath(getSelectedDetails());
}
onDetails = (item: KubeObject) => {
if (this.props.onDetails) {
this.props.onDetails(item);
}
else {
showDetails(item.selfLink);
}
}
render() {
const { className, ...layoutProps } = this.props;
return (
<ItemListLayout
{...layoutProps}
className={cssNames("KubeObjectListLayout", className)}
detailsItem={this.selectedItem}
onDetails={this.onDetails}
/>
);
}
}
@@ -0,0 +1,70 @@
import React from "react";
import { Trans } from "@lingui/macro";
import { autobind, cssNames } from "../../utils";
import { KubeObject } from "../../api/kube-object";
import { editResourceTab } from "../dock/edit-resource.store";
import { MenuActions, MenuActionsProps } from "../menu/menu-actions";
import { hideDetails } from "../../navigation";
import { apiManager } from "../../api/api-manager";
export interface KubeObjectMenuProps<T extends KubeObject = any> extends MenuActionsProps {
object: T;
editable?: boolean;
removable?: boolean;
}
export class KubeObjectMenu extends React.Component<KubeObjectMenuProps> {
get store() {
const { object } = this.props;
if (!object) return;
return apiManager.getStore(object.selfLink);
}
get isEditable() {
const { editable } = this.props;
return editable !== undefined ? editable : !!(this.store && this.store.update);
}
get isRemovable() {
const { removable } = this.props;
return removable !== undefined ? removable : !!(this.store && this.store.remove);
}
@autobind()
async update() {
hideDetails();
editResourceTab(this.props.object);
}
@autobind()
async remove() {
hideDetails();
const { object, removeAction } = this.props;
if (removeAction) await removeAction();
else await this.store.remove(object);
}
@autobind()
renderRemoveMessage() {
const { object } = this.props;
const resourceKind = object.kind;
const resourceName = object.getName();
return (
<p><Trans>Remove {resourceKind} <b>{resourceName}</b>?</Trans></p>
)
}
render() {
const { remove, update, renderRemoveMessage, isEditable, isRemovable } = this;
const { className, object, editable, removable, ...menuProps } = this.props;
return (
<MenuActions
className={cssNames("KubeObjectMenu", className)}
updateAction={isEditable ? update : undefined}
removeAction={isRemovable ? remove : undefined}
removeConfirmationMessage={renderRemoveMessage}
{...menuProps}
/>
)
}
}
@@ -0,0 +1,65 @@
import React from "react";
import { Trans } from "@lingui/macro";
import { IKubeMetaField, KubeObject } from "../../api/kube-object";
import { DrawerItem, DrawerItemLabels } from "../drawer";
export interface Props {
object: KubeObject;
hideFields?: IKubeMetaField[];
}
export class KubeObjectMeta extends React.Component<Props> {
static defaultHiddenFields: IKubeMetaField[] = [
"uid", "resourceVersion", "selfLink"
];
isHidden(field: IKubeMetaField): boolean {
const { hideFields = KubeObjectMeta.defaultHiddenFields } = this.props;
return hideFields.includes(field);
}
render() {
const {
getName, getNs, getLabels, getResourceVersion, selfLink,
getAnnotations, getFinalizers, getId, getAge,
metadata: { creationTimestamp },
} = this.props.object;
return (
<>
<DrawerItem name={<Trans>Created</Trans>} hidden={this.isHidden("creationTimestamp")}>
{getAge(true, false)} <Trans>ago</Trans> ({creationTimestamp})
</DrawerItem>
<DrawerItem name={<Trans>Name</Trans>} hidden={this.isHidden("name")}>
{getName()}
</DrawerItem>
<DrawerItem name={<Trans>Namespace</Trans>} hidden={this.isHidden("namespace") || !getNs()}>
{getNs()}
</DrawerItem>
<DrawerItem name={<Trans>UID</Trans>} hidden={this.isHidden("uid")}>
{getId()}
</DrawerItem>
<DrawerItem name={<Trans>Link</Trans>} hidden={this.isHidden("selfLink")}>
{selfLink}
</DrawerItem>
<DrawerItem name={<Trans>Resource Version</Trans>} hidden={this.isHidden("resourceVersion")}>
{getResourceVersion()}
</DrawerItem>
<DrawerItemLabels
name={<Trans>Labels</Trans>}
labels={getLabels()}
hidden={this.isHidden("labels")}
/>
<DrawerItemLabels
name={<Trans>Annotations</Trans>}
labels={getAnnotations()}
hidden={this.isHidden("annotations")}
/>
<DrawerItemLabels
name={<Trans>Finalizers</Trans>}
labels={getFinalizers()}
hidden={this.isHidden("finalizers")}
/>
</>
)
}
}