mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Add ability to hide KubeObjectMenu Edit and Remove buttons in extensions (#5107)
This commit is contained in:
1 parent
e532b90b72
commit
dbdde19222
51 files changed
+1245
-765
No files matched your search
@@ -6,34 +6,47 @@
|
||||
import "./menu-actions.scss";
|
||||
|
||||
import React, { isValidElement } from "react";
|
||||
import { observable, makeObservable } from "mobx";
|
||||
import { observer } from "mobx-react";
|
||||
import { observable, makeObservable, reaction } from "mobx";
|
||||
import { disposeOnUnmount, observer } from "mobx-react";
|
||||
import { autoBind, cssNames } from "../../utils";
|
||||
import { ConfirmDialog } from "../confirm-dialog";
|
||||
import type { IconProps } from "../icon";
|
||||
import { Icon } from "../icon";
|
||||
import type { MenuProps } from "./menu";
|
||||
import { Menu, MenuItem } from "./menu";
|
||||
import uniqueId from "lodash/uniqueId";
|
||||
import isString from "lodash/isString";
|
||||
import type { OpenConfirmDialog } from "../confirm-dialog/open.injectable";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import openConfirmDialogInjectable from "../confirm-dialog/open.injectable";
|
||||
|
||||
export interface MenuActionsProps extends Partial<MenuProps> {
|
||||
className?: string;
|
||||
toolbar?: boolean; // display menu as toolbar with icons
|
||||
autoCloseOnSelect?: boolean;
|
||||
triggerIcon?: string | IconProps | React.ReactNode;
|
||||
/**
|
||||
* @deprecated Provide your own remove `<MenuItem>` as part of the `children` passed to this component
|
||||
*/
|
||||
removeConfirmationMessage?: React.ReactNode | (() => React.ReactNode);
|
||||
updateAction?(): void;
|
||||
removeAction?(): void;
|
||||
onOpen?(): void;
|
||||
/**
|
||||
* @deprecated Provide your own update `<MenuItem>` as part of the `children` passed to this component
|
||||
*/
|
||||
updateAction?: () => void | Promise<void>;
|
||||
/**
|
||||
* @deprecated Provide your own remove `<MenuItem>` as part of the `children` passed to this component
|
||||
*/
|
||||
removeAction?: () => void | Promise<void>;
|
||||
onOpen?: () => void;
|
||||
}
|
||||
|
||||
interface Dependencies {
|
||||
openConfirmDialog: OpenConfirmDialog;
|
||||
}
|
||||
|
||||
@observer
|
||||
export class MenuActions extends React.Component<MenuActionsProps> {
|
||||
static defaultProps: MenuActionsProps = {
|
||||
get removeConfirmationMessage() {
|
||||
return `Remove item?`;
|
||||
},
|
||||
class NonInjectedMenuActions extends React.Component<MenuActionsProps & Dependencies> {
|
||||
static defaultProps = {
|
||||
removeConfirmationMessage: "Remove item?",
|
||||
};
|
||||
|
||||
public id = uniqueId("menu_actions_");
|
||||
@@ -45,22 +58,34 @@ export class MenuActions extends React.Component<MenuActionsProps> {
|
||||
this.isOpen = !this.isOpen;
|
||||
};
|
||||
|
||||
constructor(props: MenuActionsProps) {
|
||||
constructor(props: MenuActionsProps & Dependencies) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
autoBind(this);
|
||||
}
|
||||
|
||||
componentDidMount(): void {
|
||||
disposeOnUnmount(this, [
|
||||
reaction(() => this.isOpen, (isOpen) => {
|
||||
if (isOpen) {
|
||||
this.props.onOpen?.();
|
||||
}
|
||||
}, {
|
||||
fireImmediately: true,
|
||||
}),
|
||||
]);
|
||||
}
|
||||
|
||||
remove() {
|
||||
const { removeAction } = this.props;
|
||||
const { removeAction, openConfirmDialog } = this.props;
|
||||
let { removeConfirmationMessage } = this.props;
|
||||
|
||||
if (typeof removeConfirmationMessage === "function") {
|
||||
removeConfirmationMessage = removeConfirmationMessage();
|
||||
}
|
||||
ConfirmDialog.open({
|
||||
openConfirmDialog({
|
||||
ok: removeAction,
|
||||
labelOk: `Remove`,
|
||||
labelOk: "Remove",
|
||||
message: <div>{removeConfirmationMessage}</div>,
|
||||
});
|
||||
}
|
||||
@@ -83,10 +108,6 @@ export class MenuActions extends React.Component<MenuActionsProps> {
|
||||
...(typeof triggerIcon === "object" ? triggerIcon : {}),
|
||||
};
|
||||
|
||||
if (this.props.onOpen) {
|
||||
iconProps.onClick = this.props.onOpen;
|
||||
}
|
||||
|
||||
if (iconProps.tooltip && this.isOpen) {
|
||||
delete iconProps.tooltip; // don't show tooltip for icon when menu is open
|
||||
}
|
||||
@@ -101,10 +122,6 @@ export class MenuActions extends React.Component<MenuActionsProps> {
|
||||
className, toolbar, autoCloseOnSelect, children, updateAction, removeAction, triggerIcon, removeConfirmationMessage,
|
||||
...menuProps
|
||||
} = this.props;
|
||||
const menuClassName = cssNames("MenuActions flex", className, {
|
||||
toolbar,
|
||||
gaps: toolbar, // add spacing for .flex
|
||||
});
|
||||
const autoClose = !toolbar;
|
||||
|
||||
return (
|
||||
@@ -113,11 +130,17 @@ export class MenuActions extends React.Component<MenuActionsProps> {
|
||||
|
||||
<Menu
|
||||
htmlFor={this.id}
|
||||
isOpen={this.isOpen} open={this.toggle} close={this.toggle}
|
||||
className={menuClassName}
|
||||
isOpen={this.isOpen}
|
||||
open={this.toggle}
|
||||
close={this.toggle}
|
||||
className={cssNames("MenuActions flex", className, {
|
||||
toolbar,
|
||||
gaps: toolbar, // add spacing for .flex
|
||||
})}
|
||||
animated={!toolbar}
|
||||
usePortal={autoClose}
|
||||
closeOnScroll={autoClose}
|
||||
closeOnClickItem={autoCloseOnSelect ?? autoClose }
|
||||
closeOnClickItem={autoCloseOnSelect ?? autoClose}
|
||||
closeOnClickOutside={autoClose}
|
||||
{...menuProps}
|
||||
>
|
||||
@@ -139,3 +162,10 @@ export class MenuActions extends React.Component<MenuActionsProps> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const MenuActions = withInjectables<Dependencies, MenuActionsProps>(NonInjectedMenuActions, {
|
||||
getProps: (di, props) => ({
|
||||
...props,
|
||||
openConfirmDialog: di.inject(openConfirmDialogInjectable),
|
||||
}),
|
||||
});
|
||||
@@ -42,6 +42,7 @@ export interface MenuProps {
|
||||
closeOnScroll?: boolean; // applicable when usePortal={true}
|
||||
position?: MenuPosition; // applicable when usePortal={false}
|
||||
children?: ReactNode;
|
||||
animated?: boolean;
|
||||
toggleEvent?: "click" | "contextmenu";
|
||||
}
|
||||
|
||||
@@ -58,6 +59,7 @@ const defaultPropsMenu: Partial<MenuProps> = {
|
||||
closeOnClickOutside: true,
|
||||
closeOnScroll: false,
|
||||
toggleEvent: "click",
|
||||
animated: true,
|
||||
};
|
||||
|
||||
export class Menu extends React.Component<MenuProps, State> {
|
||||
@@ -297,7 +299,7 @@ export class Menu extends React.Component<MenuProps, State> {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { position, id } = this.props;
|
||||
const { position, id, animated } = this.props;
|
||||
let { className, usePortal } = this.props;
|
||||
|
||||
className = cssNames("Menu", className, this.state.position || position, {
|
||||
@@ -319,28 +321,40 @@ export class Menu extends React.Component<MenuProps, State> {
|
||||
return item;
|
||||
});
|
||||
|
||||
const menu = (
|
||||
<MenuContext.Provider value={this}>
|
||||
let menu = (
|
||||
<ul
|
||||
id={id}
|
||||
ref={this.bindRef}
|
||||
className={className}
|
||||
style={{
|
||||
left: this.state?.menuStyle?.left,
|
||||
top: this.state?.menuStyle?.top,
|
||||
}}
|
||||
onKeyDown={this.onKeyDown}
|
||||
>
|
||||
{menuItems}
|
||||
</ul>
|
||||
);
|
||||
|
||||
if (animated) {
|
||||
menu = (
|
||||
<Animate enter={this.isOpen}>
|
||||
<ul
|
||||
id={id}
|
||||
ref={this.bindRef}
|
||||
className={className}
|
||||
style={{
|
||||
left: this.state?.menuStyle?.left,
|
||||
top: this.state?.menuStyle?.top,
|
||||
}}
|
||||
onKeyDown={this.onKeyDown}
|
||||
>
|
||||
{menuItems}
|
||||
</ul>
|
||||
{menu}
|
||||
</Animate>
|
||||
);
|
||||
}
|
||||
|
||||
menu = (
|
||||
<MenuContext.Provider value={this}>
|
||||
{menu}
|
||||
</MenuContext.Provider>
|
||||
);
|
||||
|
||||
if (usePortal === true) usePortal = document.body;
|
||||
|
||||
return usePortal instanceof HTMLElement ? createPortal(menu, usePortal) : menu;
|
||||
return usePortal instanceof HTMLElement
|
||||
? createPortal(menu, usePortal)
|
||||
: menu;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user