1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Fix <Icon>'s not using tooltip and fix toolbar not being boolean (#3038)

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton 2021-06-23 09:14:59 -04:00 committed by GitHub
parent f8dd7b12f2
commit e49576ee8c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 64 additions and 52 deletions

View File

@ -86,23 +86,26 @@ export function NodeMenu(props: NodeMenuProps) {
return ( return (
<> <>
<MenuItem onClick={shell}> <MenuItem onClick={shell}>
<Icon svg="ssh" interactive={toolbar} title="Node shell"/> <Icon svg="ssh" interactive={toolbar} tooltip={toolbar && "Node shell"}/>
<span className="title">Shell</span> <span className="title">Shell</span>
</MenuItem> </MenuItem>
{!node.isUnschedulable() && ( {
<MenuItem onClick={cordon}> node.isUnschedulable()
<Icon material="pause_circle_filled" title="Cordon" interactive={toolbar}/> ? (
<span className="title">Cordon</span> <MenuItem onClick={unCordon}>
</MenuItem> <Icon material="play_circle_filled" tooltip={toolbar && "Uncordon"} interactive={toolbar} />
)} <span className="title">Uncordon</span>
{node.isUnschedulable() && ( </MenuItem>
<MenuItem onClick={unCordon}> )
<Icon material="play_circle_filled" title="Uncordon" interactive={toolbar}/> : (
<span className="title">Uncordon</span> <MenuItem onClick={cordon}>
</MenuItem> <Icon material="pause_circle_filled" tooltip={toolbar && "Cordon"} interactive={toolbar} />
)} <span className="title">Cordon</span>
</MenuItem>
)
}
<MenuItem onClick={drain}> <MenuItem onClick={drain}>
<Icon material="delete_sweep" title="Drain" interactive={toolbar}/> <Icon material="delete_sweep" tooltip={toolbar && "Drain"} interactive={toolbar}/>
<span className="title">Drain</span> <span className="title">Drain</span>
</MenuItem> </MenuItem>
</> </>

View File

@ -74,7 +74,7 @@ export class PodAttachMenu extends React.Component<PodAttachMenuProps> {
return ( return (
<MenuItem onClick={Util.prevDefault(() => this.attachToPod(containers[0].name))}> <MenuItem onClick={Util.prevDefault(() => this.attachToPod(containers[0].name))}>
<Icon material="pageview" interactive={toolbar} title="Attach to Pod"/> <Icon material="pageview" interactive={toolbar} tooltip={toolbar && "Attach to Pod"}/>
<span className="title">Attach Pod</span> <span className="title">Attach Pod</span>
{containers.length > 1 && ( {containers.length > 1 && (
<> <>

View File

@ -62,7 +62,7 @@ export class PodLogsMenu extends React.Component<PodLogsMenuProps> {
return ( return (
<MenuItem onClick={Util.prevDefault(() => this.showLogs(containers[0]))}> <MenuItem onClick={Util.prevDefault(() => this.showLogs(containers[0]))}>
<Icon material="subject" title="Logs" interactive={toolbar}/> <Icon material="subject" interactive={toolbar} tooltip={toolbar && "Pod Logs"}/>
<span className="title">Logs</span> <span className="title">Logs</span>
{containers.length > 1 && ( {containers.length > 1 && (
<> <>

View File

@ -79,7 +79,7 @@ export class PodShellMenu extends React.Component<PodShellMenuProps> {
return ( return (
<MenuItem onClick={Util.prevDefault(() => this.execShell(containers[0].name))}> <MenuItem onClick={Util.prevDefault(() => this.execShell(containers[0].name))}>
<Icon svg="ssh" interactive={toolbar} title="Pod shell"/> <Icon svg="ssh" interactive={toolbar} tooltip={toolbar && "Pod Shell"} />
<span className="title">Shell</span> <span className="title">Shell</span>
{containers.length > 1 && ( {containers.length > 1 && (
<> <>

View File

@ -41,9 +41,13 @@ describe("Lens cluster pages", () => {
const BACKSPACE = "\uE003"; const BACKSPACE = "\uE003";
let app: Application; let app: Application;
const ready = minikubeReady(TEST_NAMESPACE); const ready = minikubeReady(TEST_NAMESPACE);
let clusterAdded = false;
afterEach(() => {
clusterAdded = false;
});
utils.describeIf(ready)("test common pages", () => { utils.describeIf(ready)("test common pages", () => {
let clusterAdded = false;
const addCluster = async () => { const addCluster = async () => {
await waitForMinikubeDashboard(app); await waitForMinikubeDashboard(app);
await app.client.click('a[href="/nodes"]'); await app.client.click('a[href="/nodes"]');
@ -68,10 +72,9 @@ describe("Lens cluster pages", () => {
}); });
const appStartAddCluster = async () => { const appStartAddCluster = async () => {
if (clusterAdded) { app = await utils.appStart();
app = await utils.appStart(); await addCluster();
await addCluster(); clusterAdded = true;
}
}; };
function getSidebarSelectors(itemId: string) { function getSidebarSelectors(itemId: string) {
@ -408,8 +411,12 @@ describe("Lens cluster pages", () => {
// Open logs tab in dock // Open logs tab in dock
await app.client.click(".list .TableRow:first-child"); await app.client.click(".list .TableRow:first-child");
await app.client.waitForVisible(".Drawer"); await app.client.waitForVisible(".Drawer");
await app.client.waitForVisible(`ul.KubeObjectMenu li.MenuItem i[title="Logs"]`);
await app.client.click("ul.KubeObjectMenu li.MenuItem i[title='Logs']"); const logsButton = "ul.KubeObjectMenu li.MenuItem i.Icon span[data-icon-name='subject']";
await app.client.waitForVisible(logsButton);
await app.client.click(logsButton);
// Check if controls are available // Check if controls are available
await app.client.waitForVisible(".LogList .VirtualList"); await app.client.waitForVisible(".LogList .VirtualList");
await app.client.waitForVisible(".LogResourceSelector"); await app.client.waitForVisible(".LogResourceSelector");

View File

@ -63,7 +63,7 @@ export class HelmReleaseMenu extends React.Component<Props> {
<> <>
{hasRollback && ( {hasRollback && (
<MenuItem onClick={this.rollback}> <MenuItem onClick={this.rollback}>
<Icon material="history" interactive={toolbar} title="Rollback"/> <Icon material="history" interactive={toolbar} tooltip="Rollback"/>
<span className="title">Rollback</span> <span className="title">Rollback</span>
</MenuItem> </MenuItem>
)} )}

View File

@ -91,7 +91,7 @@ export class CatalogEntityDrawerMenu<T extends CatalogEntity> extends React.Comp
items.push( items.push(
<MenuItem key={menuItem.title} onClick={() => this.onMenuItemClick(menuItem)}> <MenuItem key={menuItem.title} onClick={() => this.onMenuItemClick(menuItem)}>
<Icon <Icon
title={menuItem.title} tooltip={menuItem.title}
{...{ [key]: menuItem.icon }} {...{ [key]: menuItem.icon }}
/> />
</MenuItem> </MenuItem>
@ -100,7 +100,7 @@ export class CatalogEntityDrawerMenu<T extends CatalogEntity> extends React.Comp
items.push( items.push(
<MenuItem key="add-to-hotbar" onClick={() => this.addToHotbar(entity) }> <MenuItem key="add-to-hotbar" onClick={() => this.addToHotbar(entity) }>
<Icon material="playlist_add" small title="Add to Hotbar" /> <Icon material="playlist_add" small tooltip="Add to Hotbar" />
</MenuItem> </MenuItem>
); );

View File

@ -93,7 +93,7 @@ export function ServiceAccountMenu(props: KubeObjectMenuProps<ServiceAccount>) {
return ( return (
<MenuItem onClick={() => openServiceAccountKubeConfig(object)}> <MenuItem onClick={() => openServiceAccountKubeConfig(object)}>
<Icon material="insert_drive_file" title="Kubeconfig File" interactive={toolbar} /> <Icon material="insert_drive_file" tooltip="Kubeconfig File" interactive={toolbar} />
<span className="title">Kubeconfig</span> <span className="title">Kubeconfig</span>
</MenuItem> </MenuItem>
); );

View File

@ -107,7 +107,7 @@ export function CronJobMenu(props: KubeObjectMenuProps<CronJob>) {
return ( return (
<> <>
<MenuItem onClick={() => CronJobTriggerDialog.open(object)}> <MenuItem onClick={() => CronJobTriggerDialog.open(object)}>
<Icon material="play_circle_filled" title="Trigger" interactive={toolbar}/> <Icon material="play_circle_filled" tooltip="Trigger" interactive={toolbar}/>
<span className="title">Trigger</span> <span className="title">Trigger</span>
</MenuItem> </MenuItem>
@ -126,7 +126,7 @@ export function CronJobMenu(props: KubeObjectMenuProps<CronJob>) {
Resume CronJob <b>{object.getName()}</b>? Resume CronJob <b>{object.getName()}</b>?
</p>), </p>),
})}> })}>
<Icon material="play_circle_outline" title="Resume" interactive={toolbar}/> <Icon material="play_circle_outline" tooltip="Resume" interactive={toolbar}/>
<span className="title">Resume</span> <span className="title">Resume</span>
</MenuItem> </MenuItem>
@ -144,7 +144,7 @@ export function CronJobMenu(props: KubeObjectMenuProps<CronJob>) {
Suspend CronJob <b>{object.getName()}</b>? Suspend CronJob <b>{object.getName()}</b>?
</p>), </p>),
})}> })}>
<Icon material="pause_circle_filled" title="Suspend" interactive={toolbar}/> <Icon material="pause_circle_filled" tooltip="Suspend" interactive={toolbar}/>
<span className="title">Suspend</span> <span className="title">Suspend</span>
</MenuItem> </MenuItem>
} }

View File

@ -124,7 +124,7 @@ export function DeploymentMenu(props: KubeObjectMenuProps<Deployment>) {
return ( return (
<> <>
<MenuItem onClick={() => DeploymentScaleDialog.open(object)}> <MenuItem onClick={() => DeploymentScaleDialog.open(object)}>
<Icon material="open_with" title="Scale" interactive={toolbar}/> <Icon material="open_with" tooltip="Scale" interactive={toolbar}/>
<span className="title">Scale</span> <span className="title">Scale</span>
</MenuItem> </MenuItem>
<MenuItem onClick={() => ConfirmDialog.open({ <MenuItem onClick={() => ConfirmDialog.open({
@ -146,7 +146,7 @@ export function DeploymentMenu(props: KubeObjectMenuProps<Deployment>) {
</p> </p>
), ),
})}> })}>
<Icon material="autorenew" title="Restart" interactive={toolbar}/> <Icon material="autorenew" tooltip="Restart" interactive={toolbar}/>
<span className="title">Restart</span> <span className="title">Restart</span>
</MenuItem> </MenuItem>
</> </>

View File

@ -98,7 +98,7 @@ export function ReplicaSetMenu(props: KubeObjectMenuProps<ReplicaSet>) {
return ( return (
<> <>
<MenuItem onClick={() => ReplicaSetScaleDialog.open(object)}> <MenuItem onClick={() => ReplicaSetScaleDialog.open(object)}>
<Icon material="open_with" title="Scale" interactive={toolbar}/> <Icon material="open_with" tooltip="Scale" interactive={toolbar}/>
<span className="title">Scale</span> <span className="title">Scale</span>
</MenuItem> </MenuItem>
</> </>

View File

@ -103,7 +103,7 @@ export function StatefulSetMenu(props: KubeObjectMenuProps<StatefulSet>) {
return ( return (
<> <>
<MenuItem onClick={() => StatefulSetScaleDialog.open(object)}> <MenuItem onClick={() => StatefulSetScaleDialog.open(object)}>
<Icon material="open_with" title="Scale" interactive={toolbar}/> <Icon material="open_with" tooltip="Scale" interactive={toolbar}/>
<span className="title">Scale</span> <span className="title">Scale</span>
</MenuItem> </MenuItem>
</> </>

View File

@ -94,7 +94,7 @@ export class DockTab extends React.Component<DockTabProps> {
{!pinned && ( {!pinned && (
<Icon <Icon
small material="close" small material="close"
title="Close (Ctrl+Shift+W)" tooltip="Close (Ctrl+Shift+W)"
onClick={prevDefault(this.close)} onClick={prevDefault(this.close)}
/> />
)} )}

View File

@ -71,15 +71,15 @@ export interface BaseProps {
// the larger number is upper limit, the lower is lower limit // the larger number is upper limit, the lower is lower limit
// the lower limit is capped at 0 and the upper limit is capped at Infinity // the lower limit is capped at 0 and the upper limit is capped at Infinity
limit?: [number, number]; limit?: [number, number];
// default is "Reject" // default is "Reject"
onOverLimit?: OverLimitStyle; onOverLimit?: OverLimitStyle;
// individual files are checked before the total size. // individual files are checked before the total size.
maxSize?: number; maxSize?: number;
// default is "Reject" // default is "Reject"
onOverSizeLimit?: OverSizeLimitStyle; onOverSizeLimit?: OverSizeLimitStyle;
maxTotalSize?: number; maxTotalSize?: number;
// default is "Reject" // default is "Reject"
onOverTotalSizeLimit?: OverTotalSizeLimitStyle; onOverTotalSizeLimit?: OverTotalSizeLimitStyle;
@ -158,7 +158,7 @@ export class FilePicker extends React.Component<Props> {
files = _.orderBy(files, ["size"]); files = _.orderBy(files, ["size"]);
case OverTotalSizeLimitStyle.FILTER_LAST: case OverTotalSizeLimitStyle.FILTER_LAST:
let newTotalSize = totalSize; let newTotalSize = totalSize;
for (;files.length > 0;) { for (;files.length > 0;) {
newTotalSize -= files.pop().size; newTotalSize -= files.pop().size;
@ -180,12 +180,12 @@ export class FilePicker extends React.Component<Props> {
const numberLimitedFiles = this.handleFileCount(files); const numberLimitedFiles = this.handleFileCount(files);
const sizeLimitedFiles = this.handleIndiviualFileSizes(numberLimitedFiles); const sizeLimitedFiles = this.handleIndiviualFileSizes(numberLimitedFiles);
const totalSizeLimitedFiles = this.handleTotalFileSizes(sizeLimitedFiles); const totalSizeLimitedFiles = this.handleTotalFileSizes(sizeLimitedFiles);
if ("uploadDir" in this.props) { if ("uploadDir" in this.props) {
const { uploadDir } = this.props; const { uploadDir } = this.props;
this.status = FileInputStatus.PROCESSING; this.status = FileInputStatus.PROCESSING;
const paths: string[] = []; const paths: string[] = [];
const promises = totalSizeLimitedFiles.map(async file => { const promises = totalSizeLimitedFiles.map(async file => {
const destinationPath = path.join(uploadDir, file.name); const destinationPath = path.join(uploadDir, file.name);
@ -214,9 +214,9 @@ export class FilePicker extends React.Component<Props> {
return <div className="FilePicker"> return <div className="FilePicker">
<label className="flex gaps align-center" htmlFor="file-upload">{label} {this.getIconRight()}</label> <label className="flex gaps align-center" htmlFor="file-upload">{label} {this.getIconRight()}</label>
<input <input
id="file-upload" id="file-upload"
name="FilePicker" name="FilePicker"
type="file" type="file"
accept={accept} accept={accept}
multiple={multiple} multiple={multiple}
@ -230,7 +230,7 @@ export class FilePicker extends React.Component<Props> {
case FileInputStatus.PROCESSING: case FileInputStatus.PROCESSING:
return <Spinner />; return <Spinner />;
case FileInputStatus.ERROR: case FileInputStatus.ERROR:
return <Icon material="error" title={this.errorText}></Icon>; return <Icon material="error" tooltip={this.errorText} />;
default: default:
return null; return null;
} }

View File

@ -122,7 +122,7 @@ export class Icon extends React.PureComponent<IconProps> {
// render as material-icon // render as material-icon
if (material) { if (material) {
iconContent = <span className="icon">{material}</span>; iconContent = <span className="icon" data-icon-name={material}>{material}</span>;
} }
// wrap icon's content passed from decorator // wrap icon's content passed from decorator

View File

@ -83,7 +83,9 @@ export class KubeObjectMenu<T extends KubeObject> extends React.Component<KubeOb
); );
} }
getMenuItems(object: T): React.ReactChild[] { getMenuItems(): React.ReactChild[] {
const { object, toolbar } = this.props;
if (!object) { if (!object) {
return []; return [];
} }
@ -102,7 +104,7 @@ export class KubeObjectMenu<T extends KubeObject> extends React.Component<KubeOb
render() { render() {
const { remove, update, renderRemoveMessage, isEditable, isRemovable } = this; const { remove, update, renderRemoveMessage, isEditable, isRemovable } = this;
const { className, object, editable, removable, ...menuProps } = this.props; const { className, editable, removable, ...menuProps } = this.props;
return ( return (
<MenuActions <MenuActions
@ -112,7 +114,7 @@ export class KubeObjectMenu<T extends KubeObject> extends React.Component<KubeOb
removeConfirmationMessage={renderRemoveMessage} removeConfirmationMessage={renderRemoveMessage}
{...menuProps} {...menuProps}
> >
{this.getMenuItems(object)} {this.getMenuItems()}
</MenuActions> </MenuActions>
); );
} }

View File

@ -137,13 +137,13 @@ export class MenuActions extends React.Component<MenuActionsProps> {
{children} {children}
{updateAction && ( {updateAction && (
<MenuItem onClick={updateAction}> <MenuItem onClick={updateAction}>
<Icon material="edit" interactive={toolbar} title="Edit"/> <Icon material="edit" interactive={toolbar} tooltip="Edit"/>
<span className="title">Edit</span> <span className="title">Edit</span>
</MenuItem> </MenuItem>
)} )}
{removeAction && ( {removeAction && (
<MenuItem onClick={this.remove}> <MenuItem onClick={this.remove}>
<Icon material="delete" interactive={toolbar} title="Delete"/> <Icon material="delete" interactive={toolbar} tooltip="Delete"/>
<span className="title">Remove</span> <span className="title">Remove</span>
</MenuItem> </MenuItem>
)} )}