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,26 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
|
||||
.Dialog {
|
||||
position: fixed;
|
||||
overflow: auto;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: $unit * 5;
|
||||
z-index: $zIndex-dialog;
|
||||
overscroll-behavior: none; // prevent swiping with touch-pad on MacOSX
|
||||
overflow: auto;
|
||||
|
||||
&.modal {
|
||||
background: transparentize(#222, .5);
|
||||
}
|
||||
|
||||
h5 {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import "./dialog.scss";
|
||||
|
||||
import React from "react";
|
||||
import { createPortal } from "react-dom";
|
||||
import { disposeOnUnmount, observer } from "mobx-react";
|
||||
import { reaction } from "mobx";
|
||||
import { Animate } from "../animate";
|
||||
import { cssNames, noop, stopPropagation } from "../../utils";
|
||||
import type { ObservableHistory } from "mobx-observable-history";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import observableHistoryInjectable from "../../navigation/observable-history.injectable";
|
||||
import requestAnimationFrameInjectable from "../animate/request-animation-frame.injectable";
|
||||
|
||||
// todo: refactor + handle animation-end in props.onClose()?
|
||||
|
||||
export interface DialogProps {
|
||||
className?: string;
|
||||
isOpen?: boolean;
|
||||
open?: () => void;
|
||||
close?: () => void;
|
||||
onOpen?: () => void;
|
||||
onClose?: () => void;
|
||||
modal?: boolean;
|
||||
pinned?: boolean;
|
||||
animated?: boolean;
|
||||
"data-testid"?: string;
|
||||
children?: React.ReactNode | React.ReactNode[];
|
||||
}
|
||||
|
||||
interface DialogState {
|
||||
isOpen: boolean;
|
||||
}
|
||||
|
||||
interface Dependencies {
|
||||
navigation: ObservableHistory<unknown>;
|
||||
requestAnimationFrame: (callback: () => void) => void;
|
||||
}
|
||||
|
||||
@observer
|
||||
class NonInjectedDialog extends React.PureComponent<DialogProps & Dependencies & typeof NonInjectedDialog.defaultProps, DialogState> {
|
||||
private readonly contentElem = React.createRef<HTMLDivElement>();
|
||||
private readonly ref = React.createRef<HTMLDivElement>();
|
||||
|
||||
static defaultProps = {
|
||||
isOpen: false,
|
||||
open: noop,
|
||||
close: noop,
|
||||
onOpen: noop,
|
||||
onClose: noop,
|
||||
modal: true,
|
||||
animated: true,
|
||||
pinned: false,
|
||||
};
|
||||
|
||||
public state: DialogState = {
|
||||
isOpen: this.props.isOpen ?? false,
|
||||
};
|
||||
|
||||
get elem() {
|
||||
return this.ref.current;
|
||||
}
|
||||
|
||||
get isOpen() {
|
||||
return this.state.isOpen;
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (this.isOpen) {
|
||||
this.onOpen();
|
||||
}
|
||||
|
||||
disposeOnUnmount(this, [
|
||||
reaction(() => this.props.navigation.toString(), () => this.close()),
|
||||
]);
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps: DialogProps) {
|
||||
const { isOpen } = this.props;
|
||||
|
||||
if (isOpen !== prevProps.isOpen) {
|
||||
this.toggle(isOpen ?? false);
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.isOpen) this.onClose();
|
||||
}
|
||||
|
||||
toggle(isOpen: boolean) {
|
||||
if (isOpen) this.open();
|
||||
else this.close();
|
||||
}
|
||||
|
||||
open() {
|
||||
this.props.requestAnimationFrame(this.onOpen); // wait for render(), bind close-event to this.elem
|
||||
this.setState({ isOpen: true });
|
||||
this.props.open?.();
|
||||
}
|
||||
|
||||
close() {
|
||||
this.onClose(); // must be first to get access to dialog's content from outside
|
||||
this.setState({ isOpen: false });
|
||||
this.props.close?.();
|
||||
}
|
||||
|
||||
onOpen = () => {
|
||||
this.props.onOpen?.();
|
||||
|
||||
if (!this.props.pinned) {
|
||||
if (this.elem) this.elem.addEventListener("click", this.onClickOutside);
|
||||
// Using document.body target to handle keydown event before Drawer does
|
||||
document.body.addEventListener("keydown", this.onEscapeKey);
|
||||
}
|
||||
};
|
||||
|
||||
onClose = () => {
|
||||
this.props.onClose?.();
|
||||
|
||||
if (!this.props.pinned) {
|
||||
if (this.elem) this.elem.removeEventListener("click", this.onClickOutside);
|
||||
document.body.removeEventListener("keydown", this.onEscapeKey);
|
||||
}
|
||||
};
|
||||
|
||||
onEscapeKey = (evt: KeyboardEvent) => {
|
||||
const escapeKey = evt.code === "Escape";
|
||||
|
||||
if (escapeKey) {
|
||||
this.close();
|
||||
evt.stopPropagation();
|
||||
}
|
||||
};
|
||||
|
||||
onClickOutside = (evt: MouseEvent) => {
|
||||
const target = evt.target as HTMLElement;
|
||||
|
||||
if (!this.contentElem.current?.contains(target)) {
|
||||
this.close();
|
||||
evt.stopPropagation();
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const { modal, animated, pinned, "data-testid": testId, className } = this.props;
|
||||
|
||||
let dialog = (
|
||||
<div
|
||||
className={cssNames("Dialog flex center", className, { modal, pinned })}
|
||||
onClick={stopPropagation}
|
||||
ref={this.ref}
|
||||
data-testid={testId}
|
||||
>
|
||||
<div
|
||||
className="box"
|
||||
ref={this.contentElem}
|
||||
>
|
||||
{this.props.children}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
if (animated) {
|
||||
dialog = (
|
||||
<Animate enter={this.isOpen} name="opacity-scale">
|
||||
{dialog}
|
||||
</Animate>
|
||||
);
|
||||
} else if (!this.isOpen) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return createPortal(dialog, document.body);
|
||||
}
|
||||
}
|
||||
|
||||
export const Dialog = withInjectables<Dependencies, DialogProps>((props) => <NonInjectedDialog {...props} />, {
|
||||
getProps: (di, props) => ({
|
||||
...props,
|
||||
navigation: di.inject(observableHistoryInjectable),
|
||||
requestAnimationFrame: di.inject(requestAnimationFrameInjectable),
|
||||
}),
|
||||
});
|
||||
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
export * from "./dialog";
|
||||
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
.LogsDialog {
|
||||
.Wizard {
|
||||
--wizard-width: 70vw;
|
||||
}
|
||||
|
||||
.WizardStep {
|
||||
.step-content {
|
||||
padding: var(--wizard-spacing);
|
||||
}
|
||||
|
||||
code {
|
||||
max-height: 50vh;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import "./logs-dialog.scss";
|
||||
|
||||
import React from "react";
|
||||
import type { DialogProps } from "../dialog";
|
||||
import { Dialog } from "../dialog";
|
||||
import { Wizard, WizardStep } from "../wizard";
|
||||
import type { ShowNotification } from "../notifications";
|
||||
import { Button } from "../button";
|
||||
import { Icon } from "../icon";
|
||||
import { clipboard } from "electron";
|
||||
import { kebabCase } from "lodash/fp";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import showSuccessNotificationInjectable from "../notifications/show-success-notification.injectable";
|
||||
|
||||
export interface LogsDialogProps extends DialogProps {
|
||||
title: string;
|
||||
logs: string;
|
||||
}
|
||||
|
||||
interface Dependencies {
|
||||
showSuccessNotification: ShowNotification;
|
||||
}
|
||||
|
||||
const NonInjectedLogsDialog = (props: LogsDialogProps & Dependencies) => {
|
||||
const {
|
||||
title,
|
||||
logs,
|
||||
showSuccessNotification,
|
||||
...dialogProps
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
{...dialogProps}
|
||||
className="LogsDialog"
|
||||
data-testid={`logs-dialog-for-${kebabCase(title)}`}
|
||||
>
|
||||
<Wizard
|
||||
header={<h5>{title}</h5>}
|
||||
done={dialogProps.close}
|
||||
>
|
||||
<WizardStep
|
||||
scrollable={false}
|
||||
customButtons={(
|
||||
<div className="buttons flex gaps align-center justify-space-between">
|
||||
<Button
|
||||
plain
|
||||
onClick={() => {
|
||||
clipboard.writeText(logs);
|
||||
showSuccessNotification(`Logs copied to clipboard.`);
|
||||
}}
|
||||
>
|
||||
<Icon material="assignment"/>
|
||||
{" Copy to clipboard"}
|
||||
</Button>
|
||||
<Button plain onClick={dialogProps.close}>
|
||||
Close
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
>
|
||||
<code className="block">
|
||||
{logs || "There are no logs available."}
|
||||
</code>
|
||||
</WizardStep>
|
||||
</Wizard>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
||||
export const LogsDialog = withInjectables<Dependencies, LogsDialogProps>(NonInjectedLogsDialog, {
|
||||
getProps: (di, props) => ({
|
||||
...props,
|
||||
showSuccessNotification: di.inject(showSuccessNotificationInjectable),
|
||||
}),
|
||||
});
|
||||
Reference in new issue
Block a user