mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Add OnClickDecorator for UI components
Signed-off-by: Juho Heikka <juho.heikka@gmail.com>
This commit is contained in:
parent
17ddee2bde
commit
396d08051f
@ -262,7 +262,7 @@ export class MetricsSettings extends React.Component<MetricsSettingsProps> {
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
<Button
|
<OpenLensButton
|
||||||
label={this.buttonLabel}
|
label={this.buttonLabel}
|
||||||
waiting={this.inProgress}
|
waiting={this.inProgress}
|
||||||
onClick={() => this.save()}
|
onClick={() => this.save()}
|
||||||
|
|||||||
@ -24,8 +24,8 @@ describe("add custom helm repository in preferences", () => {
|
|||||||
let showErrorNotificationMock: jest.Mock;
|
let showErrorNotificationMock: jest.Mock;
|
||||||
let rendered: RenderResult;
|
let rendered: RenderResult;
|
||||||
let execFileMock: AsyncFnMock<
|
let execFileMock: AsyncFnMock<
|
||||||
ReturnType<typeof execFileInjectable["instantiate"]>
|
ReturnType<typeof execFileInjectable["instantiate"]>
|
||||||
>;
|
>;
|
||||||
let getActiveHelmRepositoriesMock: AsyncFnMock<() => Promise<AsyncResult<HelmRepo[]>>>;
|
let getActiveHelmRepositoriesMock: AsyncFnMock<() => Promise<AsyncResult<HelmRepo[]>>>;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import type { IComputedValue } from "mobx";
|
|||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import installUpdateCountdownInjectable from "./install-update-countdown.injectable";
|
import installUpdateCountdownInjectable from "./install-update-countdown.injectable";
|
||||||
import { Dialog } from "../../components/dialog";
|
import { Dialog } from "../../components/dialog";
|
||||||
import { Button } from "../../components/button";
|
import { OpenLensButton } from "../../components/button";
|
||||||
import styles from "./force-update-modal.module.scss";
|
import styles from "./force-update-modal.module.scss";
|
||||||
|
|
||||||
interface Dependencies {
|
interface Dependencies {
|
||||||
@ -36,7 +36,7 @@ const NonInjectedForceUpdateModal = observer(
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={styles.footer}>
|
<div className={styles.footer}>
|
||||||
<Button
|
<OpenLensButton
|
||||||
primary
|
primary
|
||||||
data-testid="update-now-from-must-update-immediately-modal"
|
data-testid="update-now-from-must-update-immediately-modal"
|
||||||
onClick={restartAndInstallUpdate}
|
onClick={restartAndInstallUpdate}
|
||||||
@ -49,7 +49,7 @@ const NonInjectedForceUpdateModal = observer(
|
|||||||
data-testid="countdown-to-automatic-update"
|
data-testid="countdown-to-automatic-update"
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
</Button>
|
</OpenLensButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
|||||||
@ -17,7 +17,7 @@ import { appEventBus } from "../../../common/app-event-bus/event-bus";
|
|||||||
import { loadConfigFromString, splitConfig } from "../../../common/kube-helpers";
|
import { loadConfigFromString, splitConfig } from "../../../common/kube-helpers";
|
||||||
import { docsUrl } from "../../../common/vars";
|
import { docsUrl } from "../../../common/vars";
|
||||||
import { isDefined, iter } from "../../utils";
|
import { isDefined, iter } from "../../utils";
|
||||||
import { Button } from "../button";
|
import { OpenLensButton } from "../button";
|
||||||
import { Notifications } from "../notifications";
|
import { Notifications } from "../notifications";
|
||||||
import { SettingLayout } from "../layout/setting-layout";
|
import { SettingLayout } from "../layout/setting-layout";
|
||||||
import { MonacoEditor } from "../monaco-editor";
|
import { MonacoEditor } from "../monaco-editor";
|
||||||
@ -138,7 +138,7 @@ class NonInjectedAddCluster extends React.Component<Dependencies> {
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<div className="actions-panel">
|
<div className="actions-panel">
|
||||||
<Button
|
<OpenLensButton
|
||||||
primary
|
primary
|
||||||
disabled={this.kubeContexts.size === 0}
|
disabled={this.kubeContexts.size === 0}
|
||||||
label={this.kubeContexts.size === 1 ? "Add cluster" : "Add clusters"}
|
label={this.kubeContexts.size === 1 ? "Add cluster" : "Add clusters"}
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import { disposeOnUnmount, observer } from "mobx-react";
|
|||||||
import { DrawerTitle } from "../drawer";
|
import { DrawerTitle } from "../drawer";
|
||||||
import { Notifications } from "../notifications";
|
import { Notifications } from "../notifications";
|
||||||
import { Input } from "../input";
|
import { Input } from "../input";
|
||||||
import { Button } from "../button";
|
import { OpenLensButton } from "../button";
|
||||||
import { configMapStore } from "./legacy-store";
|
import { configMapStore } from "./legacy-store";
|
||||||
import type { KubeObjectDetailsProps } from "../kube-object-details";
|
import type { KubeObjectDetailsProps } from "../kube-object-details";
|
||||||
import { ConfigMap } from "../../../common/k8s-api/endpoints";
|
import { ConfigMap } from "../../../common/k8s-api/endpoints";
|
||||||
@ -104,7 +104,7 @@ export class ConfigMapDetails extends React.Component<ConfigMapDetailsProps> {
|
|||||||
</div>
|
</div>
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
<Button
|
<OpenLensButton
|
||||||
primary
|
primary
|
||||||
label="Save"
|
label="Save"
|
||||||
waiting={this.isSaving}
|
waiting={this.isSaving}
|
||||||
|
|||||||
@ -17,7 +17,7 @@ import type { IResourceQuotaValues } from "../../../common/k8s-api/endpoints";
|
|||||||
import { resourceQuotaApi } from "../../../common/k8s-api/endpoints";
|
import { resourceQuotaApi } from "../../../common/k8s-api/endpoints";
|
||||||
import { Select } from "../select";
|
import { Select } from "../select";
|
||||||
import { Icon } from "../icon";
|
import { Icon } from "../icon";
|
||||||
import { Button } from "../button";
|
import { OpenLensButton } from "../button";
|
||||||
import { Notifications } from "../notifications";
|
import { Notifications } from "../notifications";
|
||||||
import { NamespaceSelect } from "../+namespaces/namespace-select";
|
import { NamespaceSelect } from "../+namespaces/namespace-select";
|
||||||
import { SubTitle } from "../layout/sub-title";
|
import { SubTitle } from "../layout/sub-title";
|
||||||
@ -218,7 +218,7 @@ export class AddQuotaDialog extends React.Component<AddQuotaDialogProps> {
|
|||||||
onKeyDown={this.onInputQuota}
|
onKeyDown={this.onInputQuota}
|
||||||
className="box grow"
|
className="box grow"
|
||||||
/>
|
/>
|
||||||
<Button
|
<OpenLensButton
|
||||||
round
|
round
|
||||||
primary
|
primary
|
||||||
onClick={this.setQuota}
|
onClick={this.setQuota}
|
||||||
@ -227,7 +227,7 @@ export class AddQuotaDialog extends React.Component<AddQuotaDialogProps> {
|
|||||||
material={this.quotaSelectValue && this.quotas[this.quotaSelectValue] ? "edit" : "add"}
|
material={this.quotaSelectValue && this.quotas[this.quotaSelectValue] ? "edit" : "add"}
|
||||||
tooltip="Set quota"
|
tooltip="Set quota"
|
||||||
/>
|
/>
|
||||||
</Button>
|
</OpenLensButton>
|
||||||
</div>
|
</div>
|
||||||
<div className="quota-entries">
|
<div className="quota-entries">
|
||||||
{this.quotaEntries.map(([quota, value]) => (
|
{this.quotaEntries.map(([quota, value]) => (
|
||||||
|
|||||||
@ -4,9 +4,12 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { render } from "@testing-library/react";
|
|
||||||
import { SecretDetails } from "../secret-details";
|
import { SecretDetails } from "../secret-details";
|
||||||
import { Secret, SecretType } from "../../../../common/k8s-api/endpoints";
|
import { Secret, SecretType } from "../../../../common/k8s-api/endpoints";
|
||||||
|
import { getDiForUnitTesting } from "../../../getDiForUnitTesting";
|
||||||
|
import type { DiRender } from "../../test-utils/renderFor";
|
||||||
|
import { renderFor } from "../../test-utils/renderFor";
|
||||||
|
import type { DiContainer } from "@ogre-tools/injectable";
|
||||||
|
|
||||||
jest.mock("../../kube-object-meta/kube-object-meta", () => ({
|
jest.mock("../../kube-object-meta/kube-object-meta", () => ({
|
||||||
KubeObjectMeta: () => null,
|
KubeObjectMeta: () => null,
|
||||||
@ -14,6 +17,14 @@ jest.mock("../../kube-object-meta/kube-object-meta", () => ({
|
|||||||
|
|
||||||
|
|
||||||
describe("SecretDetails tests", () => {
|
describe("SecretDetails tests", () => {
|
||||||
|
let di: DiContainer;
|
||||||
|
let render: DiRender;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
di = getDiForUnitTesting({ doGeneralOverrides: true });
|
||||||
|
render = renderFor(di);
|
||||||
|
});
|
||||||
|
|
||||||
it("should show the visibility toggle when the secret value is ''", () => {
|
it("should show the visibility toggle when the secret value is ''", () => {
|
||||||
const secret = new Secret({
|
const secret = new Secret({
|
||||||
apiVersion: "v1",
|
apiVersion: "v1",
|
||||||
@ -30,6 +41,7 @@ describe("SecretDetails tests", () => {
|
|||||||
},
|
},
|
||||||
type: SecretType.Opaque,
|
type: SecretType.Opaque,
|
||||||
});
|
});
|
||||||
|
|
||||||
const result = render(<SecretDetails object={secret}/>);
|
const result = render(<SecretDetails object={secret}/>);
|
||||||
|
|
||||||
expect(result.getByTestId("foobar-secret-entry").querySelector(".Icon")).toBeDefined();
|
expect(result.getByTestId("foobar-secret-entry").querySelector(".Icon")).toBeDefined();
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import { autorun, observable, makeObservable } from "mobx";
|
|||||||
import { disposeOnUnmount, observer } from "mobx-react";
|
import { disposeOnUnmount, observer } from "mobx-react";
|
||||||
import { DrawerItem, DrawerTitle } from "../drawer";
|
import { DrawerItem, DrawerTitle } from "../drawer";
|
||||||
import { Input } from "../input";
|
import { Input } from "../input";
|
||||||
import { Button } from "../button";
|
import { OpenLensButton } from "../button";
|
||||||
import { Notifications } from "../notifications";
|
import { Notifications } from "../notifications";
|
||||||
import { base64, toggle } from "../../utils";
|
import { base64, toggle } from "../../utils";
|
||||||
import { Icon } from "../icon";
|
import { Icon } from "../icon";
|
||||||
@ -122,7 +122,7 @@ export class SecretDetails extends React.Component<SecretDetailsProps> {
|
|||||||
<>
|
<>
|
||||||
<DrawerTitle>Data</DrawerTitle>
|
<DrawerTitle>Data</DrawerTitle>
|
||||||
{secrets.map(this.renderSecret)}
|
{secrets.map(this.renderSecret)}
|
||||||
<Button
|
<OpenLensButton
|
||||||
primary
|
primary
|
||||||
label="Save"
|
label="Save"
|
||||||
waiting={this.isSaving}
|
waiting={this.isSaving}
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import {
|
|||||||
disposer,
|
disposer,
|
||||||
} from "../../../../common/utils";
|
} from "../../../../common/utils";
|
||||||
import { Notifications } from "../../notifications";
|
import { Notifications } from "../../notifications";
|
||||||
import { Button } from "../../button";
|
import { OpenLensButton } from "../../button";
|
||||||
import type { ExtensionLoader } from "../../../../extensions/extension-loader";
|
import type { ExtensionLoader } from "../../../../extensions/extension-loader";
|
||||||
import type { LensExtensionId } from "../../../../extensions/lens-extension";
|
import type { LensExtensionId } from "../../../../extensions/lens-extension";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
@ -110,7 +110,7 @@ export const attemptInstall =
|
|||||||
{` ${name}@${oldVersion} will be removed before installation.`}
|
{` ${name}@${oldVersion} will be removed before installation.`}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<OpenLensButton
|
||||||
autoFocus
|
autoFocus
|
||||||
label="Install"
|
label="Install"
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
import styles from "./install.module.scss";
|
import styles from "./install.module.scss";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { prevDefault } from "../../utils";
|
import { prevDefault } from "../../utils";
|
||||||
import { Button } from "../button";
|
import { OpenLensButton } from "../button";
|
||||||
import { Icon } from "../icon";
|
import { Icon } from "../icon";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import { Input, InputValidators } from "../input";
|
import { Input, InputValidators } from "../input";
|
||||||
@ -77,7 +77,7 @@ const NonInjectedInstall: React.FC<Dependencies & InstallProps> = ({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<Button
|
<OpenLensButton
|
||||||
className={styles.button}
|
className={styles.button}
|
||||||
primary
|
primary
|
||||||
label="Install"
|
label="Install"
|
||||||
|
|||||||
@ -12,7 +12,7 @@ import { Drawer, DrawerItem } from "../drawer";
|
|||||||
import { autoBind, stopPropagation } from "../../utils";
|
import { autoBind, stopPropagation } from "../../utils";
|
||||||
import { MarkdownViewer } from "../markdown-viewer";
|
import { MarkdownViewer } from "../markdown-viewer";
|
||||||
import { Spinner } from "../spinner";
|
import { Spinner } from "../spinner";
|
||||||
import { Button } from "../button";
|
import { OpenLensButton } from "../button";
|
||||||
import { Select } from "../select";
|
import { Select } from "../select";
|
||||||
import { Badge } from "../badge";
|
import { Badge } from "../badge";
|
||||||
import { Tooltip, withStyles } from "@material-ui/core";
|
import { Tooltip, withStyles } from "@material-ui/core";
|
||||||
@ -76,7 +76,7 @@ class NonInjectedHelmChartDetails extends Component<HelmChartDetailsProps & Depe
|
|||||||
<div className="intro-contents box grow">
|
<div className="intro-contents box grow">
|
||||||
<div className="description flex align-center justify-space-between" data-testid="selected-chart-description">
|
<div className="description flex align-center justify-space-between" data-testid="selected-chart-description">
|
||||||
{selectedChart.getDescription()}
|
{selectedChart.getDescription()}
|
||||||
<Button
|
<OpenLensButton
|
||||||
primary
|
primary
|
||||||
label="Install"
|
label="Install"
|
||||||
onClick={this.install}
|
onClick={this.install}
|
||||||
|
|||||||
@ -14,7 +14,7 @@ import { observer } from "mobx-react";
|
|||||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||||
import type { ConfigurationInput, MinimalResourceGroup, OnlyUserSuppliedValuesAreShownToggle, ReleaseDetailsModel } from "./release-details-model/release-details-model.injectable";
|
import type { ConfigurationInput, MinimalResourceGroup, OnlyUserSuppliedValuesAreShownToggle, ReleaseDetailsModel } from "./release-details-model/release-details-model.injectable";
|
||||||
import releaseDetailsModelInjectable from "./release-details-model/release-details-model.injectable";
|
import releaseDetailsModelInjectable from "./release-details-model/release-details-model.injectable";
|
||||||
import { Button } from "../../button";
|
import { OpenLensButton } from "../../button";
|
||||||
import { kebabCase } from "lodash/fp";
|
import { kebabCase } from "lodash/fp";
|
||||||
import { Badge } from "../../badge";
|
import { Badge } from "../../badge";
|
||||||
import { SubTitle } from "../../layout/sub-title";
|
import { SubTitle } from "../../layout/sub-title";
|
||||||
@ -64,7 +64,7 @@ const NonInjectedReleaseDetailsContent = observer(({ model }: Dependencies & Rel
|
|||||||
<div className="flex gaps align-center">
|
<div className="flex gaps align-center">
|
||||||
<span>{model.release.chart}</span>
|
<span>{model.release.chart}</span>
|
||||||
|
|
||||||
<Button
|
<OpenLensButton
|
||||||
primary
|
primary
|
||||||
label="Upgrade"
|
label="Upgrade"
|
||||||
className="box right upgrade"
|
className="box right upgrade"
|
||||||
@ -196,7 +196,7 @@ const ReleaseValues = observer(({ configuration, onlyUserSuppliedValuesAreShown
|
|||||||
onChange={configuration.onChange}
|
onChange={configuration.onChange}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Button
|
<OpenLensButton
|
||||||
primary
|
primary
|
||||||
label="Save"
|
label="Save"
|
||||||
waiting={configuration.isSaving.get()}
|
waiting={configuration.isSaving.get()}
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import type { Service, ServicePort } from "../../../common/k8s-api/endpoints";
|
|||||||
import { action, makeObservable, observable, reaction } from "mobx";
|
import { action, makeObservable, observable, reaction } from "mobx";
|
||||||
import { cssNames } from "../../utils";
|
import { cssNames } from "../../utils";
|
||||||
import { Notifications } from "../notifications";
|
import { Notifications } from "../notifications";
|
||||||
import { Button } from "../button";
|
import { OpenLensButton } from "../button";
|
||||||
import type { ForwardedPort, PortForwardStore } from "../../port-forward";
|
import type { ForwardedPort, PortForwardStore } from "../../port-forward";
|
||||||
import { predictProtocol } from "../../port-forward";
|
import { predictProtocol } from "../../port-forward";
|
||||||
import { Spinner } from "../spinner";
|
import { Spinner } from "../spinner";
|
||||||
@ -183,11 +183,11 @@ class NonInjectedServicePortComponent extends React.Component<ServicePortCompone
|
|||||||
<span title="Open in a browser" onClick={() => this.portForward()}>
|
<span title="Open in a browser" onClick={() => this.portForward()}>
|
||||||
{port.toString()}
|
{port.toString()}
|
||||||
</span>
|
</span>
|
||||||
<Button primary onClick={portForwardAction}>
|
<OpenLensButton primary onClick={portForwardAction}>
|
||||||
{" "}
|
{" "}
|
||||||
{this.isPortForwarded ? (this.isActive ? "Stop/Remove" : "Remove") : "Forward..."}
|
{this.isPortForwarded ? (this.isActive ? "Stop/Remove" : "Remove") : "Forward..."}
|
||||||
{" "}
|
{" "}
|
||||||
</Button>
|
</OpenLensButton>
|
||||||
{this.waiting && (
|
{this.waiting && (
|
||||||
<Spinner />
|
<Spinner />
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -17,7 +17,7 @@ import type { IObservableValue } from "mobx";
|
|||||||
import { action } from "mobx";
|
import { action } from "mobx";
|
||||||
import submitCustomHelmRepositoryInjectable from "./submit-custom-helm-repository.injectable";
|
import submitCustomHelmRepositoryInjectable from "./submit-custom-helm-repository.injectable";
|
||||||
import hideDialogForAddingCustomHelmRepositoryInjectable from "./dialog-visibility/hide-dialog-for-adding-custom-helm-repository.injectable";
|
import hideDialogForAddingCustomHelmRepositoryInjectable from "./dialog-visibility/hide-dialog-for-adding-custom-helm-repository.injectable";
|
||||||
import { Button } from "../../../../button";
|
import { OpenLensButton } from "../../../../button";
|
||||||
import { Icon } from "../../../../icon";
|
import { Icon } from "../../../../icon";
|
||||||
import maximalCustomHelmRepoOptionsAreShownInjectable from "./maximal-custom-helm-repo-options-are-shown.injectable";
|
import maximalCustomHelmRepoOptionsAreShownInjectable from "./maximal-custom-helm-repo-options-are-shown.injectable";
|
||||||
import { SubTitle } from "../../../../layout/sub-title";
|
import { SubTitle } from "../../../../layout/sub-title";
|
||||||
@ -59,7 +59,7 @@ const NonInjectedActivationOfCustomHelmRepositoryDialogContent = observer(({ hel
|
|||||||
onChange={action(v => helmRepo.url = v)}
|
onChange={action(v => helmRepo.url = v)}
|
||||||
data-testid="custom-helm-repository-url-input"
|
data-testid="custom-helm-repository-url-input"
|
||||||
/>
|
/>
|
||||||
<Button
|
<OpenLensButton
|
||||||
plain
|
plain
|
||||||
className="accordion"
|
className="accordion"
|
||||||
data-testid="toggle-maximal-options-for-custom-helm-repository-button"
|
data-testid="toggle-maximal-options-for-custom-helm-repository-button"
|
||||||
@ -71,7 +71,7 @@ const NonInjectedActivationOfCustomHelmRepositoryDialogContent = observer(({ hel
|
|||||||
tooltip="More"
|
tooltip="More"
|
||||||
material={maximalOptionsAreShown.get() ? "remove" : "add"}
|
material={maximalOptionsAreShown.get() ? "remove" : "add"}
|
||||||
/>
|
/>
|
||||||
</Button>
|
</OpenLensButton>
|
||||||
|
|
||||||
{maximalOptionsAreShown.get() && (
|
{maximalOptionsAreShown.get() && (
|
||||||
<div data-testid="maximal-options-for-custom-helm-repository-dialog">
|
<div data-testid="maximal-options-for-custom-helm-repository-dialog">
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { Button } from "../../../../button";
|
import { OpenLensButton } from "../../../../button";
|
||||||
import showDialogForAddingCustomHelmRepositoryInjectable from "./dialog-visibility/show-dialog-for-adding-custom-helm-repository.injectable";
|
import showDialogForAddingCustomHelmRepositoryInjectable from "./dialog-visibility/show-dialog-for-adding-custom-helm-repository.injectable";
|
||||||
|
|
||||||
interface Dependencies {
|
interface Dependencies {
|
||||||
@ -12,7 +12,7 @@ interface Dependencies {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const NonInjectedActivationOfCustomHelmRepositoryOpenButton = ({ showDialog }: Dependencies) => (
|
const NonInjectedActivationOfCustomHelmRepositoryOpenButton = ({ showDialog }: Dependencies) => (
|
||||||
<Button
|
<OpenLensButton
|
||||||
primary
|
primary
|
||||||
label="Add Custom Helm Repo"
|
label="Add Custom Helm Repo"
|
||||||
onClick={showDialog}
|
onClick={showDialog}
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import type { ContainerPort, Pod } from "../../../common/k8s-api/endpoints";
|
|||||||
import { action, makeObservable, observable, reaction } from "mobx";
|
import { action, makeObservable, observable, reaction } from "mobx";
|
||||||
import { cssNames } from "../../utils";
|
import { cssNames } from "../../utils";
|
||||||
import { Notifications } from "../notifications";
|
import { Notifications } from "../notifications";
|
||||||
import { Button } from "../button";
|
import { OpenLensButton } from "../button";
|
||||||
import type { ForwardedPort, PortForwardStore } from "../../port-forward";
|
import type { ForwardedPort, PortForwardStore } from "../../port-forward";
|
||||||
import { predictProtocol } from "../../port-forward";
|
import { predictProtocol } from "../../port-forward";
|
||||||
import { Spinner } from "../spinner";
|
import { Spinner } from "../spinner";
|
||||||
@ -181,11 +181,11 @@ class NonInjectedPodContainerPort extends React.Component<PodContainerPortProps
|
|||||||
<span title="Open in a browser" onClick={() => this.portForward()}>
|
<span title="Open in a browser" onClick={() => this.portForward()}>
|
||||||
{text}
|
{text}
|
||||||
</span>
|
</span>
|
||||||
<Button primary onClick={portForwardAction}>
|
<OpenLensButton primary onClick={portForwardAction}>
|
||||||
{" "}
|
{" "}
|
||||||
{this.isPortForwarded ? (this.isActive ? "Stop/Remove" : "Remove") : "Forward..."}
|
{this.isPortForwarded ? (this.isActive ? "Stop/Remove" : "Remove") : "Forward..."}
|
||||||
{" "}
|
{" "}
|
||||||
</Button>
|
</OpenLensButton>
|
||||||
{this.waiting && (
|
{this.waiting && (
|
||||||
<Spinner />
|
<Spinner />
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import "./add-remove-buttons.scss";
|
|||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { cssNames } from "../../utils";
|
import { cssNames } from "../../utils";
|
||||||
import { Button } from "../button";
|
import { OpenLensButton } from "../button";
|
||||||
import { Icon } from "../icon";
|
import { Icon } from "../icon";
|
||||||
|
|
||||||
export interface AddRemoveButtonsProps extends React.HTMLAttributes<any> {
|
export interface AddRemoveButtonsProps extends React.HTMLAttributes<any> {
|
||||||
@ -37,7 +37,7 @@ export class AddRemoveButtons extends React.PureComponent<AddRemoveButtonsProps>
|
|||||||
]
|
]
|
||||||
.filter(button => button.onClick)
|
.filter(button => button.onClick)
|
||||||
.map(({ icon, ...props }) => (
|
.map(({ icon, ...props }) => (
|
||||||
<Button
|
<OpenLensButton
|
||||||
key={icon}
|
key={icon}
|
||||||
big
|
big
|
||||||
round
|
round
|
||||||
@ -45,7 +45,7 @@ export class AddRemoveButtons extends React.PureComponent<AddRemoveButtonsProps>
|
|||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<Icon material={icon} />
|
<Icon material={icon} />
|
||||||
</Button>
|
</OpenLensButton>
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import randomColor from "randomcolor";
|
|||||||
import GraphemeSplitter from "grapheme-splitter";
|
import GraphemeSplitter from "grapheme-splitter";
|
||||||
import type { SingleOrMany } from "../../utils";
|
import type { SingleOrMany } from "../../utils";
|
||||||
import { cssNames, isDefined, iter } from "../../utils";
|
import { cssNames, isDefined, iter } from "../../utils";
|
||||||
|
import { OpenLensButton } from "../button";
|
||||||
|
|
||||||
export interface AvatarProps {
|
export interface AvatarProps {
|
||||||
title: string;
|
title: string;
|
||||||
@ -77,7 +78,7 @@ export const Avatar = ({
|
|||||||
onClick,
|
onClick,
|
||||||
"data-testid": dataTestId,
|
"data-testid": dataTestId,
|
||||||
}: AvatarProps) => (
|
}: AvatarProps) => (
|
||||||
<div
|
<OpenLensButton
|
||||||
className={cssNames(styles.Avatar, {
|
className={cssNames(styles.Avatar, {
|
||||||
[styles.circle]: variant == "circle",
|
[styles.circle]: variant == "circle",
|
||||||
[styles.rounded]: variant == "rounded",
|
[styles.rounded]: variant == "rounded",
|
||||||
@ -105,5 +106,5 @@ export const Avatar = ({
|
|||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
: children || getLabelFromTitle(title)}
|
: children || getLabelFromTitle(title)}
|
||||||
</div>
|
</OpenLensButton>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -7,7 +7,9 @@ import "./button.scss";
|
|||||||
import type { ButtonHTMLAttributes } from "react";
|
import type { ButtonHTMLAttributes } from "react";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { cssNames } from "../../utils";
|
import { cssNames } from "../../utils";
|
||||||
|
import type { TooltipDecoratorProps } from "../tooltip";
|
||||||
import { withTooltip } from "../tooltip";
|
import { withTooltip } from "../tooltip";
|
||||||
|
import { OnClickDecorated } from "../on-click-decorated/on-click-decorated";
|
||||||
|
|
||||||
export interface ButtonProps extends ButtonHTMLAttributes<any> {
|
export interface ButtonProps extends ButtonHTMLAttributes<any> {
|
||||||
label?: React.ReactNode;
|
label?: React.ReactNode;
|
||||||
@ -23,16 +25,22 @@ export interface ButtonProps extends ButtonHTMLAttributes<any> {
|
|||||||
round?: boolean;
|
round?: boolean;
|
||||||
href?: string; // render as hyperlink
|
href?: string; // render as hyperlink
|
||||||
target?: "_blank"; // in case of using @href
|
target?: "_blank"; // in case of using @href
|
||||||
|
Component?: React.ComponentType<any>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const PlainButton = (props: React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>) => <button {...props} />;
|
||||||
|
const PlainAnchor = (props: React.DetailedHTMLProps<React.AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>) => <a {...props} />;
|
||||||
|
|
||||||
export const Button = withTooltip((props: ButtonProps) => {
|
export const Button = withTooltip((props: ButtonProps) => {
|
||||||
const {
|
const {
|
||||||
waiting, label, primary, accent, plain, hidden, active, big,
|
waiting, label, primary, accent, plain, hidden, active, big,
|
||||||
round, outlined, light, children, ...btnProps
|
round, outlined, light, children, Component, ...btnProps
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
if (hidden) return null;
|
if (hidden) return null;
|
||||||
|
|
||||||
|
const ButtonComponent = Component ?? (props.href ? PlainAnchor : PlainButton);
|
||||||
|
|
||||||
btnProps.className = cssNames("Button", btnProps.className, {
|
btnProps.className = cssNames("Button", btnProps.className, {
|
||||||
waiting, primary, accent, plain, active, big, round, outlined, light,
|
waiting, primary, accent, plain, active, big, round, outlined, light,
|
||||||
});
|
});
|
||||||
@ -40,18 +48,25 @@ export const Button = withTooltip((props: ButtonProps) => {
|
|||||||
// render as link
|
// render as link
|
||||||
if (props.href) {
|
if (props.href) {
|
||||||
return (
|
return (
|
||||||
<a {...btnProps}>
|
<ButtonComponent
|
||||||
|
{...btnProps}>
|
||||||
{label}
|
{label}
|
||||||
{children}
|
{children}
|
||||||
</a>
|
</ButtonComponent>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// render as button
|
// render as button
|
||||||
return (
|
return (
|
||||||
<button type="button" {...btnProps}>
|
<ButtonComponent
|
||||||
|
type="button"
|
||||||
|
{...btnProps}>
|
||||||
{label}
|
{label}
|
||||||
{children}
|
{children}
|
||||||
</button>
|
</ButtonComponent>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const OpenLensButton = (props: ButtonProps & TooltipDecoratorProps) => {
|
||||||
|
return <Button {...props} Component={(props) => <OnClickDecorated {...props} tagName={props.href ? "a" : "button"} />} />;
|
||||||
|
};
|
||||||
|
|||||||
@ -12,7 +12,7 @@ import { ipcRendererOn } from "../../../common/ipc";
|
|||||||
import type { Cluster } from "../../../common/cluster/cluster";
|
import type { Cluster } from "../../../common/cluster/cluster";
|
||||||
import type { IClassName } from "../../utils";
|
import type { IClassName } from "../../utils";
|
||||||
import { isBoolean, hasTypedProperty, isObject, isString, cssNames } from "../../utils";
|
import { isBoolean, hasTypedProperty, isObject, isString, cssNames } from "../../utils";
|
||||||
import { Button } from "../button";
|
import { OpenLensButton } from "../button";
|
||||||
import { Icon } from "../icon";
|
import { Icon } from "../icon";
|
||||||
import { Spinner } from "../spinner";
|
import { Spinner } from "../spinner";
|
||||||
import type { KubeAuthUpdate } from "../../../common/cluster-types";
|
import type { KubeAuthUpdate } from "../../../common/cluster-types";
|
||||||
@ -134,7 +134,7 @@ class NonInjectedClusterStatus extends React.Component<ClusterStatusProps & Depe
|
|||||||
if (this.hasErrors && !this.isReconnecting) {
|
if (this.hasErrors && !this.isReconnecting) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Button
|
<OpenLensButton
|
||||||
primary
|
primary
|
||||||
label="Reconnect"
|
label="Reconnect"
|
||||||
className="box center"
|
className="box center"
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import React from "react";
|
|||||||
import { disposeOnUnmount, observer } from "mobx-react";
|
import { disposeOnUnmount, observer } from "mobx-react";
|
||||||
import { onMultiSelectFor, Select } from "../../select/select";
|
import { onMultiSelectFor, Select } from "../../select/select";
|
||||||
import { Icon } from "../../icon/icon";
|
import { Icon } from "../../icon/icon";
|
||||||
import { Button } from "../../button/button";
|
import { OpenLensButton } from "../../button/button";
|
||||||
import { SubTitle } from "../../layout/sub-title";
|
import { SubTitle } from "../../layout/sub-title";
|
||||||
import type { Cluster } from "../../../../common/cluster/cluster";
|
import type { Cluster } from "../../../../common/cluster/cluster";
|
||||||
import { observable, reaction, makeObservable } from "mobx";
|
import { observable, reaction, makeObservable } from "mobx";
|
||||||
@ -85,12 +85,12 @@ export class ClusterMetricsSetting extends React.Component<ClusterMetricsSetting
|
|||||||
)}
|
)}
|
||||||
themeName="lens"
|
themeName="lens"
|
||||||
/>
|
/>
|
||||||
<Button
|
<OpenLensButton
|
||||||
primary
|
primary
|
||||||
label="Hide all metrics"
|
label="Hide all metrics"
|
||||||
onClick={this.onChangeButton}
|
onClick={this.onChangeButton}
|
||||||
/>
|
/>
|
||||||
<Button
|
<OpenLensButton
|
||||||
primary
|
primary
|
||||||
label="Reset"
|
label="Reset"
|
||||||
onClick={this.reset}
|
onClick={this.reset}
|
||||||
|
|||||||
@ -12,7 +12,7 @@ import { observable, makeObservable, computed } from "mobx";
|
|||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import { cssNames, noop, prevDefault } from "../../utils";
|
import { cssNames, noop, prevDefault } from "../../utils";
|
||||||
import type { ButtonProps } from "../button";
|
import type { ButtonProps } from "../button";
|
||||||
import { Button } from "../button";
|
import { OpenLensButton } from "../button";
|
||||||
import type { DialogProps } from "../dialog";
|
import type { DialogProps } from "../dialog";
|
||||||
import { Dialog } from "../dialog";
|
import { Dialog } from "../dialog";
|
||||||
import { Icon } from "../icon";
|
import { Icon } from "../icon";
|
||||||
@ -140,14 +140,14 @@ class NonInjectedConfirmDialog extends React.Component<ConfirmDialogProps & Depe
|
|||||||
{message}
|
{message}
|
||||||
</div>
|
</div>
|
||||||
<div className="confirm-buttons">
|
<div className="confirm-buttons">
|
||||||
<Button
|
<OpenLensButton
|
||||||
plain
|
plain
|
||||||
className="cancel"
|
className="cancel"
|
||||||
label={labelCancel}
|
label={labelCancel}
|
||||||
onClick={prevDefault(this.close)}
|
onClick={prevDefault(this.close)}
|
||||||
{...cancelButtonProps}
|
{...cancelButtonProps}
|
||||||
/>
|
/>
|
||||||
<Button
|
<OpenLensButton
|
||||||
autoFocus
|
autoFocus
|
||||||
primary
|
primary
|
||||||
className="ok"
|
className="ok"
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import { action, observable } from "mobx";
|
|||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
import { Button } from "../button";
|
import { OpenLensButton } from "../button";
|
||||||
import { saveKubeconfig } from "./save-config";
|
import { saveKubeconfig } from "./save-config";
|
||||||
import { Notifications } from "../notifications";
|
import { Notifications } from "../notifications";
|
||||||
import { Dialog } from "../dialog";
|
import { Dialog } from "../dialog";
|
||||||
@ -226,12 +226,12 @@ class NonInjectedDeleteClusterDialog extends React.Component<Dependencies> {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.dialogButtons}>
|
<div className={styles.dialogButtons}>
|
||||||
<Button
|
<OpenLensButton
|
||||||
onClick={this.close}
|
onClick={this.close}
|
||||||
plain
|
plain
|
||||||
label="Cancel"
|
label="Cancel"
|
||||||
/>
|
/>
|
||||||
<Button
|
<OpenLensButton
|
||||||
onClick={() => this.onDelete(state)}
|
onClick={() => this.onDelete(state)}
|
||||||
autoFocus
|
autoFocus
|
||||||
accent
|
accent
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import type { DialogProps } from "../dialog";
|
|||||||
import { Dialog } from "../dialog";
|
import { Dialog } from "../dialog";
|
||||||
import { Wizard, WizardStep } from "../wizard";
|
import { Wizard, WizardStep } from "../wizard";
|
||||||
import { Notifications } from "../notifications";
|
import { Notifications } from "../notifications";
|
||||||
import { Button } from "../button";
|
import { OpenLensButton } from "../button";
|
||||||
import { Icon } from "../icon";
|
import { Icon } from "../icon";
|
||||||
import { clipboard } from "electron";
|
import { clipboard } from "electron";
|
||||||
import { kebabCase } from "lodash/fp";
|
import { kebabCase } from "lodash/fp";
|
||||||
@ -35,7 +35,7 @@ export function LogsDialog({ title, logs, ...dialogProps }: LogsDialogProps) {
|
|||||||
scrollable={false}
|
scrollable={false}
|
||||||
customButtons={(
|
customButtons={(
|
||||||
<div className="buttons flex gaps align-center justify-space-between">
|
<div className="buttons flex gaps align-center justify-space-between">
|
||||||
<Button
|
<OpenLensButton
|
||||||
plain
|
plain
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
clipboard.writeText(logs);
|
clipboard.writeText(logs);
|
||||||
@ -44,10 +44,10 @@ export function LogsDialog({ title, logs, ...dialogProps }: LogsDialogProps) {
|
|||||||
>
|
>
|
||||||
<Icon material="assignment"/>
|
<Icon material="assignment"/>
|
||||||
{" Copy to clipboard"}
|
{" Copy to clipboard"}
|
||||||
</Button>
|
</OpenLensButton>
|
||||||
<Button plain onClick={dialogProps.close}>
|
<OpenLensButton plain onClick={dialogProps.close}>
|
||||||
Close
|
Close
|
||||||
</Button>
|
</OpenLensButton>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import React, { Component } from "react";
|
|||||||
import { computed, observable, reaction, makeObservable } from "mobx";
|
import { computed, observable, reaction, makeObservable } from "mobx";
|
||||||
import { disposeOnUnmount, observer } from "mobx-react";
|
import { disposeOnUnmount, observer } from "mobx-react";
|
||||||
import { cssNames } from "../../utils";
|
import { cssNames } from "../../utils";
|
||||||
import { Button } from "../button";
|
import { OpenLensButton } from "../button";
|
||||||
import { Icon } from "../icon";
|
import { Icon } from "../icon";
|
||||||
import { Spinner } from "../spinner";
|
import { Spinner } from "../spinner";
|
||||||
import type { DockStore, TabId } from "./dock/store";
|
import type { DockStore, TabId } from "./dock/store";
|
||||||
@ -146,13 +146,13 @@ class NonInjectedInfoPanel extends Component<InfoPanelProps & Dependencies> {
|
|||||||
)}
|
)}
|
||||||
{showButtons && (
|
{showButtons && (
|
||||||
<>
|
<>
|
||||||
<Button
|
<OpenLensButton
|
||||||
plain
|
plain
|
||||||
label="Cancel"
|
label="Cancel"
|
||||||
onClick={close}
|
onClick={close}
|
||||||
data-testid={this.props.cancelTestId}
|
data-testid={this.props.cancelTestId}
|
||||||
/>
|
/>
|
||||||
<Button
|
<OpenLensButton
|
||||||
active
|
active
|
||||||
outlined={showSubmitClose}
|
outlined={showSubmitClose}
|
||||||
primary={!showSubmitClose}// one button always should be primary (blue)
|
primary={!showSubmitClose}// one button always should be primary (blue)
|
||||||
@ -162,7 +162,7 @@ class NonInjectedInfoPanel extends Component<InfoPanelProps & Dependencies> {
|
|||||||
data-testid={this.props.submitTestId}
|
data-testid={this.props.submitTestId}
|
||||||
/>
|
/>
|
||||||
{showSubmitClose && (
|
{showSubmitClose && (
|
||||||
<Button
|
<OpenLensButton
|
||||||
primary
|
primary
|
||||||
active
|
active
|
||||||
label={`${submitLabel} & Close`}
|
label={`${submitLabel} & Close`}
|
||||||
|
|||||||
@ -13,7 +13,7 @@ import { Badge } from "../../badge";
|
|||||||
import { NamespaceSelect } from "../../+namespaces/namespace-select";
|
import { NamespaceSelect } from "../../+namespaces/namespace-select";
|
||||||
import { prevDefault } from "../../../utils";
|
import { prevDefault } from "../../../utils";
|
||||||
import { Icon } from "../../icon";
|
import { Icon } from "../../icon";
|
||||||
import { Button } from "../../button";
|
import { OpenLensButton } from "../../button";
|
||||||
import { LogsDialog } from "../../dialog/logs-dialog";
|
import { LogsDialog } from "../../dialog/logs-dialog";
|
||||||
import { Select } from "../../select";
|
import { Select } from "../../select";
|
||||||
import { Input } from "../../input";
|
import { Input } from "../../input";
|
||||||
@ -46,14 +46,14 @@ const NonInjectedInstallChart = observer(
|
|||||||
</p>
|
</p>
|
||||||
<p>Installation complete!</p>
|
<p>Installation complete!</p>
|
||||||
<div className="flex gaps align-center">
|
<div className="flex gaps align-center">
|
||||||
<Button
|
<OpenLensButton
|
||||||
autoFocus
|
autoFocus
|
||||||
primary
|
primary
|
||||||
label="View Helm Release"
|
label="View Helm Release"
|
||||||
onClick={prevDefault(model.navigateToInstalledRelease)}
|
onClick={prevDefault(model.navigateToInstalledRelease)}
|
||||||
data-testid={`show-release-${installed.release.name}-for-${tabId}`}
|
data-testid={`show-release-${installed.release.name}-for-${tabId}`}
|
||||||
/>
|
/>
|
||||||
<Button
|
<OpenLensButton
|
||||||
plain
|
plain
|
||||||
active
|
active
|
||||||
label="Show Notes"
|
label="Show Notes"
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import "./error-boundary.scss";
|
|||||||
import type { ErrorInfo } from "react";
|
import type { ErrorInfo } from "react";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import { Button } from "../button";
|
import { OpenLensButton } from "../button";
|
||||||
import { navigation } from "../../navigation";
|
import { navigation } from "../../navigation";
|
||||||
import { issuesTrackerUrl, slackUrl } from "../../../common/vars";
|
import { issuesTrackerUrl, slackUrl } from "../../../common/vars";
|
||||||
import type { SingleOrMany } from "../../utils";
|
import type { SingleOrMany } from "../../utils";
|
||||||
@ -75,7 +75,7 @@ export class ErrorBoundary extends React.Component<ErrorBoundaryProps, State> {
|
|||||||
{error.stack}
|
{error.stack}
|
||||||
</code>
|
</code>
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<OpenLensButton
|
||||||
className="box self-flex-start"
|
className="box self-flex-start"
|
||||||
primary
|
primary
|
||||||
label="Back"
|
label="Back"
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import { observer } from "mobx-react";
|
|||||||
import yaml from "js-yaml";
|
import yaml from "js-yaml";
|
||||||
import type { ServiceAccount } from "../../../common/k8s-api/endpoints";
|
import type { ServiceAccount } from "../../../common/k8s-api/endpoints";
|
||||||
import { cssNames, saveFileDialog } from "../../utils";
|
import { cssNames, saveFileDialog } from "../../utils";
|
||||||
import { Button } from "../button";
|
import { OpenLensButton } from "../button";
|
||||||
import type { DialogProps } from "../dialog";
|
import type { DialogProps } from "../dialog";
|
||||||
import { Dialog } from "../dialog";
|
import { Dialog } from "../dialog";
|
||||||
import { Icon } from "../icon";
|
import { Icon } from "../icon";
|
||||||
@ -81,21 +81,21 @@ export class KubeConfigDialog extends React.Component<KubeConfigDialogProps> {
|
|||||||
<WizardStep
|
<WizardStep
|
||||||
customButtons={(
|
customButtons={(
|
||||||
<div className="actions flex gaps">
|
<div className="actions flex gaps">
|
||||||
<Button plain onClick={this.copyToClipboard}>
|
<OpenLensButton plain onClick={this.copyToClipboard}>
|
||||||
<Icon material="assignment"/>
|
<Icon material="assignment"/>
|
||||||
{" Copy to clipboard"}
|
{" Copy to clipboard"}
|
||||||
</Button>
|
</OpenLensButton>
|
||||||
<Button plain onClick={this.download}>
|
<OpenLensButton plain onClick={this.download}>
|
||||||
<Icon material="cloud_download"/>
|
<Icon material="cloud_download"/>
|
||||||
{" Download file"}
|
{" Download file"}
|
||||||
</Button>
|
</OpenLensButton>
|
||||||
<Button
|
<OpenLensButton
|
||||||
plain
|
plain
|
||||||
className="box right"
|
className="box right"
|
||||||
onClick={this.close}
|
onClick={this.close}
|
||||||
>
|
>
|
||||||
Close
|
Close
|
||||||
</Button>
|
</OpenLensButton>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
prev={this.close}
|
prev={this.close}
|
||||||
|
|||||||
@ -0,0 +1,11 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`foobar given A -element 1`] = `
|
||||||
|
<body>
|
||||||
|
<div>
|
||||||
|
<a
|
||||||
|
data-testid="some-anchor"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
`;
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`foobar given A -element 1`] = `
|
||||||
|
<body>
|
||||||
|
<div>
|
||||||
|
<a
|
||||||
|
data-testid="some-anchor"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
`;
|
||||||
@ -0,0 +1,104 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
import { getDiForUnitTesting } from "../../getDiForUnitTesting";
|
||||||
|
import type { DiRender } from "../test-utils/renderFor";
|
||||||
|
import { renderFor } from "../test-utils/renderFor";
|
||||||
|
import { OpenLensButton } from "../button";
|
||||||
|
import React from "react";
|
||||||
|
import { fireEvent } from "@testing-library/dom";
|
||||||
|
import type { RenderResult } from "@testing-library/react";
|
||||||
|
import { onClickDecoratorInjectionToken } from "./on-click-decorator-injection-token";
|
||||||
|
import type { DiContainer } from "@ogre-tools/injectable";
|
||||||
|
import { getInjectable } from "@ogre-tools/injectable";
|
||||||
|
import { OnClickDecorated } from "./on-click-decorated";
|
||||||
|
|
||||||
|
describe("foobar", () => {
|
||||||
|
let di: DiContainer;
|
||||||
|
let render: DiRender;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
di = getDiForUnitTesting({ doGeneralOverrides: true });
|
||||||
|
render = renderFor(di);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("given A -element", () => {
|
||||||
|
const rendered = render(
|
||||||
|
<OnClickDecorated
|
||||||
|
tagName="a"
|
||||||
|
onClick={() => {}}
|
||||||
|
data-testid="some-anchor"
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(rendered.baseElement).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
describe("given button", () => {
|
||||||
|
let onClickMock: jest.Mock;
|
||||||
|
let firstHigherOrderFunctionMock: jest.Mock;
|
||||||
|
let secondHigherOrderFunctionMock: jest.Mock;
|
||||||
|
let rendered: RenderResult;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
onClickMock = jest.fn();
|
||||||
|
firstHigherOrderFunctionMock = jest.fn((x) => x);
|
||||||
|
secondHigherOrderFunctionMock = jest.fn((x) => x);
|
||||||
|
|
||||||
|
const someInjectable = getInjectable({
|
||||||
|
id: "some-injectable",
|
||||||
|
|
||||||
|
instantiate: () => ({
|
||||||
|
onClick: firstHigherOrderFunctionMock,
|
||||||
|
}),
|
||||||
|
|
||||||
|
injectionToken: onClickDecoratorInjectionToken,
|
||||||
|
});
|
||||||
|
|
||||||
|
const someOtherInjectable = getInjectable({
|
||||||
|
id: "some-other-injectable",
|
||||||
|
|
||||||
|
instantiate: () => ({
|
||||||
|
onClick: secondHigherOrderFunctionMock,
|
||||||
|
}),
|
||||||
|
|
||||||
|
injectionToken: onClickDecoratorInjectionToken,
|
||||||
|
});
|
||||||
|
|
||||||
|
di.register(someInjectable, someOtherInjectable);
|
||||||
|
|
||||||
|
rendered = render(
|
||||||
|
<OpenLensButton
|
||||||
|
primary
|
||||||
|
label="Add Custom Helm Repo"
|
||||||
|
onClick={onClickMock}
|
||||||
|
data-testid="add-custom-helm-repo-button"
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when button is clicked", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
fireEvent.click(rendered.getByTestId("add-custom-helm-repo-button"));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("calls the original onClick", () => {
|
||||||
|
expect(onClickMock).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("calls the original onClick with an argument", () => {
|
||||||
|
expect(onClickMock).toHaveBeenCalledWith(expect.any(Object));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("calls the first higher order function", () => {
|
||||||
|
expect(firstHigherOrderFunctionMock).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("calls the second higher order function", () => {
|
||||||
|
expect(secondHigherOrderFunctionMock).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||||
|
import { flow } from "lodash/fp";
|
||||||
|
import type { HTMLAttributes, MouseEventHandler } from "react";
|
||||||
|
import React from "react";
|
||||||
|
import type { OnClickDecorator } from "./on-click-decorator-injection-token";
|
||||||
|
import { onClickDecoratorInjectionToken } from "./on-click-decorator-injection-token";
|
||||||
|
|
||||||
|
interface Dependencies {
|
||||||
|
decorators: OnClickDecorator[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ClickDecoratedProps extends HTMLAttributes<any> {
|
||||||
|
onClick?: MouseEventHandler<any>;
|
||||||
|
tagName: "button" | "a";
|
||||||
|
}
|
||||||
|
|
||||||
|
const NonInjectedOnClickDecorated = ({ decorators, tagName: TagName, onClick, ...props }: Dependencies & ClickDecoratedProps) => {
|
||||||
|
const onClickDecorators = decorators.map(decorator => decorator.onClick);
|
||||||
|
|
||||||
|
const decoratedOnClick = onClick ? flow(...onClickDecorators)(onClick) : undefined;
|
||||||
|
|
||||||
|
return <TagName {...props} onClick={decoratedOnClick} />;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const OnClickDecorated = withInjectables<Dependencies, ClickDecoratedProps>(
|
||||||
|
NonInjectedOnClickDecorated,
|
||||||
|
|
||||||
|
{
|
||||||
|
getProps: (di, props) => ({
|
||||||
|
decorators: di.injectMany(onClickDecoratorInjectionToken),
|
||||||
|
...props,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
);
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
/**
|
||||||
|
* 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 { MouseEventHandler } from "react";
|
||||||
|
import type React from "react";
|
||||||
|
|
||||||
|
type OnClick = (toBeDecorated: MouseEventHandler<any>) => (event: React.MouseEvent) => void;
|
||||||
|
|
||||||
|
export interface OnClickDecorator {
|
||||||
|
onClick: OnClick;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const onClickDecoratorInjectionToken = getInjectionToken<OnClickDecorator>({
|
||||||
|
id: "onclick-decorator-injection-token",
|
||||||
|
});
|
||||||
@ -0,0 +1,67 @@
|
|||||||
|
/**
|
||||||
|
* 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 { AppEvent } from "../../../common/app-event-bus/event-bus";
|
||||||
|
import type { EventEmitter } from "../../../common/event-emitter";
|
||||||
|
import capitalize from "lodash/capitalize";
|
||||||
|
import { onClickDecoratorInjectionToken } from "./on-click-decorator-injection-token";
|
||||||
|
import appEventBusInjectable from "../../../common/app-event-bus/app-event-bus.injectable";
|
||||||
|
|
||||||
|
function getEventName(el: HTMLElement, pathname: string, parentLevels = 3) {
|
||||||
|
let headers: string[] = [];
|
||||||
|
let parent = el;
|
||||||
|
|
||||||
|
const path = pathname.split("/");
|
||||||
|
|
||||||
|
headers.push(capitalize(path[path.length-1]));
|
||||||
|
|
||||||
|
for (let i = 0; i < parentLevels; i++) {
|
||||||
|
if (parent.parentElement) {
|
||||||
|
parent = parent.parentElement;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const nodelist = parent.querySelectorAll("h1, h2, h3, h4, h5, h6, .header");
|
||||||
|
|
||||||
|
nodelist.forEach(node => node.textContent && headers.push(node.textContent));
|
||||||
|
|
||||||
|
headers = [...new Set(headers)];
|
||||||
|
|
||||||
|
if (el?.textContent) {
|
||||||
|
headers.push(el.textContent);
|
||||||
|
}
|
||||||
|
const eventName = headers.join(" ");
|
||||||
|
|
||||||
|
return eventName;
|
||||||
|
}
|
||||||
|
|
||||||
|
function captureMouseEvent(eventBus: EventEmitter<[AppEvent]>, event: React.MouseEvent) {
|
||||||
|
const name = getEventName(event.target as HTMLElement, window.location.pathname);
|
||||||
|
|
||||||
|
eventBus.emit({
|
||||||
|
name,
|
||||||
|
action: capitalize(event.type),
|
||||||
|
destination: "AutoCapture",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const onClickTelemetryDecoratorInjectable = getInjectable({
|
||||||
|
id: "on-click-telemetry-decorator",
|
||||||
|
|
||||||
|
instantiate: (di) => ({
|
||||||
|
onClick: (toBeDecorated) => {
|
||||||
|
return (event) => {
|
||||||
|
captureMouseEvent(di.inject(appEventBusInjectable), event);
|
||||||
|
|
||||||
|
return toBeDecorated(event);
|
||||||
|
};
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
|
||||||
|
injectionToken: onClickDecoratorInjectionToken,
|
||||||
|
});
|
||||||
|
|
||||||
|
export default onClickTelemetryDecoratorInjectable;
|
||||||
@ -7,7 +7,7 @@ import type { FileFilter, OpenDialogOptions } from "electron";
|
|||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { cssNames } from "../../utils";
|
import { cssNames } from "../../utils";
|
||||||
import { Button } from "../button";
|
import { OpenLensButton } from "../button";
|
||||||
import { requestOpenFilePickingDialog } from "../../ipc";
|
import { requestOpenFilePickingDialog } from "../../ipc";
|
||||||
|
|
||||||
export interface PathPickOpts {
|
export interface PathPickOpts {
|
||||||
@ -53,7 +53,7 @@ export class PathPicker extends React.Component<PathPickerProps> {
|
|||||||
const { className, label, disabled } = this.props;
|
const { className, label, disabled } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button
|
<OpenLensButton
|
||||||
primary
|
primary
|
||||||
label={label}
|
label={label}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
import "./wizard.scss";
|
import "./wizard.scss";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { cssNames, prevDefault } from "../../utils";
|
import { cssNames, prevDefault } from "../../utils";
|
||||||
import { Button } from "../button";
|
import { OpenLensButton } from "../button";
|
||||||
import { Stepper } from "../stepper";
|
import { Stepper } from "../stepper";
|
||||||
import { SubTitle } from "../layout/sub-title";
|
import { SubTitle } from "../layout/sub-title";
|
||||||
import { Spinner } from "../spinner";
|
import { Spinner } from "../spinner";
|
||||||
@ -238,7 +238,7 @@ export class WizardStep<D> extends React.Component<WizardStepProps<D>, WizardSte
|
|||||||
{customButtons ?? (
|
{customButtons ?? (
|
||||||
<div className="buttons flex gaps align-center">
|
<div className="buttons flex gaps align-center">
|
||||||
{moreButtons}
|
{moreButtons}
|
||||||
<Button
|
<OpenLensButton
|
||||||
className="back-btn"
|
className="back-btn"
|
||||||
plain
|
plain
|
||||||
label={prevLabel || (isFirst?.() ? "Cancel" : "Back")}
|
label={prevLabel || (isFirst?.() ? "Cancel" : "Back")}
|
||||||
@ -246,7 +246,7 @@ export class WizardStep<D> extends React.Component<WizardStepProps<D>, WizardSte
|
|||||||
onClick={this.prev}
|
onClick={this.prev}
|
||||||
data-testid={testIdForPrev}
|
data-testid={testIdForPrev}
|
||||||
/>
|
/>
|
||||||
<Button
|
<OpenLensButton
|
||||||
primary
|
primary
|
||||||
type="submit"
|
type="submit"
|
||||||
label={nextLabel || (isLast?.() ? "Submit" : "Next")}
|
label={nextLabel || (isLast?.() ? "Submit" : "Next")}
|
||||||
|
|||||||
@ -73,6 +73,9 @@ import forceUpdateModalRootFrameComponentInjectable from "./application-update/f
|
|||||||
import legacyOnChannelListenInjectable from "./ipc/legacy-channel-listen.injectable";
|
import legacyOnChannelListenInjectable from "./ipc/legacy-channel-listen.injectable";
|
||||||
import getEntitySettingCommandsInjectable from "./components/command-palette/registered-commands/get-entity-setting-commands.injectable";
|
import getEntitySettingCommandsInjectable from "./components/command-palette/registered-commands/get-entity-setting-commands.injectable";
|
||||||
import storageSaveDelayInjectable from "./utils/create-storage/storage-save-delay.injectable";
|
import storageSaveDelayInjectable from "./utils/create-storage/storage-save-delay.injectable";
|
||||||
|
import appEventBusInjectable from "../common/app-event-bus/app-event-bus.injectable";
|
||||||
|
import { EventEmitter } from "./utils";
|
||||||
|
import type { AppEvent } from "../common/app-event-bus/event-bus";
|
||||||
|
|
||||||
export const getDiForUnitTesting = (opts: { doGeneralOverrides?: boolean } = {}) => {
|
export const getDiForUnitTesting = (opts: { doGeneralOverrides?: boolean } = {}) => {
|
||||||
const {
|
const {
|
||||||
@ -227,6 +230,8 @@ export const getDiForUnitTesting = (opts: { doGeneralOverrides?: boolean } = {})
|
|||||||
info: noop,
|
info: noop,
|
||||||
silly: noop,
|
silly: noop,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
di.override(appEventBusInjectable, () => new EventEmitter<[AppEvent]>());
|
||||||
}
|
}
|
||||||
|
|
||||||
return di;
|
return di;
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import navigateToEntitySettingsInjectable from "../../common/front-end-routing/r
|
|||||||
import type { ListNamespaceForbiddenArgs } from "../../common/ipc/cluster";
|
import type { ListNamespaceForbiddenArgs } from "../../common/ipc/cluster";
|
||||||
import { Notifications } from "../components/notifications";
|
import { Notifications } from "../components/notifications";
|
||||||
import { ClusterStore } from "../../common/cluster-store/cluster-store";
|
import { ClusterStore } from "../../common/cluster-store/cluster-store";
|
||||||
import { Button } from "../components/button";
|
import { OpenLensButton } from "../components/button";
|
||||||
import type { IpcRendererEvent } from "electron";
|
import type { IpcRendererEvent } from "electron";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import notificationsStoreInjectable from "../components/notifications/notifications-store.injectable";
|
import notificationsStoreInjectable from "../components/notifications/notifications-store.injectable";
|
||||||
@ -56,7 +56,7 @@ const listNamespacesForbiddenHandlerInjectable = getInjectable({
|
|||||||
{" does not have permissions to list namespaces. Please add the namespaces you have access to."}
|
{" does not have permissions to list namespaces. Please add the namespaces you have access to."}
|
||||||
</p>
|
</p>
|
||||||
<div className="flex gaps row align-left box grow">
|
<div className="flex gaps row align-left box grow">
|
||||||
<Button
|
<OpenLensButton
|
||||||
active
|
active
|
||||||
outlined
|
outlined
|
||||||
label="Go to Accessible Namespaces Settings"
|
label="Go to Accessible Namespaces Settings"
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { Button } from "../components/button";
|
import { OpenLensButton } from "../components/button";
|
||||||
import { Notifications } from "../components/notifications";
|
import { Notifications } from "../components/notifications";
|
||||||
import type { NavigateToPortForwards } from "../../common/front-end-routing/routes/cluster/network/port-forwards/navigate-to-port-forwards.injectable";
|
import type { NavigateToPortForwards } from "../../common/front-end-routing/routes/cluster/network/port-forwards/navigate-to-port-forwards.injectable";
|
||||||
import type { NotificationsStore } from "../components/notifications/notifications.store";
|
import type { NotificationsStore } from "../components/notifications/notifications.store";
|
||||||
@ -30,7 +30,7 @@ export const aboutPortForwarding = ({
|
|||||||
You can manage your port forwards on the Port Forwarding Page.
|
You can manage your port forwards on the Port Forwarding Page.
|
||||||
</p>
|
</p>
|
||||||
<div className="flex gaps row align-left box grow">
|
<div className="flex gaps row align-left box grow">
|
||||||
<Button
|
<OpenLensButton
|
||||||
active
|
active
|
||||||
outlined
|
outlined
|
||||||
label="Go to Port Forwarding"
|
label="Go to Port Forwarding"
|
||||||
@ -71,7 +71,7 @@ export const notifyErrorPortForwarding = ({
|
|||||||
{msg}
|
{msg}
|
||||||
</p>
|
</p>
|
||||||
<div className="flex gaps row align-left box grow">
|
<div className="flex gaps row align-left box grow">
|
||||||
<Button
|
<OpenLensButton
|
||||||
active
|
active
|
||||||
outlined
|
outlined
|
||||||
label="Check Port Forwarding"
|
label="Check Port Forwarding"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user