mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
174 lines
5.9 KiB
TypeScript
174 lines
5.9 KiB
TypeScript
/**
|
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
|
*/
|
|
|
|
import "./crd-list.scss";
|
|
|
|
import React from "react";
|
|
import { computed, makeObservable, observable } from "mobx";
|
|
import { observer } from "mobx-react";
|
|
import { Link } from "react-router-dom";
|
|
import { iter, stopPropagation } from "../../utils";
|
|
import { KubeObjectListLayout } from "../kube-object-list-layout";
|
|
import { customResourceDefinitionStore } from "./legacy-store";
|
|
import { Select } from "../select";
|
|
import { Icon } from "../icon";
|
|
import { KubeObjectAge } from "../kube-object/age";
|
|
import { TabLayout } from "../layout/tab-layout-2";
|
|
import type { PageParam } from "../../navigation";
|
|
import type { CustomResourceDefinitionStore } from "./definition.store";
|
|
import { withInjectables } from "@ogre-tools/injectable-react";
|
|
import crdGroupsUrlParamInjectable from "./crd-groups-url-param.injectable";
|
|
import customResourceDefinitionStoreInjectable from "./definition.store.injectable";
|
|
|
|
enum columnId {
|
|
kind = "kind",
|
|
group = "group",
|
|
version = "version",
|
|
scope = "scope",
|
|
age = "age",
|
|
}
|
|
|
|
interface Dependencies {
|
|
crdGroupsUrlParam: PageParam<string[]>;
|
|
customResourceDefinitionStore: CustomResourceDefinitionStore;
|
|
}
|
|
|
|
@observer
|
|
class NonInjectedCustomResourceDefinitions extends React.Component<Dependencies> {
|
|
private readonly selectedGroups = observable.set(this.props.crdGroupsUrlParam.get());
|
|
|
|
constructor(props: Dependencies) {
|
|
super(props);
|
|
makeObservable(this);
|
|
}
|
|
|
|
@computed get items() {
|
|
if (this.selectedGroups.size) {
|
|
return this.props.customResourceDefinitionStore.items.filter(item => this.selectedGroups.has(item.getGroup()));
|
|
}
|
|
|
|
return this.props.customResourceDefinitionStore.items; // show all by default
|
|
}
|
|
|
|
@computed get groupSelectOptions() {
|
|
return Object.keys(this.props.customResourceDefinitionStore.groups)
|
|
.map(group => ({
|
|
value: group,
|
|
label: group,
|
|
isSelected: this.selectedGroups.has(group),
|
|
}));
|
|
}
|
|
|
|
toggleSelection = (options: readonly ({ value: string })[]) => {
|
|
const groups = options.map(({ value }) => value);
|
|
|
|
this.selectedGroups.replace(groups);
|
|
this.props.crdGroupsUrlParam.set(groups);
|
|
};
|
|
|
|
private getPlaceholder() {
|
|
if (this.selectedGroups.size === 0) {
|
|
return "All groups";
|
|
}
|
|
|
|
const prefix = this.selectedGroups.size === 1
|
|
? "Group"
|
|
: "Groups";
|
|
|
|
return `${prefix}: ${iter.join(this.selectedGroups.values(), ", ")}`;
|
|
}
|
|
|
|
render() {
|
|
return (
|
|
<TabLayout>
|
|
<KubeObjectListLayout
|
|
isConfigurable
|
|
tableId="crd"
|
|
className="CrdList"
|
|
store={customResourceDefinitionStore}
|
|
// Don't subscribe the `customResourceDefinitionStore` because <Sidebar> already has and is always mounted
|
|
subscribeStores={false}
|
|
items={this.items}
|
|
sortingCallbacks={{
|
|
[columnId.kind]: crd => crd.getResourceKind(),
|
|
[columnId.group]: crd => crd.getGroup(),
|
|
[columnId.version]: crd => crd.getVersion(),
|
|
[columnId.scope]: crd => crd.getScope(),
|
|
[columnId.age]: crd => -crd.getCreationTimestamp(),
|
|
}}
|
|
searchFilters={[
|
|
crd => crd.getResourceKind(),
|
|
crd => crd.getGroup(),
|
|
crd => crd.getVersion(),
|
|
crd => crd.getScope(),
|
|
crd => -crd.getCreationTimestamp(),
|
|
]}
|
|
renderHeaderTitle="Custom Resources"
|
|
customizeHeader={({ filters, ...headerPlaceholders }) => ({
|
|
// todo: move to global filters
|
|
filters: (
|
|
<>
|
|
{filters}
|
|
<Select
|
|
id="crd-input"
|
|
className="group-select"
|
|
placeholder={this.getPlaceholder()}
|
|
options={this.groupSelectOptions}
|
|
onChange={this.toggleSelection}
|
|
closeMenuOnSelect={false}
|
|
controlShouldRenderValue={false}
|
|
isMulti={true}
|
|
formatOptionLabel={({ value, isSelected }) => (
|
|
<div className="flex gaps align-center">
|
|
<Icon small material="folder" />
|
|
<span>{value}</span>
|
|
{isSelected && (
|
|
<Icon
|
|
small
|
|
material="check"
|
|
className="box right"
|
|
/>
|
|
)}
|
|
</div>
|
|
)}
|
|
/>
|
|
</>
|
|
),
|
|
...headerPlaceholders,
|
|
})}
|
|
renderTableHeader={[
|
|
{ title: "Resource", className: "kind", sortBy: columnId.kind, id: columnId.kind },
|
|
{ title: "Group", className: "group", sortBy: columnId.group, id: columnId.group },
|
|
{ title: "Version", className: "version", sortBy: columnId.version, id: columnId.version },
|
|
{ title: "Scope", className: "scope", sortBy: columnId.scope, id: columnId.scope },
|
|
{ title: "Age", className: "age", sortBy: columnId.age, id: columnId.age },
|
|
]}
|
|
renderTableContents={crd => [
|
|
<Link
|
|
key="link"
|
|
to={crd.getResourceUrl()}
|
|
onClick={stopPropagation}
|
|
>
|
|
{crd.getResourceKind()}
|
|
</Link>,
|
|
crd.getGroup(),
|
|
crd.getVersion(),
|
|
crd.getScope(),
|
|
<KubeObjectAge key="age" object={crd} />,
|
|
]}
|
|
/>
|
|
</TabLayout>
|
|
);
|
|
}
|
|
}
|
|
|
|
export const CustomResourceDefinitions = withInjectables<Dependencies>(NonInjectedCustomResourceDefinitions, {
|
|
getProps: (di, props) => ({
|
|
...props,
|
|
crdGroupsUrlParam: di.inject(crdGroupsUrlParamInjectable),
|
|
customResourceDefinitionStore: di.inject(customResourceDefinitionStoreInjectable),
|
|
}),
|
|
});
|