mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Full dependency inversion of <Dock> and all current tab kinds (#4757)
Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Co-authored-by: Sebastian Malton <sebastian@malton.name> Co-authored-by: Janne Savolainen <janne.savolainen@live.fi>
This commit is contained in:
152 files changed
+3423
-2617
No files matched your search
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable";
|
||||
import type { TabId } from "../dock/store";
|
||||
import upgradeChartTabStoreInjectable from "./store.injectable";
|
||||
|
||||
const clearUpgradeChartTabDataInjectable = getInjectable({
|
||||
instantiate: (di) => {
|
||||
const upgradeChartTabStore = di.inject(upgradeChartTabStoreInjectable);
|
||||
|
||||
return (tabId: TabId) => {
|
||||
upgradeChartTabStore.clearData(tabId);
|
||||
};
|
||||
},
|
||||
|
||||
lifecycle: lifecycleEnum.singleton,
|
||||
});
|
||||
|
||||
export default clearUpgradeChartTabDataInjectable;
|
||||
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable";
|
||||
import upgradeChartTabStoreInjectable from "./store.injectable";
|
||||
import dockStoreInjectable from "../dock/store.injectable";
|
||||
import type { HelmRelease } from "../../../../common/k8s-api/endpoints/helm-releases.api";
|
||||
import { DockStore, DockTabCreateSpecific, TabId, TabKind } from "../dock/store";
|
||||
import type { UpgradeChartTabStore } from "./store";
|
||||
import { runInAction } from "mobx";
|
||||
|
||||
interface Dependencies {
|
||||
upgradeChartStore: UpgradeChartTabStore;
|
||||
dockStore: DockStore
|
||||
}
|
||||
|
||||
const createUpgradeChartTab = ({ upgradeChartStore, dockStore }: Dependencies) => (release: HelmRelease, tabParams: DockTabCreateSpecific = {}): TabId => {
|
||||
const tabId = upgradeChartStore.getTabIdByRelease(release.getName());
|
||||
|
||||
if (tabId) {
|
||||
dockStore.open();
|
||||
dockStore.selectTab(tabId);
|
||||
|
||||
return tabId;
|
||||
}
|
||||
|
||||
return runInAction(() => {
|
||||
const tab = dockStore.createTab(
|
||||
{
|
||||
title: `Helm Upgrade: ${release.getName()}`,
|
||||
...tabParams,
|
||||
kind: TabKind.UPGRADE_CHART,
|
||||
},
|
||||
false,
|
||||
);
|
||||
|
||||
upgradeChartStore.setData(tab.id, {
|
||||
releaseName: release.getName(),
|
||||
releaseNamespace: release.getNs(),
|
||||
});
|
||||
|
||||
return tab.id;
|
||||
});
|
||||
};
|
||||
|
||||
const createUpgradeChartTabInjectable = getInjectable({
|
||||
instantiate: (di) => createUpgradeChartTab({
|
||||
upgradeChartStore: di.inject(upgradeChartTabStoreInjectable),
|
||||
dockStore: di.inject(dockStoreInjectable),
|
||||
}),
|
||||
|
||||
lifecycle: lifecycleEnum.singleton,
|
||||
});
|
||||
|
||||
export default createUpgradeChartTabInjectable;
|
||||
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable";
|
||||
import { UpgradeChartTabStore } from "./store";
|
||||
import createDockTabStoreInjectable from "../dock-tab-store/create-dock-tab-store.injectable";
|
||||
import createStorageInjectable from "../../../utils/create-storage/create-storage.injectable";
|
||||
|
||||
const upgradeChartTabStoreInjectable = getInjectable({
|
||||
instantiate: (di) => {
|
||||
const createDockTabStore = di.inject(createDockTabStoreInjectable);
|
||||
|
||||
return new UpgradeChartTabStore({
|
||||
createStorage: di.inject(createStorageInjectable),
|
||||
valuesStore: createDockTabStore<string>(),
|
||||
});
|
||||
},
|
||||
|
||||
lifecycle: lifecycleEnum.singleton,
|
||||
});
|
||||
|
||||
export default upgradeChartTabStoreInjectable;
|
||||
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import { action, computed, makeObservable } from "mobx";
|
||||
import type { TabId } from "../dock/store";
|
||||
import { DockTabStorageState, DockTabStore } from "../dock-tab-store/dock-tab.store";
|
||||
import { getReleaseValues } from "../../../../common/k8s-api/endpoints/helm-releases.api";
|
||||
import type { StorageHelper } from "../../../utils";
|
||||
|
||||
export interface IChartUpgradeData {
|
||||
releaseName: string;
|
||||
releaseNamespace: string;
|
||||
}
|
||||
|
||||
interface Dependencies {
|
||||
valuesStore: DockTabStore<string>;
|
||||
createStorage: <T>(storageKey: string, options: DockTabStorageState<T>) => StorageHelper<DockTabStorageState<T>>;
|
||||
}
|
||||
|
||||
export class UpgradeChartTabStore extends DockTabStore<IChartUpgradeData> {
|
||||
@computed private get releaseNameReverseLookup(): Map<string, string> {
|
||||
return new Map(this.getAllData().map(([id, { releaseName }]) => [releaseName, id]));
|
||||
}
|
||||
|
||||
get values() {
|
||||
return this.dependencies.valuesStore;
|
||||
}
|
||||
|
||||
constructor(protected dependencies : Dependencies) {
|
||||
super(dependencies, {
|
||||
storageKey: "chart_releases",
|
||||
});
|
||||
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
@action
|
||||
async reloadValues(tabId: TabId) {
|
||||
this.values.clearData(tabId); // reset
|
||||
const { releaseName, releaseNamespace } = this.getData(tabId);
|
||||
const values = await getReleaseValues(releaseName, releaseNamespace, true);
|
||||
|
||||
this.values.setData(tabId, values);
|
||||
}
|
||||
|
||||
getTabIdByRelease(releaseName: string): TabId {
|
||||
return this.releaseNameReverseLookup.get(releaseName);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
.UpgradeChart {
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import "./upgrade-chart.scss";
|
||||
|
||||
import React from "react";
|
||||
import { action, makeObservable, observable, reaction } from "mobx";
|
||||
import { disposeOnUnmount, observer } from "mobx-react";
|
||||
import { cssNames } from "../../../utils";
|
||||
import type { DockTab } from "../dock/store";
|
||||
import { InfoPanel } from "../info-panel";
|
||||
import type { UpgradeChartTabStore } from "./store";
|
||||
import { Spinner } from "../../spinner";
|
||||
import { Badge } from "../../badge";
|
||||
import { EditorPanel } from "../editor-panel";
|
||||
import { helmChartStore, IChartVersion } from "../../+apps-helm-charts/helm-chart.store";
|
||||
import type { HelmRelease, IReleaseUpdateDetails, IReleaseUpdatePayload } from "../../../../common/k8s-api/endpoints/helm-releases.api";
|
||||
import { Select, SelectOption } from "../../select";
|
||||
import { IAsyncComputed, withInjectables } from "@ogre-tools/injectable-react";
|
||||
import upgradeChartTabStoreInjectable from "./store.injectable";
|
||||
import updateReleaseInjectable from "../../+apps-releases/update-release/update-release.injectable";
|
||||
import releasesInjectable from "../../+apps-releases/releases.injectable";
|
||||
|
||||
interface Props {
|
||||
className?: string;
|
||||
tab: DockTab;
|
||||
}
|
||||
|
||||
interface Dependencies {
|
||||
releases: IAsyncComputed<HelmRelease[]>;
|
||||
upgradeChartTabStore: UpgradeChartTabStore;
|
||||
updateRelease: (name: string, namespace: string, payload: IReleaseUpdatePayload) => Promise<IReleaseUpdateDetails>;
|
||||
}
|
||||
|
||||
@observer
|
||||
export class NonInjectedUpgradeChart extends React.Component<Props & Dependencies> {
|
||||
@observable error: string;
|
||||
@observable versions = observable.array<IChartVersion>();
|
||||
@observable version: IChartVersion;
|
||||
|
||||
constructor(props: Props & Dependencies) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
disposeOnUnmount(this, [
|
||||
reaction(
|
||||
() => this.release,
|
||||
release => this.reloadVersions(release),
|
||||
{
|
||||
fireImmediately: true,
|
||||
},
|
||||
),
|
||||
reaction(
|
||||
() => this.release?.getRevision(),
|
||||
() => this.reloadValues(),
|
||||
{
|
||||
fireImmediately: true,
|
||||
},
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
get tabId() {
|
||||
return this.props.tab.id;
|
||||
}
|
||||
|
||||
get release(): HelmRelease {
|
||||
const tabData = this.props.upgradeChartTabStore.getData(this.tabId);
|
||||
|
||||
if (!tabData) return null;
|
||||
|
||||
return this.props.releases.value.get().find(release => release.getName() === tabData.releaseName);
|
||||
}
|
||||
|
||||
get value() {
|
||||
return this.props.upgradeChartTabStore.values.getData(this.tabId);
|
||||
}
|
||||
|
||||
async reloadValues() {
|
||||
this.props.upgradeChartTabStore.reloadValues(this.props.tab.id);
|
||||
}
|
||||
|
||||
async reloadVersions(release: HelmRelease) {
|
||||
if (!release) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.version = null;
|
||||
this.versions.clear();
|
||||
const versions = await helmChartStore.getVersions(this.release.getChart());
|
||||
|
||||
this.versions.replace(versions);
|
||||
this.version = this.versions[0];
|
||||
}
|
||||
|
||||
onChange = action((value: string) => {
|
||||
this.error = "";
|
||||
this.props.upgradeChartTabStore.values.setData(this.tabId, value);
|
||||
});
|
||||
|
||||
onError = action((error: Error | string) => {
|
||||
this.error = error.toString();
|
||||
});
|
||||
|
||||
upgrade = async () => {
|
||||
if (this.error) return null;
|
||||
const { version, repo } = this.version;
|
||||
const releaseName = this.release.getName();
|
||||
const releaseNs = this.release.getNs();
|
||||
|
||||
await this.props.updateRelease(releaseName, releaseNs, {
|
||||
chart: this.release.getChart(),
|
||||
values: this.value,
|
||||
repo, version,
|
||||
});
|
||||
|
||||
return (
|
||||
<p>
|
||||
Release <b>{releaseName}</b> successfully upgraded to version <b>{version}</b>
|
||||
</p>
|
||||
);
|
||||
};
|
||||
|
||||
formatVersionLabel = ({ value }: SelectOption<IChartVersion>) => {
|
||||
const chartName = this.release.getChart();
|
||||
const { repo, version } = value;
|
||||
|
||||
return `${repo}/${chartName}-${version}`;
|
||||
};
|
||||
|
||||
render() {
|
||||
const { tabId, release, value, error, onChange, onError, upgrade, versions, version } = this;
|
||||
const { className } = this.props;
|
||||
|
||||
if (!release || this.props.upgradeChartTabStore.isReady(tabId) || !version) {
|
||||
return <Spinner center/>;
|
||||
}
|
||||
const currentVersion = release.getVersion();
|
||||
const controlsAndInfo = (
|
||||
<div className="upgrade flex gaps align-center">
|
||||
<span>Release</span> <Badge label={release.getName()}/>
|
||||
<span>Namespace</span> <Badge label={release.getNs()}/>
|
||||
<span>Version</span> <Badge label={currentVersion}/>
|
||||
<span>Upgrade version</span>
|
||||
<Select
|
||||
className="chart-version"
|
||||
menuPlacement="top"
|
||||
themeName="outlined"
|
||||
value={version}
|
||||
options={versions}
|
||||
formatOptionLabel={this.formatVersionLabel}
|
||||
onChange={({ value }: SelectOption) => this.version = value}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={cssNames("UpgradeChart flex column", className)}>
|
||||
<InfoPanel
|
||||
tabId={tabId}
|
||||
error={error}
|
||||
submit={upgrade}
|
||||
submitLabel="Upgrade"
|
||||
submittingMessage="Updating.."
|
||||
controls={controlsAndInfo}
|
||||
/>
|
||||
<EditorPanel
|
||||
tabId={tabId}
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
onError={onError}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const UpgradeChart = withInjectables<Dependencies, Props>(NonInjectedUpgradeChart, {
|
||||
getProps: (di, props) => ({
|
||||
releases: di.inject(releasesInjectable),
|
||||
updateRelease: di.inject(updateReleaseInjectable),
|
||||
upgradeChartTabStore: di.inject(upgradeChartTabStoreInjectable),
|
||||
...props,
|
||||
}),
|
||||
});
|
||||
Reference in new issue
Block a user