1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Introduce download logs dropdown

Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com>
This commit is contained in:
Alex Andreev 2022-08-01 14:18:04 +03:00
parent e0a061c0ce
commit f12e2e1345
5 changed files with 143 additions and 6 deletions

View File

@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`download logs when opening pod logs renders 1`] = `
exports[`download logs options in pod logs dock tab when opening pod logs renders 1`] = `
<body>
<div>
<div
@ -823,9 +823,26 @@ exports[`download logs when opening pod logs renders 1`] = `
Show previous terminated container
</span>
</label>
<button
class="dropdown"
data-testid="download-logs-dropdown"
id="download-logs-dropdown"
>
Download
<i
class="Icon material focusable smallest"
>
<span
class="icon"
data-icon-name="arrow_drop_down"
>
arrow_drop_down
</span>
</i>
</button>
<i
class="Icon download-icon material interactive focusable"
id="tooltip_target_29"
id="tooltip_target_30"
tabindex="0"
>
<span
@ -838,7 +855,7 @@ exports[`download logs when opening pod logs renders 1`] = `
</i>
<i
class="Icon download-icon material interactive focusable"
id="tooltip_target_30"
id="tooltip_target_31"
tabindex="0"
>
<span

View File

@ -64,7 +64,7 @@ const getOnePodViewModel = (tabId: TabId, deps: Partial<LogTabViewModelDependenc
});
};
describe("download logs", () => {
describe("download logs options in pod logs dock tab", () => {
let builder: ApplicationBuilder;
beforeEach(() => {
@ -111,8 +111,11 @@ describe("download logs", () => {
});
it("renders", () => {
// expect(rendered.getByText("Storage")).toBeInTheDocument();
expect(rendered.baseElement).toMatchSnapshot();
});
it("contains download dropdown button", () => {
expect(rendered.getByTestId("download-logs-dropdown")).toBeInTheDocument();
});
});
});

View File

@ -15,6 +15,7 @@ import type { LogTabViewModel } from "./logs-view-model";
import { withInjectables } from "@ogre-tools/injectable-react";
import openSaveFileDialogInjectable from "../../../utils/save-file.injectable";
import callForAllLogsInjectable from "./call-for-all-logs.injectable";
import { DownloadLogsDropdown } from "./download-logs-dropdown";
export interface LogControlsProps {
model: LogTabViewModel;
@ -53,18 +54,24 @@ const NonInjectedLogControls = observer(({ openSaveFileDialog, model, callForAll
const logs = await callForAllLogs(pod.getName(), pod.getNs());
console.log(logs);
return !!logs;
}
return false;
// openSaveFileDialog("logs.txt", logs, "text/plain");
}
const downloadLogs = () => {
const downloadLogs = (): Promise<boolean> => {
const fileName = pod.getName();
const logsToDownload: string[] = showTimestamps
? model.logs.get()
: model.logsWithoutTimestamps.get();
openSaveFileDialog(`${fileName}.log`, logsToDownload.join("\n"), "text/plain");
return new Promise(resolve => resolve(true));
};
return (
@ -91,6 +98,12 @@ const NonInjectedLogControls = observer(({ openSaveFileDialog, model, callForAll
onChange={togglePrevious}
className="show-previous"
/>
<DownloadLogsDropdown
downloadVisibleLogs={downloadLogs}
downloadAllLogs={downloadAllLogs}
/>
<Icon
material="get_app"
onClick={downloadLogs}

View File

@ -0,0 +1,40 @@
.dropDown {
--accent-color: var(--colorOk);
border: 1px solid var(--accent-color);
border-radius: 4px;
color: var(--accent-color);
display: flex;
align-items: center;
padding: calc(var(--padding) / 4) var(--padding);
gap: 6px;
cursor: default;
position: relative;
&.waiting {
cursor: progress;
pointer-events: none;
opacity: .5;
}
&:hover::before{
opacity: 0.25;
}
&:focus-visible {
box-shadow: 0 0 0 2px var(--blue);
border-color: transparent;
}
&::before {
content: " ";
position: absolute;
background: var(--accent-color);
width: 100%;
height: 100%;
left: 0;
opacity: 0.15;
z-index: -1;
transition: opacity 0.1s;
}
}

View File

@ -0,0 +1,64 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import styles from "./download-logs-dropdown.module.scss";
import React, { useState } from "react";
import { cssNames } from "../../../utils";
import { Icon } from "../../icon";
import { Menu, MenuItem } from "../../menu";
interface DownloadLogsDropdownProps {
downloadVisibleLogs: () => Promise<boolean>
downloadAllLogs: () => Promise<boolean>
}
export function DownloadLogsDropdown({ downloadAllLogs, downloadVisibleLogs }: DownloadLogsDropdownProps) {
const [waiting, setWaiting] = useState(false);
const [opened, setOpened] = useState(false);
const toggle = () => {
setOpened(!opened);
};
const downloadLogs = async (download: () => Promise<boolean>) => {
setWaiting(true);
await download();
setWaiting(false);
}
return (
<>
<button
data-testid="download-logs-dropdown"
id="download-logs-dropdown"
className={cssNames(styles.dropdown, { [styles.waiting]: waiting })}
>
Download
<Icon material="arrow_drop_down" smallest/>
</button>
<Menu
usePortal
htmlFor="download-logs-dropdown"
isOpen={opened}
close={toggle}
open={toggle}
>
<MenuItem
onClick={() => downloadLogs(downloadVisibleLogs)}
data-testid="download-visible-logs"
>
Visible logs
</MenuItem>
<MenuItem
onClick={() => downloadLogs(downloadAllLogs)}
data-testid="download-all-logs"
>
All logs
</MenuItem>
</Menu>
</>
);
}