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
|
<div
|
||||||
class="flex align-center"
|
class="flex align-center"
|
||||||
>
|
>
|
||||||
<div>
|
<div
|
||||||
|
data-dock-tab-test="some-dock-tab-1"
|
||||||
|
>
|
||||||
<div
|
<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>
|
</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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import { renderFor } from "@k8slens/test-utils";
|
|||||||
import { DockHost } from "./dock/dock-host";
|
import { DockHost } from "./dock/dock-host";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import type { RenderResult } from "@testing-library/react";
|
import type { RenderResult } from "@testing-library/react";
|
||||||
|
import { act } from "@testing-library/react";
|
||||||
import { dockTabInjectionToken } from "./dock-tab";
|
import { dockTabInjectionToken } from "./dock-tab";
|
||||||
import { Discover, discoverFor } from "@k8slens/react-testing-library-discovery";
|
import { Discover, discoverFor } from "@k8slens/react-testing-library-discovery";
|
||||||
import { registerFeature } from "@k8slens/feature-core";
|
import { registerFeature } from "@k8slens/feature-core";
|
||||||
@ -31,20 +32,38 @@ describe("DockHost, given rendered", () => {
|
|||||||
|
|
||||||
describe("given implementations of dock tabs emerge", () => {
|
describe("given implementations of dock tabs emerge", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
const dockTabInjectable = getInjectable({
|
const dockTabInjectable1 = getInjectable({
|
||||||
id: "some-dock-tab",
|
id: "some-dock-tab-1",
|
||||||
|
|
||||||
instantiate: () => ({
|
instantiate: () => ({
|
||||||
id: "some-dock-tab",
|
id: "some-dock-tab-1",
|
||||||
TitleComponent: () => <div data-some-dock-tab-title-test>Some title</div>,
|
TitleComponent: () => <div data-dock-tab-title-test="some-title-1">Some title 1</div>,
|
||||||
ContentComponent: () => <div data-some-dock-tab-content-test>Some content</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,
|
injectionToken: dockTabInjectionToken,
|
||||||
});
|
});
|
||||||
|
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
di.register(dockTabInjectable);
|
di.register(dockTabInjectable1, dockTabInjectable2);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -52,12 +71,35 @@ describe("DockHost, given rendered", () => {
|
|||||||
expect(rendered.baseElement).toMatchSnapshot();
|
expect(rendered.baseElement).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("renders the title of dock tab", () => {
|
it("renders the titles of all the dock tabs in order", () => {
|
||||||
discover.getSingleElement("some-dock-tab-title");
|
expect(discover.queryAllElements("dock-tab-title").attributeValues).toEqual([
|
||||||
|
"some-title-1",
|
||||||
|
"some-title-2",
|
||||||
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("renders the content of the dock tab", () => {
|
it("renders only the content of the first dock tab", () => {
|
||||||
discover.getSingleElement("some-dock-tab-content");
|
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 { getInjectable } from "@ogre-tools/injectable";
|
||||||
import { computed } from "mobx";
|
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({
|
const activeDockTabInjectable = getInjectable({
|
||||||
id: "active-dock-tab",
|
id: "active-dock-tab",
|
||||||
|
|
||||||
instantiate: (di) => {
|
instantiate: (di) => {
|
||||||
const dockTabs = di.inject(dockTabsInjectable);
|
const dockTabTypes = di.inject(dockTabTypesInjectable);
|
||||||
|
const activeDockTabId = di.inject(activeDockTabIdInjectable);
|
||||||
|
|
||||||
return computed(() => {
|
return computed(() => {
|
||||||
const [
|
const tabs = dockTabTypes.get();
|
||||||
activeDockTab = {
|
|
||||||
id: "no-active-dock-tab",
|
|
||||||
TitleComponent: () => null,
|
|
||||||
ContentComponent: () => null,
|
|
||||||
},
|
|
||||||
] = dockTabs.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 React from "react";
|
||||||
import { Tabs } from "./tabs";
|
import { Tabs } from "./tabs";
|
||||||
import { Div, Map } from "@k8slens/ui-components";
|
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 type { DockTab } from "../dock-tab";
|
||||||
import activeDockTabInjectable from "./active-dock-tab.injectable";
|
import activeDockTabInjectable from "./active-dock-tab.injectable";
|
||||||
|
|
||||||
@ -15,8 +15,8 @@ const NonInjectedDockHost = observer(({ dockTabs, activeDockTab }: Dependencies)
|
|||||||
<Div>
|
<Div>
|
||||||
<Tabs>
|
<Tabs>
|
||||||
<Map items={dockTabs.get()}>
|
<Map items={dockTabs.get()}>
|
||||||
{({ TitleComponent }) => (
|
{({ id, TitleComponent, activate }) => (
|
||||||
<Tabs.Tab>
|
<Tabs.Tab data-dock-tab-test={id} onClick={activate}>
|
||||||
<TitleComponent />
|
<TitleComponent />
|
||||||
</Tabs.Tab>
|
</Tabs.Tab>
|
||||||
)}
|
)}
|
||||||
@ -31,7 +31,7 @@ const NonInjectedDockHost = observer(({ dockTabs, activeDockTab }: Dependencies)
|
|||||||
});
|
});
|
||||||
|
|
||||||
interface Dependencies {
|
interface Dependencies {
|
||||||
dockTabs: IComputedValue<DockTab[]>;
|
dockTabs: IComputedValue<ActivatableDockTab[]>;
|
||||||
activeDockTab: IComputedValue<DockTab>;
|
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 { getInjectable } from "@ogre-tools/injectable";
|
||||||
import { computedInjectManyInjectable } from "@ogre-tools/injectable-extension-for-mobx";
|
import { computed } from "mobx";
|
||||||
import { dockTabInjectionToken } from "../dock-tab";
|
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({
|
const dockTabsInjectable = getInjectable({
|
||||||
id: "dock-tabs",
|
id: "dock-tabs",
|
||||||
|
|
||||||
instantiate: (di) => {
|
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 { Div } from "@k8slens/ui-components";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import type { DivProps } from "@k8slens/ui-components";
|
||||||
|
|
||||||
export interface TabsProps {
|
export interface TabsProps {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
@ -9,12 +10,10 @@ export const Tabs = ({ children }: TabsProps) => (
|
|||||||
<Div _flexParent={{ centeredVertically: true }}>{children}</Div>
|
<Div _flexParent={{ centeredVertically: true }}>{children}</Div>
|
||||||
);
|
);
|
||||||
|
|
||||||
export interface TabProps {
|
export type TabProps = {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}
|
} & DivProps;
|
||||||
|
|
||||||
const Tab = ({ children }: TabProps) => (
|
const Tab = ({ ...props }: TabProps) => <Div {...props} />;
|
||||||
<Div>{children}</Div>
|
|
||||||
);
|
|
||||||
|
|
||||||
Tabs.Tab = Tab;
|
Tabs.Tab = Tab;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user