mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Fix build
Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
parent
3862122031
commit
d9a8d8fc8a
@ -351,6 +351,7 @@
|
|||||||
"fork-ts-checker-webpack-plugin": "^5.2.1",
|
"fork-ts-checker-webpack-plugin": "^5.2.1",
|
||||||
"hoist-non-react-statics": "^3.3.2",
|
"hoist-non-react-statics": "^3.3.2",
|
||||||
"html-webpack-plugin": "^4.5.2",
|
"html-webpack-plugin": "^4.5.2",
|
||||||
|
"ignore-loader": "^0.1.2",
|
||||||
"include-media": "^1.4.9",
|
"include-media": "^1.4.9",
|
||||||
"jest": "26.6.3",
|
"jest": "26.6.3",
|
||||||
"jest-canvas-mock": "^2.3.1",
|
"jest-canvas-mock": "^2.3.1",
|
||||||
|
|||||||
@ -7,12 +7,17 @@ import { getLegacyGlobalDiForExtensionApi } from "./legacy-global-di-for-extensi
|
|||||||
|
|
||||||
type TentativeTuple<T> = T extends object ? [T] : [undefined?];
|
type TentativeTuple<T> = T extends object ? [T] : [undefined?];
|
||||||
|
|
||||||
|
type MapInjectables<T> = {
|
||||||
|
[Key in keyof T]: T[Key] extends () => infer Res ? Res : never;
|
||||||
|
};
|
||||||
|
|
||||||
export const asLegacyGlobalObjectForExtensionApiWithModifications = <
|
export const asLegacyGlobalObjectForExtensionApiWithModifications = <
|
||||||
TInjectable extends Injectable<unknown, unknown, TInstantiationParameter>,
|
TInjectable extends Injectable<unknown, unknown, TInstantiationParameter>,
|
||||||
TInstantiationParameter,
|
TInstantiationParameter,
|
||||||
|
OtherFields extends Record<string, () => any>,
|
||||||
>(
|
>(
|
||||||
injectableKey: TInjectable,
|
injectableKey: TInjectable,
|
||||||
otherFields: Record<string | symbol, () => any>,
|
otherFields: OtherFields,
|
||||||
...instantiationParameter: TentativeTuple<TInstantiationParameter>
|
...instantiationParameter: TentativeTuple<TInstantiationParameter>
|
||||||
) =>
|
) =>
|
||||||
new Proxy(
|
new Proxy(
|
||||||
@ -28,7 +33,7 @@ export const asLegacyGlobalObjectForExtensionApiWithModifications = <
|
|||||||
...instantiationParameter,
|
...instantiationParameter,
|
||||||
);
|
);
|
||||||
|
|
||||||
const propertyValue = instance[propertyName] ?? otherFields[propertyName]?.();
|
const propertyValue = instance[propertyName] ?? otherFields[propertyName as any];
|
||||||
|
|
||||||
if (typeof propertyValue === "function") {
|
if (typeof propertyValue === "function") {
|
||||||
return function (...args: any[]) {
|
return function (...args: any[]) {
|
||||||
@ -39,4 +44,4 @@ export const asLegacyGlobalObjectForExtensionApiWithModifications = <
|
|||||||
return propertyValue;
|
return propertyValue;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
) as ReturnType<TInjectable["instantiate"]>;
|
) as ReturnType<TInjectable["instantiate"]> & MapInjectables<OtherFields>;
|
||||||
|
|||||||
@ -19,6 +19,7 @@ import directoryForUserDataInjectable from "../../../../../common/app-paths/dire
|
|||||||
import callForLogsInjectable from "../call-for-logs.injectable";
|
import callForLogsInjectable from "../call-for-logs.injectable";
|
||||||
import { LogTabViewModel, LogTabViewModelDependencies } from "../logs-view-model";
|
import { LogTabViewModel, LogTabViewModelDependencies } from "../logs-view-model";
|
||||||
import type { TabId } from "../../dock/store";
|
import type { TabId } from "../../dock/store";
|
||||||
|
import userEvent from "@testing-library/user-event";
|
||||||
|
|
||||||
jest.mock("electron", () => ({
|
jest.mock("electron", () => ({
|
||||||
app: {
|
app: {
|
||||||
@ -57,7 +58,7 @@ function mockLogTabViewModel(tabId: TabId, deps: Partial<LogTabViewModelDependen
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const getOnePodViewModel = (tabId: TabId): LogTabViewModel => {
|
const getOnePodViewModel = (tabId: TabId, deps: Partial<LogTabViewModelDependencies> = {}): LogTabViewModel => {
|
||||||
const selectedPod = new Pod(dockerPod);
|
const selectedPod = new Pod(dockerPod);
|
||||||
|
|
||||||
return mockLogTabViewModel(tabId, {
|
return mockLogTabViewModel(tabId, {
|
||||||
@ -75,10 +76,11 @@ const getOnePodViewModel = (tabId: TabId): LogTabViewModel => {
|
|||||||
|
|
||||||
return undefined;
|
return undefined;
|
||||||
},
|
},
|
||||||
|
...deps,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const getFewPodsTabData = (tabId: TabId): LogTabViewModel => {
|
const getFewPodsTabData = (tabId: TabId, deps: Partial<LogTabViewModelDependencies> = {}): LogTabViewModel => {
|
||||||
const selectedPod = new Pod(deploymentPod1);
|
const selectedPod = new Pod(deploymentPod1);
|
||||||
const anotherPod = new Pod(deploymentPod2);
|
const anotherPod = new Pod(deploymentPod2);
|
||||||
|
|
||||||
@ -109,6 +111,7 @@ const getFewPodsTabData = (tabId: TabId): LogTabViewModel => {
|
|||||||
|
|
||||||
return [];
|
return [];
|
||||||
},
|
},
|
||||||
|
...deps,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -167,18 +170,15 @@ describe("<LogResourceSelector />", () => {
|
|||||||
const { container, findByText } = render(getComponent(model));
|
const { container, findByText } = render(getComponent(model));
|
||||||
|
|
||||||
selectEvent.openMenu(container.querySelector(".pod-selector"));
|
selectEvent.openMenu(container.querySelector(".pod-selector"));
|
||||||
|
expect(await findByText("deploymentPod2", { selector: ".pod-selector-menu .Select__option" })).toBeInTheDocument();
|
||||||
expect(await findByText("dockerExporter", { selector: ".pod-selector-menu .Select__option" })).toBeInTheDocument();
|
|
||||||
expect(await findByText("deploymentPod1", { selector: ".pod-selector-menu .Select__option" })).toBeInTheDocument();
|
expect(await findByText("deploymentPod1", { selector: ".pod-selector-menu .Select__option" })).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("renders sibling containers in dropdown", async () => {
|
it("renders sibling containers in dropdown", async () => {
|
||||||
const model = getFewPodsTabData("foobar");
|
const model = getFewPodsTabData("foobar");
|
||||||
const { findByText, container } = render(getComponent(model));
|
const { findByText, container } = render(getComponent(model));
|
||||||
const containerSelector: HTMLElement = container.querySelector(".container-selector");
|
|
||||||
|
|
||||||
selectEvent.openMenu(containerSelector);
|
|
||||||
|
|
||||||
|
selectEvent.openMenu(container.querySelector(".container-selector"));
|
||||||
expect(await findByText("node-exporter-1")).toBeInTheDocument();
|
expect(await findByText("node-exporter-1")).toBeInTheDocument();
|
||||||
expect(await findByText("init-node-exporter")).toBeInTheDocument();
|
expect(await findByText("init-node-exporter")).toBeInTheDocument();
|
||||||
expect(await findByText("init-node-exporter-1")).toBeInTheDocument();
|
expect(await findByText("init-node-exporter-1")).toBeInTheDocument();
|
||||||
@ -187,10 +187,19 @@ describe("<LogResourceSelector />", () => {
|
|||||||
it("renders pod owner as dropdown title", async () => {
|
it("renders pod owner as dropdown title", async () => {
|
||||||
const model = getFewPodsTabData("foobar");
|
const model = getFewPodsTabData("foobar");
|
||||||
const { findByText, container } = render(getComponent(model));
|
const { findByText, container } = render(getComponent(model));
|
||||||
const podSelector: HTMLElement = container.querySelector(".pod-selector");
|
|
||||||
|
|
||||||
selectEvent.openMenu(podSelector);
|
|
||||||
|
|
||||||
|
selectEvent.openMenu(container.querySelector(".pod-selector"));
|
||||||
expect(await findByText("super-deployment")).toBeInTheDocument();
|
expect(await findByText("super-deployment")).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("updates tab name if selected pod changes", async () => {
|
||||||
|
const updateTabName = jest.fn();
|
||||||
|
const model = getFewPodsTabData("foobar", { updateTabName });
|
||||||
|
const { findByText, container } = render(getComponent(model));
|
||||||
|
|
||||||
|
selectEvent.openMenu(container.querySelector(".pod-selector"));
|
||||||
|
|
||||||
|
userEvent.click(await findByText("deploymentPod2", { selector: ".pod-selector-menu .Select__option" }));
|
||||||
|
expect(updateTabName).toBeCalled();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -0,0 +1,6 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export {};
|
||||||
@ -1,149 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
|
||||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { podsStore } from "../../../+workloads-pods/pods.store";
|
|
||||||
import { UserStore } from "../../../../../common/user-store";
|
|
||||||
import { Pod } from "../../../../../common/k8s-api/endpoints";
|
|
||||||
import { ThemeStore } from "../../../../theme.store";
|
|
||||||
import { deploymentPod1, deploymentPod2, deploymentPod3, dockerPod } from "./pod.mock";
|
|
||||||
import { mockWindow } from "../../../../../../__mocks__/windowMock";
|
|
||||||
import { getDiForUnitTesting } from "../../../../getDiForUnitTesting";
|
|
||||||
import logTabStoreInjectable from "../tab-store.injectable";
|
|
||||||
import type { LogTabStore } from "../tab-store";
|
|
||||||
import dockStoreInjectable from "../../dock/store.injectable";
|
|
||||||
import type { DockStore, TabId } from "../../dock/store";
|
|
||||||
import directoryForUserDataInjectable from "../../../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
|
|
||||||
import mockFs from "mock-fs";
|
|
||||||
import type { PodLogsTabData } from "../create-pod-logs-tab.injectable";
|
|
||||||
import createPodLogsTabInjectable from "../create-pod-logs-tab.injectable";
|
|
||||||
|
|
||||||
mockWindow();
|
|
||||||
|
|
||||||
podsStore.items.push(new Pod(dockerPod));
|
|
||||||
podsStore.items.push(new Pod(deploymentPod1));
|
|
||||||
podsStore.items.push(new Pod(deploymentPod2));
|
|
||||||
|
|
||||||
describe("log tab store", () => {
|
|
||||||
let logTabStore: LogTabStore;
|
|
||||||
let dockStore: DockStore;
|
|
||||||
let createPodTab: ({ selectedPod, selectedContainer }: PodLogsTabData) => TabId;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
const di = getDiForUnitTesting({ doGeneralOverrides: true });
|
|
||||||
|
|
||||||
mockFs();
|
|
||||||
|
|
||||||
di.override(directoryForUserDataInjectable, () => "some-directory-for-user-data");
|
|
||||||
|
|
||||||
await di.runSetups();
|
|
||||||
|
|
||||||
dockStore = di.inject(dockStoreInjectable);
|
|
||||||
logTabStore = di.inject(logTabStoreInjectable);
|
|
||||||
createPodTab = di.inject(createPodLogsTabInjectable);
|
|
||||||
|
|
||||||
UserStore.createInstance();
|
|
||||||
ThemeStore.createInstance();
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
UserStore.resetInstance();
|
|
||||||
ThemeStore.resetInstance();
|
|
||||||
mockFs.restore();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("creates log tab without sibling pods", () => {
|
|
||||||
const selectedPod = new Pod(dockerPod);
|
|
||||||
const selectedContainer = selectedPod.getAllContainers()[0];
|
|
||||||
|
|
||||||
createPodTab({
|
|
||||||
selectedPod,
|
|
||||||
selectedContainer,
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(logTabStore.getData(dockStore.selectedTabId)).toEqual({
|
|
||||||
pods: [selectedPod],
|
|
||||||
selectedPod,
|
|
||||||
selectedContainer,
|
|
||||||
showTimestamps: false,
|
|
||||||
previous: false,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("creates log tab with sibling pods", () => {
|
|
||||||
const selectedPod = new Pod(deploymentPod1);
|
|
||||||
const siblingPod = new Pod(deploymentPod2);
|
|
||||||
const selectedContainer = selectedPod.getInitContainers()[0];
|
|
||||||
|
|
||||||
createPodTab({
|
|
||||||
selectedPod,
|
|
||||||
selectedContainer,
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(logTabStore.getData(dockStore.selectedTabId)).toEqual({
|
|
||||||
pods: [selectedPod, siblingPod],
|
|
||||||
selectedPod,
|
|
||||||
selectedContainer,
|
|
||||||
showTimestamps: false,
|
|
||||||
previous: false,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("removes item from pods list if pod deleted from store", () => {
|
|
||||||
const selectedPod = new Pod(deploymentPod1);
|
|
||||||
const selectedContainer = selectedPod.getInitContainers()[0];
|
|
||||||
|
|
||||||
createPodTab({
|
|
||||||
selectedPod,
|
|
||||||
selectedContainer,
|
|
||||||
});
|
|
||||||
|
|
||||||
podsStore.items.pop();
|
|
||||||
|
|
||||||
expect(logTabStore.getData(dockStore.selectedTabId)).toEqual({
|
|
||||||
pods: [selectedPod],
|
|
||||||
selectedPod,
|
|
||||||
selectedContainer,
|
|
||||||
showTimestamps: false,
|
|
||||||
previous: false,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("adds item into pods list if new sibling pod added to store", () => {
|
|
||||||
const selectedPod = new Pod(deploymentPod1);
|
|
||||||
const selectedContainer = selectedPod.getInitContainers()[0];
|
|
||||||
|
|
||||||
createPodTab({
|
|
||||||
selectedPod,
|
|
||||||
selectedContainer,
|
|
||||||
});
|
|
||||||
|
|
||||||
podsStore.items.push(new Pod(deploymentPod3));
|
|
||||||
|
|
||||||
expect(logTabStore.getData(dockStore.selectedTabId)).toEqual({
|
|
||||||
pods: [selectedPod, deploymentPod3],
|
|
||||||
selectedPod,
|
|
||||||
selectedContainer,
|
|
||||||
showTimestamps: false,
|
|
||||||
previous: false,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// FIXME: this is failed when it's not .only == depends on something above
|
|
||||||
it.only("closes tab if no pods left in store", async () => {
|
|
||||||
const selectedPod = new Pod(deploymentPod1);
|
|
||||||
const selectedContainer = selectedPod.getInitContainers()[0];
|
|
||||||
|
|
||||||
const id = createPodTab({
|
|
||||||
selectedPod,
|
|
||||||
selectedContainer,
|
|
||||||
});
|
|
||||||
|
|
||||||
podsStore.items.clear();
|
|
||||||
|
|
||||||
expect(logTabStore.getData(dockStore.selectedTabId)).toBeUndefined();
|
|
||||||
expect(logTabStore.getData(id)).toBeUndefined();
|
|
||||||
expect(dockStore.getTabById(id)).toBeUndefined();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@ -8,16 +8,22 @@ import "./controls.scss";
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
|
|
||||||
import { cssNames, saveFileDialog } from "../../../utils";
|
import { cssNames } from "../../../utils";
|
||||||
import { Checkbox } from "../../checkbox";
|
import { Checkbox } from "../../checkbox";
|
||||||
import { Icon } from "../../icon";
|
import { Icon } from "../../icon";
|
||||||
import type { LogTabViewModel } from "./logs-view-model";
|
import type { LogTabViewModel } from "./logs-view-model";
|
||||||
|
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||||
|
import openSaveFileDialogInjectable from "../../../utils/save-file.injectable";
|
||||||
|
|
||||||
export interface LogControlsProps {
|
export interface LogControlsProps {
|
||||||
model: LogTabViewModel;
|
model: LogTabViewModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const LogControls = observer(({ model }: LogControlsProps) => {
|
interface Dependencies {
|
||||||
|
openSaveFileDialog: (filename: string, contents: BlobPart | BlobPart[], type: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const NonInjectedLogControls = observer(({ openSaveFileDialog, model }: Dependencies & LogControlsProps) => {
|
||||||
const tabData = model.logTabData.get();
|
const tabData = model.logTabData.get();
|
||||||
|
|
||||||
if (!tabData) {
|
if (!tabData) {
|
||||||
@ -43,7 +49,7 @@ export const LogControls = observer(({ model }: LogControlsProps) => {
|
|||||||
? model.logs.get()
|
? model.logs.get()
|
||||||
: model.logsWithoutTimestamps.get();
|
: model.logsWithoutTimestamps.get();
|
||||||
|
|
||||||
saveFileDialog(`${fileName}.log`, logsToDownload.join("\n"), "text/plain");
|
openSaveFileDialog(`${fileName}.log`, logsToDownload.join("\n"), "text/plain");
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -79,3 +85,10 @@ export const LogControls = observer(({ model }: LogControlsProps) => {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const LogControls = withInjectables<Dependencies, LogControlsProps>(NonInjectedLogControls, {
|
||||||
|
getProps: (di, props) => ({
|
||||||
|
openSaveFileDialog: di.inject(openSaveFileDialogInjectable),
|
||||||
|
...props,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|||||||
@ -212,8 +212,6 @@ export class LogList extends React.Component<LogListProps> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const rowHeights = array.filled(this.logs.length, this.lineHeight);
|
|
||||||
|
|
||||||
if (!this.logs.length) {
|
if (!this.logs.length) {
|
||||||
return (
|
return (
|
||||||
<div className="LogList flex box grow align-center justify-center">
|
<div className="LogList flex box grow align-center justify-center">
|
||||||
@ -226,7 +224,7 @@ export class LogList extends React.Component<LogListProps> {
|
|||||||
<div className={cssNames("LogList flex" )}>
|
<div className={cssNames("LogList flex" )}>
|
||||||
<VirtualList
|
<VirtualList
|
||||||
items={this.logs}
|
items={this.logs}
|
||||||
rowHeights={rowHeights}
|
rowHeights={array.filled(this.logs.length, this.lineHeight)}
|
||||||
getRow={this.getLogRow}
|
getRow={this.getLogRow}
|
||||||
onScroll={this.onScroll}
|
onScroll={this.onScroll}
|
||||||
outerRef={this.virtualListDiv}
|
outerRef={this.virtualListDiv}
|
||||||
|
|||||||
@ -12,15 +12,13 @@ import { Icon } from "../../icon";
|
|||||||
import type { LogTabViewModel } from "./logs-view-model";
|
import type { LogTabViewModel } from "./logs-view-model";
|
||||||
|
|
||||||
export interface PodLogSearchProps {
|
export interface PodLogSearchProps {
|
||||||
onSearch: (query: string) => void;
|
onSearch?: (query: string) => void;
|
||||||
toPrevOverlay: () => void;
|
scrollToOverlay: (lineNumber: number | undefined) => void;
|
||||||
toNextOverlay: () => void;
|
|
||||||
model: LogTabViewModel;
|
model: LogTabViewModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const LogSearch = observer(({ onSearch, scrollToOverlay, model: { logTabData, searchStore, ...model }}: PodLogSearchProps) => {
|
||||||
export const LogSearch = observer(({ onSearch, toPrevOverlay, toNextOverlay, model }: PodLogSearchProps) => {
|
const tabData = logTabData.get();
|
||||||
const tabData = model.logTabData.get();
|
|
||||||
|
|
||||||
if (!tabData) {
|
if (!tabData) {
|
||||||
return null;
|
return null;
|
||||||
@ -29,27 +27,23 @@ export const LogSearch = observer(({ onSearch, toPrevOverlay, toNextOverlay, mod
|
|||||||
const logs = tabData.showTimestamps
|
const logs = tabData.showTimestamps
|
||||||
? model.logs.get()
|
? model.logs.get()
|
||||||
: model.logsWithoutTimestamps.get();
|
: model.logsWithoutTimestamps.get();
|
||||||
const { setNextOverlayActive, setPrevOverlayActive, searchQuery, occurrences, activeFind, totalFinds } = model.searchStore;
|
const { setNextOverlayActive, setPrevOverlayActive, searchQuery, occurrences, activeFind, totalFinds } = searchStore;
|
||||||
const jumpDisabled = !searchQuery || !occurrences.length;
|
const jumpDisabled = !searchQuery || !occurrences.length;
|
||||||
const findCounts = (
|
|
||||||
<div className="find-count">
|
|
||||||
{activeFind}/{totalFinds}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
const setSearch = (query: string) => {
|
const setSearch = (query: string) => {
|
||||||
model.searchStore.onSearch(logs, query);
|
searchStore.onSearch(logs, query);
|
||||||
onSearch(query);
|
onSearch?.(query);
|
||||||
|
scrollToOverlay(searchStore.activeOverlayLine);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onPrevOverlay = () => {
|
const onPrevOverlay = () => {
|
||||||
setPrevOverlayActive();
|
setPrevOverlayActive();
|
||||||
toPrevOverlay();
|
scrollToOverlay(searchStore.activeOverlayLine);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onNextOverlay = () => {
|
const onNextOverlay = () => {
|
||||||
setNextOverlayActive();
|
setNextOverlayActive();
|
||||||
toNextOverlay();
|
scrollToOverlay(searchStore.activeOverlayLine);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onClear = () => {
|
const onClear = () => {
|
||||||
@ -64,7 +58,7 @@ export const LogSearch = observer(({ onSearch, toPrevOverlay, toNextOverlay, mod
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Refresh search when logs changed
|
// Refresh search when logs changed
|
||||||
model.searchStore.onSearch(logs);
|
searchStore.onSearch(logs);
|
||||||
}, [logs]);
|
}, [logs]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -73,7 +67,11 @@ export const LogSearch = observer(({ onSearch, toPrevOverlay, toNextOverlay, mod
|
|||||||
value={searchQuery}
|
value={searchQuery}
|
||||||
onChange={setSearch}
|
onChange={setSearch}
|
||||||
showClearIcon={true}
|
showClearIcon={true}
|
||||||
contentRight={totalFinds > 0 && findCounts}
|
contentRight={totalFinds > 0 && (
|
||||||
|
<div className="find-count">
|
||||||
|
{activeFind}/{totalFinds}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
onClear={onClear}
|
onClear={onClear}
|
||||||
onKeyDown={onKeyDown}
|
onKeyDown={onKeyDown}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -46,15 +46,13 @@ const NonInjectedLogsDockTab = observer(({ className, tab, model, subscribeStore
|
|||||||
namespaces: data ? [data.namespace] : [],
|
namespaces: data ? [data.namespace] : [],
|
||||||
}), [data?.namespace]);
|
}), [data?.namespace]);
|
||||||
|
|
||||||
const scrollToOverlay = () => {
|
const scrollToOverlay = (overlayLine: number | undefined) => {
|
||||||
const { activeOverlayLine } = model.searchStore;
|
if (!logListElement.current || overlayLine === undefined) {
|
||||||
|
|
||||||
if (!logListElement.current || activeOverlayLine === undefined) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scroll vertically
|
// Scroll vertically
|
||||||
logListElement.current.scrollToItem(activeOverlayLine, "center");
|
logListElement.current.scrollToItem(overlayLine, "center");
|
||||||
// Scroll horizontally in timeout since virtual list need some time to prepare its contents
|
// Scroll horizontally in timeout since virtual list need some time to prepare its contents
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const overlay = document.querySelector(".PodLogs .list span.active");
|
const overlay = document.querySelector(".PodLogs .list span.active");
|
||||||
@ -76,10 +74,8 @@ const NonInjectedLogsDockTab = observer(({ className, tab, model, subscribeStore
|
|||||||
<div className="flex gaps">
|
<div className="flex gaps">
|
||||||
<LogResourceSelector model={model} />
|
<LogResourceSelector model={model} />
|
||||||
<LogSearch
|
<LogSearch
|
||||||
onSearch={scrollToOverlay}
|
|
||||||
model={model}
|
model={model}
|
||||||
toPrevOverlay={scrollToOverlay}
|
scrollToOverlay={scrollToOverlay}
|
||||||
toNextOverlay={scrollToOverlay}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
13
src/renderer/utils/save-file.injectable.ts
Normal file
13
src/renderer/utils/save-file.injectable.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
/**
|
||||||
|
* 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 { saveFileDialog } from "./saveFile";
|
||||||
|
|
||||||
|
const openSaveFileDialogInjectable = getInjectable({
|
||||||
|
instantiate: () => saveFileDialog,
|
||||||
|
lifecycle: lifecycleEnum.singleton,
|
||||||
|
});
|
||||||
|
|
||||||
|
export default openSaveFileDialogInjectable;
|
||||||
@ -34,6 +34,10 @@ export default function generateExtensionTypes(): webpack.Configuration {
|
|||||||
stats: "errors-warnings",
|
stats: "errors-warnings",
|
||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.node$/,
|
||||||
|
loader: "ignore-loader",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
test: /\.tsx?$/,
|
test: /\.tsx?$/,
|
||||||
loader: "ts-loader",
|
loader: "ts-loader",
|
||||||
|
|||||||
@ -7184,6 +7184,11 @@ ignore-by-default@^1.0.1:
|
|||||||
resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09"
|
resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09"
|
||||||
integrity sha1-SMptcvbGo68Aqa1K5odr44ieKwk=
|
integrity sha1-SMptcvbGo68Aqa1K5odr44ieKwk=
|
||||||
|
|
||||||
|
ignore-loader@^0.1.2:
|
||||||
|
version "0.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/ignore-loader/-/ignore-loader-0.1.2.tgz#d81f240376d0ba4f0d778972c3ad25874117a463"
|
||||||
|
integrity sha1-2B8kA3bQuk8Nd4lyw60lh0EXpGM=
|
||||||
|
|
||||||
ignore-walk@^3.0.1:
|
ignore-walk@^3.0.1:
|
||||||
version "3.0.3"
|
version "3.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.3.tgz#017e2447184bfeade7c238e4aefdd1e8f95b1e37"
|
resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.3.tgz#017e2447184bfeade7c238e4aefdd1e8f95b1e37"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user