mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Feat: Implement rendering of dock tab content
Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com>
This commit is contained in:
parent
934784c588
commit
88bf456cea
@ -7,19 +7,68 @@ exports[`DockHost, given rendered given implementations of dock tabs emerge rend
|
||||
<div
|
||||
class="flex align-center"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
data-dock-tab-test="some-dock-tab-1"
|
||||
>
|
||||
<div
|
||||
data-some-dock-tab-title-test="true"
|
||||
data-dock-tab-title-test="some-title-1"
|
||||
>
|
||||
Some title
|
||||
Some title 1
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
data-dock-tab-test="some-dock-tab-2"
|
||||
>
|
||||
<div
|
||||
data-dock-tab-title-test="some-title-2"
|
||||
>
|
||||
Some title 2
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
data-some-dock-tab-content-test="true"
|
||||
data-dock-tab-content-test="some-content-1"
|
||||
>
|
||||
Some content
|
||||
Some content 1
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
`;
|
||||
|
||||
exports[`DockHost, given rendered given implementations of dock tabs emerge when the second dock tab is clicked renders 1`] = `
|
||||
<body>
|
||||
<div>
|
||||
<div>
|
||||
<div
|
||||
class="flex align-center"
|
||||
>
|
||||
<div
|
||||
data-dock-tab-test="some-dock-tab-1"
|
||||
>
|
||||
<div
|
||||
data-dock-tab-title-test="some-title-1"
|
||||
>
|
||||
Some title 1
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
data-dock-tab-test="some-dock-tab-2"
|
||||
>
|
||||
<div
|
||||
data-dock-tab-title-test="some-title-2"
|
||||
>
|
||||
Some title 2
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
data-dock-tab-content-test="some-content-2"
|
||||
>
|
||||
Some content 2
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -4,6 +4,7 @@ import { renderFor } from "@k8slens/test-utils";
|
||||
import { DockHost } from "./dock/dock-host";
|
||||
import React from "react";
|
||||
import type { RenderResult } from "@testing-library/react";
|
||||
import { act } from "@testing-library/react";
|
||||
import { dockTabInjectionToken } from "./dock-tab";
|
||||
import { Discover, discoverFor } from "@k8slens/react-testing-library-discovery";
|
||||
import { registerFeature } from "@k8slens/feature-core";
|
||||
@ -31,20 +32,38 @@ describe("DockHost, given rendered", () => {
|
||||
|
||||
describe("given implementations of dock tabs emerge", () => {
|
||||
beforeEach(() => {
|
||||
const dockTabInjectable = getInjectable({
|
||||
id: "some-dock-tab",
|
||||
const dockTabInjectable1 = getInjectable({
|
||||
id: "some-dock-tab-1",
|
||||
|
||||
instantiate: () => ({
|
||||
id: "some-dock-tab",
|
||||
TitleComponent: () => <div data-some-dock-tab-title-test>Some title</div>,
|
||||
ContentComponent: () => <div data-some-dock-tab-content-test>Some content</div>,
|
||||
id: "some-dock-tab-1",
|
||||
TitleComponent: () => <div data-dock-tab-title-test="some-title-1">Some title 1</div>,
|
||||
|
||||
ContentComponent: () => (
|
||||
<div data-dock-tab-content-test="some-content-1">Some content 1</div>
|
||||
),
|
||||
}),
|
||||
|
||||
injectionToken: dockTabInjectionToken,
|
||||
});
|
||||
|
||||
const dockTabInjectable2 = getInjectable({
|
||||
id: "some-dock-tab-2",
|
||||
|
||||
instantiate: () => ({
|
||||
id: "some-dock-tab-2",
|
||||
TitleComponent: () => <div data-dock-tab-title-test="some-title-2">Some title 2</div>,
|
||||
|
||||
ContentComponent: () => (
|
||||
<div data-dock-tab-content-test="some-content-2">Some content 2</div>
|
||||
),
|
||||
}),
|
||||
|
||||
injectionToken: dockTabInjectionToken,
|
||||
});
|
||||
|
||||
runInAction(() => {
|
||||
di.register(dockTabInjectable);
|
||||
di.register(dockTabInjectable1, dockTabInjectable2);
|
||||
});
|
||||
});
|
||||
|
||||
@ -52,12 +71,35 @@ describe("DockHost, given rendered", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("renders the title of dock tab", () => {
|
||||
discover.getSingleElement("some-dock-tab-title");
|
||||
it("renders the titles of all the dock tabs in order", () => {
|
||||
expect(discover.queryAllElements("dock-tab-title").attributeValues).toEqual([
|
||||
"some-title-1",
|
||||
"some-title-2",
|
||||
]);
|
||||
});
|
||||
|
||||
it("renders the content of the dock tab", () => {
|
||||
discover.getSingleElement("some-dock-tab-content");
|
||||
it("renders only the content of the first dock tab", () => {
|
||||
expect(discover.queryAllElements("dock-tab-content").attributeValues).toEqual([
|
||||
"some-content-1",
|
||||
]);
|
||||
});
|
||||
|
||||
describe("when the second dock tab is clicked", () => {
|
||||
beforeEach(() => {
|
||||
act(() => {
|
||||
discover.getSingleElement("dock-tab", "some-dock-tab-2").click();
|
||||
});
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
expect(rendered.baseElement).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("renders only the content of the second dock tab", () => {
|
||||
expect(discover.queryAllElements("dock-tab-content").attributeValues).toEqual([
|
||||
"some-content-2",
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -0,0 +1,19 @@
|
||||
import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable";
|
||||
import { action } from "mobx";
|
||||
import activeDockTabIdInjectable from "./active-dock-tab-id.injectable";
|
||||
|
||||
const activateDockTabInjectable = getInjectable({
|
||||
id: "activate-dock-tab",
|
||||
|
||||
instantiate: (di, tabId) => {
|
||||
const activeDockTabId = di.inject(activeDockTabIdInjectable);
|
||||
|
||||
return action(() => activeDockTabId.set(tabId));
|
||||
},
|
||||
|
||||
lifecycle: lifecycleEnum.keyedSingleton({
|
||||
getInstanceKey: (di, tabId: string) => tabId,
|
||||
}),
|
||||
});
|
||||
|
||||
export default activateDockTabInjectable;
|
||||
@ -0,0 +1,9 @@
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { observable } from "mobx";
|
||||
|
||||
const activeDockTabIdInjectable = getInjectable({
|
||||
id: "active-dock-tab-id",
|
||||
instantiate: () => observable.box<string | null>(),
|
||||
});
|
||||
|
||||
export default activeDockTabIdInjectable;
|
||||
@ -1,23 +1,33 @@
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { computed } from "mobx";
|
||||
import dockTabsInjectable from "./dock-tabs.injectable";
|
||||
import activeDockTabIdInjectable from "./active-dock-tab-id.injectable";
|
||||
import { pipeline } from "@ogre-tools/fp";
|
||||
import { defaults, find, first } from "lodash/fp";
|
||||
import type { DockTab } from "../dock-tab";
|
||||
import dockTabTypesInjectable from "./dock-tabs-types.injectable";
|
||||
|
||||
const nullTab: DockTab = {
|
||||
id: "no-active-dock-tab",
|
||||
TitleComponent: () => null,
|
||||
ContentComponent: () => null,
|
||||
};
|
||||
|
||||
const activeDockTabInjectable = getInjectable({
|
||||
id: "active-dock-tab",
|
||||
|
||||
instantiate: (di) => {
|
||||
const dockTabs = di.inject(dockTabsInjectable);
|
||||
const dockTabTypes = di.inject(dockTabTypesInjectable);
|
||||
const activeDockTabId = di.inject(activeDockTabIdInjectable);
|
||||
|
||||
return computed(() => {
|
||||
const [
|
||||
activeDockTab = {
|
||||
id: "no-active-dock-tab",
|
||||
TitleComponent: () => null,
|
||||
ContentComponent: () => null,
|
||||
},
|
||||
] = dockTabs.get();
|
||||
const tabs = dockTabTypes.get();
|
||||
|
||||
return activeDockTab;
|
||||
return pipeline(
|
||||
tabs,
|
||||
find((tab) => tab.id === activeDockTabId.get()),
|
||||
defaults(first(tabs)),
|
||||
defaults(nullTab),
|
||||
);
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
@ -4,7 +4,7 @@ import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import React from "react";
|
||||
import { Tabs } from "./tabs";
|
||||
import { Div, Map } from "@k8slens/ui-components";
|
||||
import dockTabsInjectable from "./dock-tabs.injectable";
|
||||
import dockTabsInjectable, { ActivatableDockTab } from "./dock-tabs.injectable";
|
||||
import type { DockTab } from "../dock-tab";
|
||||
import activeDockTabInjectable from "./active-dock-tab.injectable";
|
||||
|
||||
@ -15,8 +15,8 @@ const NonInjectedDockHost = observer(({ dockTabs, activeDockTab }: Dependencies)
|
||||
<Div>
|
||||
<Tabs>
|
||||
<Map items={dockTabs.get()}>
|
||||
{({ TitleComponent }) => (
|
||||
<Tabs.Tab>
|
||||
{({ id, TitleComponent, activate }) => (
|
||||
<Tabs.Tab data-dock-tab-test={id} onClick={activate}>
|
||||
<TitleComponent />
|
||||
</Tabs.Tab>
|
||||
)}
|
||||
@ -31,7 +31,7 @@ const NonInjectedDockHost = observer(({ dockTabs, activeDockTab }: Dependencies)
|
||||
});
|
||||
|
||||
interface Dependencies {
|
||||
dockTabs: IComputedValue<DockTab[]>;
|
||||
dockTabs: IComputedValue<ActivatableDockTab[]>;
|
||||
activeDockTab: IComputedValue<DockTab>;
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,15 @@
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { computedInjectManyInjectable } from "@ogre-tools/injectable-extension-for-mobx";
|
||||
import { dockTabInjectionToken } from "../dock-tab";
|
||||
|
||||
const dockTabTypesInjectable = getInjectable({
|
||||
id: "dock-tab-types",
|
||||
|
||||
instantiate: (di) => {
|
||||
const computedInjectMany = di.inject(computedInjectManyInjectable);
|
||||
|
||||
return computedInjectMany(dockTabInjectionToken);
|
||||
},
|
||||
});
|
||||
|
||||
export default dockTabTypesInjectable;
|
||||
@ -1,14 +1,27 @@
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { computedInjectManyInjectable } from "@ogre-tools/injectable-extension-for-mobx";
|
||||
import { dockTabInjectionToken } from "../dock-tab";
|
||||
import { computed } from "mobx";
|
||||
import type { DockTab } from "../dock-tab";
|
||||
import activateDockTabInjectable from "./activate-dock-tab.injectable";
|
||||
import dockTabTypesInjectable from "./dock-tabs-types.injectable";
|
||||
|
||||
type Activatable = { activate: () => void };
|
||||
|
||||
export type ActivatableDockTab = DockTab & Activatable;
|
||||
|
||||
const dockTabsInjectable = getInjectable({
|
||||
id: "dock-tabs",
|
||||
|
||||
instantiate: (di) => {
|
||||
const computedInjectMany = di.inject(computedInjectManyInjectable);
|
||||
const dockTabTypes = di.inject(dockTabTypesInjectable);
|
||||
const activateFor = di.injectFactory(activateDockTabInjectable);
|
||||
|
||||
return computedInjectMany(dockTabInjectionToken);
|
||||
return computed(() =>
|
||||
dockTabTypes.get().map((tab) => ({
|
||||
...tab,
|
||||
|
||||
activate: activateFor(tab.id),
|
||||
})),
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { Div } from "@k8slens/ui-components";
|
||||
import React from "react";
|
||||
import type { DivProps } from "@k8slens/ui-components";
|
||||
|
||||
export interface TabsProps {
|
||||
children: React.ReactNode;
|
||||
@ -9,12 +10,10 @@ export const Tabs = ({ children }: TabsProps) => (
|
||||
<Div _flexParent={{ centeredVertically: true }}>{children}</Div>
|
||||
);
|
||||
|
||||
export interface TabProps {
|
||||
export type TabProps = {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
} & DivProps;
|
||||
|
||||
const Tab = ({ children }: TabProps) => (
|
||||
<Div>{children}</Div>
|
||||
);
|
||||
const Tab = ({ ...props }: TabProps) => <Div {...props} />;
|
||||
|
||||
Tabs.Tab = Tab;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user