1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00
lens/src/renderer/components/+helm-releases/releases.tsx
Sebastian Malton c65a1f3f61 Enforce some naming conventions (#4813)
Signed-off-by: DmitriyNoa <dmytro.zharkov@gmail.com>
2022-03-03 14:40:53 +01:00

238 lines
7.6 KiB
TypeScript

/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import "../item-object-list/item-list-layout.scss";
import "./releases.scss";
import React, { Component } from "react";
import type { RouteComponentProps } from "react-router";
import type { HelmRelease } from "../../../common/k8s-api/endpoints/helm-releases.api";
import { navigation } from "../../navigation";
import type { ReleaseRouteParams } from "../../../common/routes";
import { releaseURL } from "../../../common/routes";
import { withInjectables } from "@ogre-tools/injectable-react";
import namespaceStoreInjectable from "../+namespaces/namespace-store/namespace-store.injectable";
import { ItemListLayout } from "../item-object-list";
import { NamespaceSelectFilter } from "../+namespaces/namespace-select-filter";
import { kebabCase } from "lodash/fp";
import { HelmReleaseMenu } from "./release-menu";
import type { ItemStore } from "../../../common/item.store";
import { ReleaseRollbackDialog } from "./release-rollback-dialog";
import { ReleaseDetails } from "./release-details/release-details";
import removableReleasesInjectable from "./removable-releases.injectable";
import type { RemovableHelmRelease } from "./removable-releases";
import type { IComputedValue } from "mobx";
import releasesInjectable from "./releases.injectable";
enum columnId {
name = "name",
namespace = "namespace",
revision = "revision",
chart = "chart",
version = "version",
appVersion = "app-version",
status = "status",
updated = "update",
}
export interface HelmReleasesProps extends RouteComponentProps<ReleaseRouteParams> {
}
interface Dependencies {
releases: IComputedValue<RemovableHelmRelease[]>;
releasesArePending: IComputedValue<boolean>;
selectNamespace: (namespace: string) => void;
}
class NonInjectedHelmReleases extends Component<Dependencies & HelmReleasesProps> {
componentDidMount() {
const { match: { params: { namespace }}} = this.props;
if (namespace) {
this.props.selectNamespace(namespace);
}
}
onDetails = (item: HelmRelease) => {
this.showDetails(item);
};
showDetails = (item: HelmRelease) => {
navigation.push(releaseURL({
params: {
name: item.getName(),
namespace: item.getNs(),
},
}));
};
hideDetails = () => {
navigation.push(releaseURL());
};
renderRemoveDialogMessage(selectedItems: HelmRelease[]) {
const releaseNames = selectedItems.map(item => item.getName()).join(", ");
return (
<div>
<>Remove <b>{releaseNames}</b>?</>
<p className="warning">
Note: StatefulSet Volumes won&apos;t be deleted automatically
</p>
</div>
);
}
render() {
const releases = this.props.releases;
const releasesArePending = this.props.releasesArePending;
// TODO: Implement ItemListLayout without stateful stores
const legacyReleaseStore = {
get items() {
return releases.get();
},
loadAll: () => Promise.resolve(),
get isLoaded() {
return !releasesArePending.get();
},
failedLoading: false,
getTotalCount: () => releases.get().length,
toggleSelection: (item) => {
item.toggle();
},
isSelectedAll: (visibleItems: RemovableHelmRelease[]) => (
visibleItems.length > 0
&& visibleItems.every((release) => release.isSelected)
),
toggleSelectionAll: (visibleItems: RemovableHelmRelease[]) => {
let selected = false;
if (!legacyReleaseStore.isSelectedAll(visibleItems)) {
selected = true;
}
visibleItems.forEach((release) => {
if (release.isSelected !== selected) {
release.toggle();
}
});
},
isSelected: (item) => item.isSelected,
get selectedItems() {
return releases.get().filter((release) => release.isSelected);
},
pickOnlySelected: (releases) => {
return releases.filter(release => release.isSelected);
},
removeItems: async (releases) => {
await Promise.all(releases.map(release => release.delete()));
},
} as ItemStore<RemovableHelmRelease>;
return (
<>
<ItemListLayout
store={legacyReleaseStore}
getItems={() => legacyReleaseStore.items}
preloadStores={false}
isConfigurable
tableId="helm_releases"
className="HelmReleases"
sortingCallbacks={{
[columnId.name]: release => release.getName(),
[columnId.namespace]: release => release.getNs(),
[columnId.revision]: release => release.getRevision(),
[columnId.chart]: release => release.getChart(),
[columnId.status]: release => release.getStatus(),
[columnId.updated]: release => release.getUpdated(false, false),
}}
searchFilters={[
release => release.getName(),
release => release.getNs(),
release => release.getChart(),
release => release.getStatus(),
release => release.getVersion(),
]}
customizeHeader={({ filters, searchProps, ...headerPlaceholders }) => ({
filters: (
<>
{filters}
<NamespaceSelectFilter />
</>
),
searchProps: {
...searchProps,
placeholder: "Search Releases...",
},
...headerPlaceholders,
})}
renderHeaderTitle="Releases"
renderTableHeader={[
{ title: "Name", className: "name", sortBy: columnId.name, id: columnId.name },
{ title: "Namespace", className: "namespace", sortBy: columnId.namespace, id: columnId.namespace },
{ title: "Chart", className: "chart", sortBy: columnId.chart, id: columnId.chart },
{ title: "Revision", className: "revision", sortBy: columnId.revision, id: columnId.revision },
{ title: "Version", className: "version", id: columnId.version },
{ title: "App Version", className: "app-version", id: columnId.appVersion },
{ title: "Status", className: "status", sortBy: columnId.status, id: columnId.status },
{ title: "Updated", className: "updated", sortBy: columnId.updated, id: columnId.updated },
]}
renderTableContents={release => [
release.getName(),
release.getNs(),
release.getChart(),
release.getRevision(),
release.getVersion(),
release.appVersion,
{ title: release.getStatus(), className: kebabCase(release.getStatus()) },
release.getUpdated(),
]}
renderItemMenu={release => (
<HelmReleaseMenu
release={release}
removeConfirmationMessage={this.renderRemoveDialogMessage([release])}
/>
)}
customizeRemoveDialog={selectedItems => ({
message: this.renderRemoveDialogMessage(selectedItems),
})}
onDetails={this.onDetails}
/>
<ReleaseDetails
hideDetails={this.hideDetails}
/>
<ReleaseRollbackDialog/>
</>
);
}
}
export const HelmReleases = withInjectables<Dependencies, HelmReleasesProps>(
NonInjectedHelmReleases,
{
getProps: (di, props) => ({
releases: di.inject(removableReleasesInjectable),
releasesArePending: di.inject(releasesInjectable).pending,
selectNamespace: di.inject(namespaceStoreInjectable).selectNamespaces,
...props,
}),
},
);