Topbar history buttons (#3696)

* HistoryStore initial draft

Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com>

* Adding history icons

Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com>

* Jump history using electron methods

Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com>

* Using 1 topbar component for all views

Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com>

* Add Catalog title to sidebar

Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com>

* Show cluster name in sidebar

Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com>

* Updating topbar tests

Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com>

* Fixing Welcome tests

Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com>

* Removing padding for external topbar items

Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com>

* Fix cluster name prop

Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com>

* Using material icons for history buttons

Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com>
This commit is contained in:
Alex Andreev authored and GitHub committed 2021-08-31 14:44:47 +03:00
1 parent 9d6bed8786
commit 7981e79cbd
16 files changed
+163 -132

No files matched your search

@@ -20,11 +20,46 @@
*/
import React from "react";
import { render } from "@testing-library/react";
import { render, fireEvent } from "@testing-library/react";
import "@testing-library/jest-dom/extend-expect";
import { TopBar } from "../topbar";
import { TopBarRegistry } from "../../../../extensions/registries";
jest.mock(
"electron",
() => ({
ipcRenderer: {
on: jest.fn(
(channel: string, listener: (event: any, ...args: any[]) => void) => {
if (channel === "history:can-go-back") {
listener({}, true);
}
if (channel === "history:can-go-forward") {
listener({}, true);
}
}
),
},
})
);
const goBack = jest.fn();
const goForward = jest.fn();
jest.mock("@electron/remote", () => {
return {
webContents: {
getFocusedWebContents: () => {
return {
goBack,
goForward
};
}
}
};
});
describe("<TopBar/>", () => {
beforeEach(() => {
TopBarRegistry.createInstance();
@@ -35,15 +70,38 @@ describe("<TopBar/>", () => {
});
it("renders w/o errors", () => {
const { container } = render(<TopBar label="test bar" />);
const { container } = render(<TopBar/>);
expect(container).toBeInstanceOf(HTMLElement);
});
it("renders title", async () => {
const { getByTestId } = render(<TopBar label="topbar" />);
it("renders history arrows", async () => {
const { getByTestId } = render(<TopBar/>);
expect(await getByTestId("topbarLabel")).toHaveTextContent("topbar");
expect(await getByTestId("history-back")).toBeInTheDocument();
expect(await getByTestId("history-forward")).toBeInTheDocument();
});
it("enables arrow by ipc event", async () => {
const { getByTestId } = render(<TopBar/>);
expect(await getByTestId("history-back")).not.toHaveClass("disabled");
expect(await getByTestId("history-forward")).not.toHaveClass("disabled");
});
it("triggers browser history back and forward", async () => {
const { getByTestId } = render(<TopBar/>);
const prevButton = await getByTestId("history-back");
const nextButton = await getByTestId("history-forward");
fireEvent.click(prevButton);
expect(goBack).toBeCalled();
fireEvent.click(nextButton);
expect(goForward).toBeCalled();
});
it("renders items", async () => {
@@ -58,7 +116,7 @@ describe("<TopBar/>", () => {
}
]);
const { getByTestId } = render(<TopBar label="topbar" />);
const { getByTestId } = render(<TopBar/>);
expect(await getByTestId(testId)).toHaveTextContent(text);
});
@@ -45,4 +45,12 @@
padding: $padding;
text-align: center;
}
.cluster-name {
padding: 1.25rem;
font-weight: bold;
font-size: 1.5rem;
word-break: break-all;
color: var(--textColorAccent);
}
}
@@ -40,6 +40,8 @@ import { SidebarItem } from "./sidebar-item";
import { Apps } from "../+apps";
import * as routes from "../../../common/routes";
import { Config } from "../+config";
import { ClusterStore } from "../../../common/cluster-store";
import { App } from "../app";
interface Props {
className?: string;
@@ -181,6 +183,9 @@ export class Sidebar extends React.Component<Props> {
return (
<div className={cssNames(Sidebar.displayName, "flex column", className)}>
<div className="cluster-name">
{ClusterStore.getInstance().getById(App.clusterId)?.name}
</div>
<div className={cssNames("sidebar-nav flex column box grow-fixed")}>
<SidebarItem
id="cluster"
@@ -30,11 +30,8 @@
grid-area: topbar;
}
.title {
@apply font-bold px-6;
color: var(--textColorAccent);
align-items: center;
display: flex;
.history {
@apply flex items-center;
}
.controls {
+49 -5
View File
@@ -20,15 +20,30 @@
*/
import styles from "./topbar.module.css";
import React from "react";
import React, { useEffect } from "react";
import { observer } from "mobx-react";
import { TopBarRegistry } from "../../../extensions/registries";
import { Icon } from "../icon";
import { webContents } from "@electron/remote";
import { observable } from "mobx";
import { ipcRendererOn } from "../../../common/ipc";
import { watchHistoryState } from "../../remote-helpers/history-updater";
interface Props extends React.HTMLAttributes<any> {
label: React.ReactNode;
}
export const TopBar = observer(({ label, children, ...rest }: Props) => {
const prevEnabled = observable.box(false);
const nextEnabled = observable.box(false);
ipcRendererOn("history:can-go-back", (event, state: boolean) => {
prevEnabled.set(state);
});
ipcRendererOn("history:can-go-forward", (event, state: boolean) => {
nextEnabled.set(state);
});
export const TopBar = observer(({ children, ...rest }: Props) => {
const renderRegisteredItems = () => {
const items = TopBarRegistry.getInstance().getItems();
@@ -37,7 +52,7 @@ export const TopBar = observer(({ label, children, ...rest }: Props) => {
}
return (
<div className="px-6">
<div>
{items.map((registration, index) => {
if (!registration?.components?.Item) {
return null;
@@ -53,9 +68,38 @@ export const TopBar = observer(({ label, children, ...rest }: Props) => {
);
};
const goBack = () => {
webContents.getFocusedWebContents()?.goBack();
};
const goForward = () => {
webContents.getFocusedWebContents()?.goForward();
};
useEffect(() => {
const disposer = watchHistoryState();
return () => disposer();
}, []);
return (
<div className={styles.topBar} {...rest}>
<div className={styles.title} data-testid="topbarLabel">{label}</div>
<div className={styles.history}>
<Icon
data-testid="history-back"
material="arrow_back"
className="ml-5"
onClick={goBack}
disabled={!prevEnabled.get()}
/>
<Icon
data-testid="history-forward"
material="arrow_forward"
className="ml-5"
onClick={goForward}
disabled={!nextEnabled.get()}
/>
</div>
<div className={styles.controls}>
{renderRegisteredItems()}
{children}