diff --git a/src/extensions/renderer-api/components.ts b/src/extensions/renderer-api/components.ts index dfabddd7ec..8e6df41fa1 100644 --- a/src/extensions/renderer-api/components.ts +++ b/src/extensions/renderer-api/components.ts @@ -12,8 +12,9 @@ import commandOverlayInjectable from "../../renderer/components/command-palette/ import { asLegacyGlobalObjectForExtensionApiWithModifications } from "../as-legacy-globals-for-extension-api/as-legacy-global-object-for-extension-api-with-modifications"; import createPodLogsTabInjectable from "../../renderer/components/dock/logs/create-pod-logs-tab.injectable"; import createWorkloadLogsTabInjectable from "../../renderer/components/dock/logs/create-workload-logs-tab.injectable"; -import updateTabNameInjectable from "../../renderer/components/dock/logs/update-tab-name.injectable"; import sendCommandInjectable from "../../renderer/components/dock/terminal/send-command.injectable"; +import { podsStore } from "../../renderer/components/+workloads-pods/pods.store"; +import renameTabInjectable from "../../renderer/components/dock/dock/rename-tab.injectable"; // layouts export * from "../../renderer/components/layout/main-layout"; @@ -80,7 +81,13 @@ export const terminalStore = asLegacyGlobalObjectForExtensionApiWithModification export const logTabStore = asLegacyGlobalObjectForExtensionApiWithModifications(logTabStoreInjectable, { createPodTab: () => asLegacyGlobalFunctionForExtensionApi(createPodLogsTabInjectable), createWorkloadTab: () => asLegacyGlobalFunctionForExtensionApi(createWorkloadLogsTabInjectable), - renameTab: () => asLegacyGlobalFunctionForExtensionApi(updateTabNameInjectable), + renameTab: () => (tabId: string): void => { + const renameTab = asLegacyGlobalFunctionForExtensionApi(renameTabInjectable); + const tabData = logTabStore.getData(tabId); + const pod = podsStore.getById(tabData.selectedPodId); + + renameTab(tabId, `Pod ${pod.getName()}`); + }, tabs: () => undefined, }); diff --git a/src/renderer/components/dock/dock.tsx b/src/renderer/components/dock/dock.tsx index c8b481b859..d067931762 100644 --- a/src/renderer/components/dock/dock.tsx +++ b/src/renderer/components/dock/dock.tsx @@ -25,6 +25,7 @@ import { withInjectables } from "@ogre-tools/injectable-react"; import createResourceTabInjectable from "./create-resource/create-resource-tab.injectable"; import dockStoreInjectable from "./dock/store.injectable"; import createTerminalTabInjectable from "./terminal/create-terminal-tab.injectable"; +import { ErrorBoundary } from "../error-boundary"; interface Props { className?: string; @@ -160,7 +161,9 @@ class NonInjectedDock extends React.Component { )} - {this.renderTabContent()} + + {this.renderTabContent()} + ); } diff --git a/src/renderer/components/dock/logs/__test__/log-resource-selector.test.tsx b/src/renderer/components/dock/logs/__test__/log-resource-selector.test.tsx index 28ed8a8563..33754310a3 100644 --- a/src/renderer/components/dock/logs/__test__/log-resource-selector.test.tsx +++ b/src/renderer/components/dock/logs/__test__/log-resource-selector.test.tsx @@ -46,7 +46,7 @@ function mockLogTabViewModel(tabId: TabId, deps: Partial", () => { }); it("updates tab name if selected pod changes", async () => { - const updateTabName = jest.fn(); - const model = getFewPodsTabData("foobar", { updateTabName }); + const renameTab = jest.fn(); + const model = getFewPodsTabData("foobar", { renameTab }); const { findByText, container } = render(); selectEvent.openMenu(container.querySelector(".pod-selector")); userEvent.click(await findByText("deploymentPod2", { selector: ".pod-selector-menu .Select__option" })); - expect(updateTabName).toBeCalled(); + expect(renameTab).toBeCalledWith("foobar", "Pod deploymentPod1"); }); }); diff --git a/src/renderer/components/dock/logs/__test__/log-search.test.tsx b/src/renderer/components/dock/logs/__test__/log-search.test.tsx index 35705a7057..78e27c5570 100644 --- a/src/renderer/components/dock/logs/__test__/log-search.test.tsx +++ b/src/renderer/components/dock/logs/__test__/log-search.test.tsx @@ -25,7 +25,7 @@ function mockLogTabViewModel(tabId: TabId, deps: Partial & Omit, "ownerId" | "selectedPodId" | "selectedContainer" | "namespace">; +export type CreateLogsTabData = Pick & Omit, "owner" | "selectedPodId" | "selectedContainer" | "namespace">; interface Dependencies { createDockTab: (rawTabDesc: DockTabCreate, addNumber?: boolean) => DockTab; diff --git a/src/renderer/components/dock/logs/create-pod-logs-tab.injectable.ts b/src/renderer/components/dock/logs/create-pod-logs-tab.injectable.ts index 78beaddd47..77c36d52d3 100644 --- a/src/renderer/components/dock/logs/create-pod-logs-tab.injectable.ts +++ b/src/renderer/components/dock/logs/create-pod-logs-tab.injectable.ts @@ -18,10 +18,8 @@ interface Dependencies { } function createPodLogsTab({ createLogsTab }: Dependencies, { selectedPod, selectedContainer }: PodLogsTabData): TabId { - const podOwner = selectedPod.getOwnerRefs()[0]; - return createLogsTab(`Pod ${selectedPod.getName()}`, { - ownerId: podOwner?.uid, + owner: selectedPod.getOwnerRefs()[0], namespace: selectedPod.getNs(), selectedContainer: selectedContainer.name, selectedPodId: selectedPod.getId(), diff --git a/src/renderer/components/dock/logs/create-workload-logs-tab.injectable.ts b/src/renderer/components/dock/logs/create-workload-logs-tab.injectable.ts index a131a26706..1efd88eb2f 100644 --- a/src/renderer/components/dock/logs/create-workload-logs-tab.injectable.ts +++ b/src/renderer/components/dock/logs/create-workload-logs-tab.injectable.ts @@ -30,7 +30,11 @@ function createWorkloadLogsTab({ createLogsTab }: Dependencies, { workload }: Wo selectedContainer: selectedPod.getAllContainers()[0].name, selectedPodId: selectedPod.getId(), namespace: selectedPod.getNs(), - ownerId: workload.getId(), + owner: { + kind: workload.kind, + name: workload.getName(), + uid: workload.getId(), + }, }); } diff --git a/src/renderer/components/dock/logs/log-tab-data.validator.ts b/src/renderer/components/dock/logs/log-tab-data.validator.ts index 2b8db255e0..32baf38fbb 100644 --- a/src/renderer/components/dock/logs/log-tab-data.validator.ts +++ b/src/renderer/components/dock/logs/log-tab-data.validator.ts @@ -3,10 +3,22 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import Joi from "joi"; +import type { LogTabData, LogTabOwnerRef } from "./tab-store"; -export const logTabDataValidator = Joi.object({ - ownerId: Joi - .string() +export const logTabDataValidator = Joi.object({ + owner: Joi + .object({ + uid: Joi + .string() + .required(), + name: Joi + .string() + .required(), + kind: Joi + .string() + .required(), + }) + .unknown(true) .optional(), selectedPodId: Joi .string() @@ -20,7 +32,7 @@ export const logTabDataValidator = Joi.object({ showTimestamps: Joi .boolean() .required(), - previous: Joi + showPrevious: Joi .boolean() .required(), }); diff --git a/src/renderer/components/dock/logs/logs-view-model.injectable.ts b/src/renderer/components/dock/logs/logs-view-model.injectable.ts index 71264ab129..9969191f4f 100644 --- a/src/renderer/components/dock/logs/logs-view-model.injectable.ts +++ b/src/renderer/components/dock/logs/logs-view-model.injectable.ts @@ -12,10 +12,10 @@ import reloadLogsInjectable from "./reload-logs.injectable"; import getLogTabDataInjectable from "./get-log-tab-data.injectable"; import loadLogsInjectable from "./load-logs.injectable"; import setLogTabDataInjectable from "./set-log-tab-data.injectable"; -import updateTabNameInjectable from "./update-tab-name.injectable"; import stopLoadingLogsInjectable from "./stop-loading-logs.injectable"; import { podsStore } from "../../+workloads-pods/pods.store"; import createSearchStoreInjectable from "../../../search-store/create-search-store.injectable"; +import renameTabInjectable from "../dock/rename-tab.injectable"; export interface InstantiateArgs { tabId: TabId; @@ -30,7 +30,7 @@ const logsViewModelInjectable = getInjectable({ getLogTabData: di.inject(getLogTabDataInjectable), setLogTabData: di.inject(setLogTabDataInjectable), loadLogs: di.inject(loadLogsInjectable), - updateTabName: di.inject(updateTabNameInjectable), + renameTab: di.inject(renameTabInjectable), stopLoadingLogs: di.inject(stopLoadingLogsInjectable), getPodById: id => podsStore.getById(id), getPodsByOwnerId: id => podsStore.getPodsByOwnerId(id), diff --git a/src/renderer/components/dock/logs/logs-view-model.ts b/src/renderer/components/dock/logs/logs-view-model.ts index 3af2ea8612..5598298c53 100644 --- a/src/renderer/components/dock/logs/logs-view-model.ts +++ b/src/renderer/components/dock/logs/logs-view-model.ts @@ -16,7 +16,7 @@ export interface LogTabViewModelDependencies { setLogTabData: (tabId: TabId, data: LogTabData) => void; loadLogs: (tabId: TabId, logTabData: IComputedValue) => Promise; reloadLogs: (tabId: TabId, logTabData: IComputedValue) => Promise; - updateTabName: (tabId: TabId, pod: Pod) => void; + renameTab: (tabId: TabId, title: string) => void; stopLoadingLogs: (tabId: TabId) => void; getPodById: (id: string) => Pod | undefined; getPodsByOwnerId: (id: string) => Pod[]; @@ -37,8 +37,8 @@ export class LogTabViewModel { return []; } - if (typeof data.ownerId === "string") { - return this.dependencies.getPodsByOwnerId(data.ownerId); + if (typeof data.owner?.uid === "string") { + return this.dependencies.getPodsByOwnerId(data.owner.uid); } return [this.dependencies.getPodById(data.selectedPodId)]; @@ -60,6 +60,6 @@ export class LogTabViewModel { loadLogs = () => this.dependencies.loadLogs(this.tabId, this.logTabData); reloadLogs = () => this.dependencies.reloadLogs(this.tabId, this.logTabData); - updateTabName = () => this.dependencies.updateTabName(this.tabId, this.pod.get()); + renameTab = (title: string) => this.dependencies.renameTab(this.tabId, title); stopLoadingLogs = () => this.dependencies.stopLoadingLogs(this.tabId); } diff --git a/src/renderer/components/dock/logs/resource-selector.tsx b/src/renderer/components/dock/logs/resource-selector.tsx index f664c42862..459069fd61 100644 --- a/src/renderer/components/dock/logs/resource-selector.tsx +++ b/src/renderer/components/dock/logs/resource-selector.tsx @@ -5,18 +5,25 @@ import "./resource-selector.scss"; -import React, { useEffect } from "react"; +import React from "react"; import { observer } from "mobx-react"; import { Badge } from "../../badge"; import { Select, SelectOption } from "../../select"; import type { LogTabViewModel } from "./logs-view-model"; -import { action } from "mobx"; +import type { IPodContainer, Pod } from "../../../../common/k8s-api/endpoints"; export interface LogResourceSelectorProps { model: LogTabViewModel; } +function getSelectOptions(containers: IPodContainer[]): SelectOption[] { + return containers.map(container => ({ + value: container.name, + label: container.name, + })); +} + export const LogResourceSelector = observer(({ model }: LogResourceSelectorProps) => { const tabData = model.logTabData.get(); @@ -24,65 +31,61 @@ export const LogResourceSelector = observer(({ model }: LogResourceSelectorProps return null; } - const { selectedContainer } = tabData; + const { selectedContainer, owner } = tabData; const pods = model.pods.get(); const pod = model.pod.get(); - const containers = pod.getContainers(); - const initContainers = pod.getInitContainers(); + + if (!pod) { + return null; + } const onContainerChange = (option: SelectOption) => { model.updateLogTabData({ selectedContainer: option.value, }); - model.reloadLogs(); }; - const onPodChange = action((option: SelectOption) => { + const onPodChange = ({ value }: SelectOption) => { model.updateLogTabData({ - selectedPodId: option.value, - }); - model.updateTabName(); - }); - - const getSelectOptions = (items: string[]) => { - return items.map(item => { - return { - value: item, - label: item, - }; + selectedPodId: value.getId(), + selectedContainer: value.getAllContainers()[0]?.name, }); + model.renameTab(`Pod ${value.getName()}`); + model.reloadLogs(); }; const containerSelectOptions = [ { - label: `Containers`, - options: getSelectOptions(containers.map(container => container.name)), + label: "Containers", + options: getSelectOptions(pod.getContainers()), }, { - label: `Init Containers`, - options: getSelectOptions(initContainers.map(container => container.name)), + label: "Init Containers", + options: getSelectOptions(pod.getInitContainers()), }, ]; - const podSelectOptions = [ - { - label: pod.getOwnerRefs()[0]?.name, - options: getSelectOptions(pods.map(pod => pod.metadata.name)), - }, - ]; - - useEffect(() => { - model.reloadLogs(); - }, [pod.getId()]); + const podSelectOptions = pods.map(pod => ({ + label: pod.getName(), + value: pod, + })); return (
Namespace + { + owner && ( + <> + Owner + + ) + } Pod