mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Restructure to monorepo (#6907)
* wip: restructure to monorepo Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com> * refactor create-release-pr to a package Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com> * build fixes Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com> * github workflow fixes Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com> * fix typo Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com> * add webpack-env types to core Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com> * fix github workflows Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com> * refactor/fix integration tests Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com> * lint fix Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com> * yarn run dev Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com> * eslint settings for vscode Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com> * move templates to right package Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com> * open-lens build fixes Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com> * integration test fix Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com> * fix nx task dependencies Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com> * use bash shell for unit tests in test workflow Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com> * fix test:unit for windows Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com> * fix win-ca webpack error in open-lens Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com> * fix win-ca webpack error in open-lens Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com> * fix build:app on windows Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com> * remove ELECTRON_BUILDER_EXTRA_ARGS Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com> * sync src/ from master Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com> * remove Makefile from core Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com> Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>
This commit is contained in:
1 parent
0066ca4ea2
commit
2657df2293
3321 files changed
+28699
-11447
No files matched your search
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectionToken } from "@ogre-tools/injectable";
|
||||
import type { IComputedValue } from "mobx";
|
||||
import type React from "react";
|
||||
|
||||
export interface StatusBarItem {
|
||||
origin?: string;
|
||||
component: React.ComponentType<any>;
|
||||
position: "left" | "right";
|
||||
visible: IComputedValue<boolean>;
|
||||
}
|
||||
|
||||
export const statusBarItemInjectionToken = getInjectionToken<StatusBarItem>({
|
||||
id: "status-bar-item",
|
||||
});
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import type { Injectable } from "@ogre-tools/injectable";
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type { IComputedValue } from "mobx";
|
||||
import { computed } from "mobx";
|
||||
import { extensionRegistratorInjectionToken } from "../../../extensions/extension-loader/extension-registrator-injection-token";
|
||||
import type { LensRendererExtension } from "../../../extensions/lens-renderer-extension";
|
||||
import type { StatusBarItem } from "./status-bar-item-injection-token";
|
||||
import { statusBarItemInjectionToken } from "./status-bar-item-injection-token";
|
||||
import type { StatusBarRegistration } from "./status-bar-registration";
|
||||
import React from "react";
|
||||
import getRandomIdInjectable from "../../../common/utils/get-random-id.injectable";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
import type { Logger } from "../../../common/logger";
|
||||
|
||||
const statusBarItemRegistratorInjectable = getInjectable({
|
||||
id: "status-bar-item-registrator",
|
||||
|
||||
instantiate: (di) => (extension) => {
|
||||
const rendererExtension = extension as LensRendererExtension;
|
||||
const getRandomId = di.inject(getRandomIdInjectable);
|
||||
const logger = di.inject(loggerInjectable);
|
||||
|
||||
return rendererExtension.statusBarItems.flatMap(
|
||||
toItemInjectableFor(rendererExtension, getRandomId, logger),
|
||||
);
|
||||
},
|
||||
|
||||
injectionToken: extensionRegistratorInjectionToken,
|
||||
});
|
||||
|
||||
export default statusBarItemRegistratorInjectable;
|
||||
|
||||
const toItemInjectableFor = (extension: LensRendererExtension, getRandomId: () => string, logger: Logger) => {
|
||||
return (registration: StatusBarRegistration): Injectable<StatusBarItem, StatusBarItem, void>[] => {
|
||||
const id = `${getRandomId()}-status-bar-item-for-extension-${extension.sanitizedExtensionId}`;
|
||||
let component: React.ComponentType;
|
||||
let position: "left" | "right";
|
||||
const visible: IComputedValue<boolean> | undefined = registration?.visible;
|
||||
|
||||
if (registration?.item) {
|
||||
const { item } = registration;
|
||||
|
||||
position = "right";
|
||||
component =
|
||||
() => (
|
||||
<>
|
||||
{
|
||||
typeof item === "function"
|
||||
? item()
|
||||
: item
|
||||
}
|
||||
</>
|
||||
);
|
||||
} else if (registration?.components) {
|
||||
const { position: pos = "right", Item } = registration.components;
|
||||
|
||||
if (pos !== "left" && pos !== "right") {
|
||||
throw new TypeError("StatusBarRegistration.components.position must be either 'right' or 'left'");
|
||||
}
|
||||
|
||||
position = pos;
|
||||
component = Item;
|
||||
} else {
|
||||
logger.warn("StatusBarRegistration must have valid item or components field");
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
return [getInjectable({
|
||||
id,
|
||||
|
||||
instantiate: () => ({
|
||||
origin: extension.sanitizedExtensionId,
|
||||
component,
|
||||
position,
|
||||
visible: visible ?? computed(() => true),
|
||||
}),
|
||||
|
||||
injectionToken: statusBarItemInjectionToken,
|
||||
})];
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type { IComputedValue } from "mobx";
|
||||
import { computed } from "mobx";
|
||||
import type { StatusBarItemProps } from "./status-bar-registration";
|
||||
import type { StatusBarItem } from "./status-bar-item-injection-token";
|
||||
import { statusBarItemInjectionToken } from "./status-bar-item-injection-token";
|
||||
import { computedInjectManyInjectable } from "@ogre-tools/injectable-extension-for-mobx";
|
||||
|
||||
interface StatusItem {
|
||||
origin?: string;
|
||||
component: React.ComponentType<StatusBarItemProps>;
|
||||
}
|
||||
|
||||
export interface StatusBarItems {
|
||||
right: StatusItem[];
|
||||
left: StatusItem[];
|
||||
}
|
||||
|
||||
interface Dependencies {
|
||||
registrations: IComputedValue<StatusBarItem[]>;
|
||||
}
|
||||
|
||||
function getStatusBarItems({ registrations }: Dependencies): IComputedValue<StatusBarItems> {
|
||||
return computed(() => {
|
||||
const res: StatusBarItems = {
|
||||
left: [],
|
||||
right: [],
|
||||
};
|
||||
|
||||
for (const registration of registrations.get()) {
|
||||
const { position = "right", component, visible, origin } = registration;
|
||||
|
||||
if (!visible.get()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
res[position].push({
|
||||
origin,
|
||||
component,
|
||||
});
|
||||
}
|
||||
|
||||
// This is done so that the first ones registered are closest to the corner
|
||||
res.right.reverse();
|
||||
|
||||
return res;
|
||||
});
|
||||
}
|
||||
|
||||
const statusBarItemsInjectable = getInjectable({
|
||||
id: "status-bar-items",
|
||||
|
||||
instantiate: (di) => {
|
||||
const computedInjectMany = di.inject(
|
||||
computedInjectManyInjectable,
|
||||
);
|
||||
|
||||
return getStatusBarItems({
|
||||
registrations: computedInjectMany(statusBarItemInjectionToken),
|
||||
});
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
export default statusBarItemsInjectable;
|
||||
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import type { IComputedValue } from "mobx";
|
||||
|
||||
/**
|
||||
* The props for StatusBar item component
|
||||
*/
|
||||
export interface StatusBarItemProps {}
|
||||
|
||||
/**
|
||||
* The type defining the registration of a status bar item
|
||||
*/
|
||||
export interface StatusBarComponents {
|
||||
/**
|
||||
* The component for this registrations
|
||||
*/
|
||||
Item: React.ComponentType<StatusBarItemProps>;
|
||||
|
||||
/**
|
||||
* The side of the bottom bar to place this component.
|
||||
*
|
||||
* @default "right"
|
||||
*/
|
||||
position?: "left" | "right";
|
||||
}
|
||||
|
||||
/**
|
||||
* The type for registering status bar items from the LensRendererExtension
|
||||
*/
|
||||
export interface StatusBarRegistration {
|
||||
/**
|
||||
* @deprecated use {@link StatusBarRegistration.components} instead
|
||||
*/
|
||||
item?: React.ReactNode | (() => React.ReactNode);
|
||||
|
||||
/**
|
||||
* The newer API, allows for registering a component instead of a ReactNode
|
||||
*/
|
||||
components?: StatusBarComponents;
|
||||
|
||||
/**
|
||||
* If specified, controls item visibility
|
||||
*/
|
||||
visible?: IComputedValue<boolean>;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
.StatusBar {
|
||||
--status-bar-height: 21px;
|
||||
color: white;
|
||||
|
||||
grid-area: status-bar;
|
||||
background-color: var(--blue);
|
||||
height: var(--status-bar-height);
|
||||
font-size: var(--font-size-small);
|
||||
|
||||
display: inline-grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
|
||||
.leftSide {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-inline-start: calc(var(--padding) / 2);
|
||||
}
|
||||
|
||||
.rightSide {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
padding-inline-end: calc(var(--padding) / 2);
|
||||
}
|
||||
|
||||
.item {
|
||||
height: 100%;
|
||||
padding-inline: var(--padding);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
background-color: #ffffff33;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import "@testing-library/jest-dom/extend-expect";
|
||||
import type { IObservableArray } from "mobx";
|
||||
import { computed, observable } from "mobx";
|
||||
import type { StatusBarItems } from "./status-bar-items.injectable";
|
||||
import statusBarItemsInjectable from "./status-bar-items.injectable";
|
||||
import directoryForUserDataInjectable from "../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
|
||||
import type { ApplicationBuilder } from "../test-utils/get-application-builder";
|
||||
import { getApplicationBuilder } from "../test-utils/get-application-builder";
|
||||
import getRandomIdInjectable from "../../../common/utils/get-random-id.injectable";
|
||||
|
||||
describe("<StatusBar />", () => {
|
||||
let statusBarItems: IObservableArray<any>;
|
||||
let builder: ApplicationBuilder;
|
||||
|
||||
beforeEach(async () => {
|
||||
statusBarItems = observable.array([]);
|
||||
|
||||
builder = getApplicationBuilder();
|
||||
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
windowDi.unoverride(getRandomIdInjectable);
|
||||
windowDi.permitSideEffects(getRandomIdInjectable);
|
||||
windowDi.override(directoryForUserDataInjectable, () => "some-directory-for-user-data");
|
||||
});
|
||||
|
||||
builder.extensions.enable({
|
||||
id: "some-id",
|
||||
name: "some-name",
|
||||
|
||||
rendererOptions: {
|
||||
statusBarItems,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("renders w/o errors", async () => {
|
||||
const { container } = await builder.render();
|
||||
|
||||
expect(container).toBeInstanceOf(HTMLElement);
|
||||
});
|
||||
|
||||
it.each([
|
||||
undefined,
|
||||
"hello",
|
||||
6,
|
||||
null,
|
||||
[],
|
||||
[{}],
|
||||
{},
|
||||
])("renders w/o errors when registrations are not type compliant (%p)", async val => {
|
||||
statusBarItems.replace([val]);
|
||||
|
||||
await expect(builder.render()).resolves.toBeTruthy();
|
||||
});
|
||||
|
||||
it("renders items [{item: React.ReactNode}] (4.0.0-rc.1)", async () => {
|
||||
const testId = "testId";
|
||||
const text = "heee";
|
||||
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
windowDi.override(statusBarItemsInjectable, () => computed(() => ({
|
||||
right: [ { origin: testId, component: () => <span data-testid={testId} >{text}</span> }],
|
||||
left: [],
|
||||
}) as StatusBarItems));
|
||||
});
|
||||
|
||||
const { getByTestId } = await builder.render();
|
||||
|
||||
expect(getByTestId(testId)).toHaveTextContent(text);
|
||||
});
|
||||
|
||||
it("renders items [{item: () => React.ReactNode}] (4.0.0-rc.1+)", async () => {
|
||||
const testId = "testId";
|
||||
const text = "heee";
|
||||
|
||||
statusBarItems.replace([{
|
||||
item: () => <span data-testid={testId} >{text}</span>,
|
||||
}]);
|
||||
|
||||
const { getByTestId } = await builder.render();
|
||||
|
||||
expect(getByTestId(testId)).toHaveTextContent(text);
|
||||
});
|
||||
|
||||
|
||||
it("sort positioned items properly", async () => {
|
||||
statusBarItems.replace([
|
||||
{
|
||||
components: {
|
||||
Item: () => <div data-testid="sortedElem">right1</div>,
|
||||
},
|
||||
},
|
||||
{
|
||||
components: {
|
||||
Item: () => <div data-testid="sortedElem">right2</div>,
|
||||
position: "right",
|
||||
},
|
||||
},
|
||||
{
|
||||
components: {
|
||||
Item: () => <div data-testid="sortedElem">left1</div>,
|
||||
position: "left",
|
||||
},
|
||||
},
|
||||
{
|
||||
components: {
|
||||
Item: () => <div data-testid="sortedElem">left2</div>,
|
||||
position: "left",
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
const { getAllByTestId } = await builder.render();
|
||||
const elems = getAllByTestId("sortedElem");
|
||||
const positions = elems.map(elem => elem.textContent);
|
||||
|
||||
expect(positions).toEqual(["left1", "left2", "right2", "right1"]);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import styles from "./status-bar.module.scss";
|
||||
|
||||
import React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import type { StatusBarItems } from "./status-bar-items.injectable";
|
||||
import statusBarItemsInjectable from "./status-bar-items.injectable";
|
||||
import type { IComputedValue } from "mobx";
|
||||
|
||||
export interface StatusBarProps {}
|
||||
|
||||
interface Dependencies {
|
||||
items: IComputedValue<StatusBarItems>;
|
||||
}
|
||||
|
||||
const NonInjectedStatusBar = observer(({ items }: Dependencies & StatusBarProps) => {
|
||||
const { left, right } = items.get();
|
||||
|
||||
return (
|
||||
<div className={styles.StatusBar} data-testid="status-bar">
|
||||
<div className={styles.leftSide} data-testid="status-bar-left">
|
||||
{left.map((Item, index) => (
|
||||
<div
|
||||
className={styles.item}
|
||||
key={index}
|
||||
data-origin={Item.origin}>
|
||||
{<Item.component/>}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className={styles.rightSide} data-testid="status-bar-right">
|
||||
{right.map((Item, index) => (
|
||||
<div
|
||||
className={styles.item}
|
||||
key={index}
|
||||
data-origin={Item.origin}>
|
||||
{<Item.component/>}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
});
|
||||
|
||||
export const StatusBar = withInjectables<Dependencies, StatusBarProps>(NonInjectedStatusBar, {
|
||||
getProps: (di, props) => ({
|
||||
items: di.inject(statusBarItemsInjectable),
|
||||
...props,
|
||||
}),
|
||||
});
|
||||
Reference in new issue
Block a user