Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

frontend: refactor row action menus #2621

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion frontend/src/components/common/Resource/EditButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export default function EditButton(props: EditButtonProps) {
}

if (isReadOnly) {
return <ViewButton item={item} />;
return <ViewButton item={item} buttonStyle={buttonStyle} />;
}

return (
Expand Down
58 changes: 7 additions & 51 deletions frontend/src/components/common/Resource/ResourceTable.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { MenuItem, TableCellProps } from '@mui/material';
import { TableCellProps } from '@mui/material';

Check warning on line 1 in frontend/src/components/common/Resource/ResourceTable.tsx

View workflow job for this annotation

GitHub Actions / lint (20.x, ubuntu-22.04)

Run autofix to sort these imports!
import { useTheme } from '@mui/material/styles';
import { MRT_FilterFns, MRT_Row, MRT_SortingFn } from 'material-react-table';
import { ComponentProps, ReactNode, useEffect, useMemo, useRef, useState } from 'react';
Expand All @@ -9,20 +9,16 @@
import { KubeObject } from '../../../lib/k8s/KubeObject';
import { KubeObjectClass } from '../../../lib/k8s/KubeObject';
import { useFilterFunc } from '../../../lib/util';
import { DefaultHeaderAction, RowAction } from '../../../redux/actionButtonsSlice';
import { useNamespaces } from '../../../redux/filterSlice';
import { HeaderAction } from '../../../redux/actionButtonsSlice';
import { HeadlampEventType, useEventCallback } from '../../../redux/headlampEventSlice';
import { useTypedSelector } from '../../../redux/reducers/reducers';
import { useSettings } from '../../App/Settings/hook';
import { ClusterGroupErrorMessage } from '../../cluster/ClusterGroupErrorMessage';
import { DateLabel } from '../Label';
import Link from '../Link';
import Table, { TableColumn } from '../Table';
import DeleteButton from './DeleteButton';
import EditButton from './EditButton';
import { RestartButton } from './RestartButton';
import ScaleButton from './ScaleButton';
import ViewButton from './ViewButton';
import generateRowActionsMenu from './ResourceTableSingleActions';

export type ResourceTableColumn<RowItem> = {
/** Unique id for the column, not required but recommended */
Expand Down Expand Up @@ -84,7 +80,7 @@
columns: (ResourceTableColumn<RowItem> | ColumnType)[];
/** Show or hide row actions @default false*/
enableRowActions?: boolean;
actions?: null | RowAction[];
actions?: null | HeaderAction[];
Comment on lines -87 to +83
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to leave this with the previous type because plugins may be using it and it would mean a type break for them.

/** Provide a list of columns that won't be shown and cannot be turned on */
hideColumns?: string[] | null;
/** ID for the table. Will be used by plugins to identify this table.
Expand Down Expand Up @@ -412,52 +408,12 @@
tableSettings,
]);

const defaultActions: RowAction[] = [
{
id: DefaultHeaderAction.RESTART,
action: ({ item }) => <RestartButton item={item} buttonStyle="menu" />,
},
{
id: DefaultHeaderAction.SCALE,
action: ({ item }) => <ScaleButton item={item} buttonStyle="menu" />,
},
{
id: DefaultHeaderAction.EDIT,
action: ({ item, closeMenu }) => (
<EditButton item={item} buttonStyle="menu" afterConfirm={closeMenu} />
),
},
{
id: DefaultHeaderAction.VIEW,
action: ({ item }) => <ViewButton item={item} buttonStyle="menu" />,
},
{
id: DefaultHeaderAction.DELETE,
action: ({ item, closeMenu }) => (
<DeleteButton item={item} buttonStyle="menu" afterConfirm={closeMenu} />
),
},
];
let hAccs: RowAction[] = [];
if (actions !== undefined && actions !== null) {
hAccs = actions;
}

const actionsProcessed: RowAction[] = [...hAccs, ...defaultActions];

const renderRowActionMenuItems = useMemo(() => {
if (actionsProcessed.length === 0) {
if (!enableRowActions) {
return null;
}
return ({ closeMenu, row }: { closeMenu: () => void; row: MRT_Row<Record<string, any>> }) => {
return actionsProcessed.map(action => {
if (action.action === undefined || action.action === null) {
return <MenuItem />;
}
return action.action({ item: row.original, closeMenu });
});
};
}, [actionsProcessed]);
return generateRowActionsMenu(actions);
}, [actions, enableRowActions]);

function onColumnsVisibilityChange(updater: any): void {
setColumnVisibility(oldCols => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { MenuItem } from '@mui/material';
import { MRT_Row } from 'material-react-table';
import { DefaultHeaderAction, HeaderAction } from '../../../redux/actionButtonsSlice';
import { ButtonStyle } from '../ActionButton/ActionButton';
import DeleteButton from './DeleteButton';
import EditButton from './EditButton';
import { RestartButton } from './RestartButton';
import ScaleButton from './ScaleButton';

export function generateActions(actions: HeaderAction[], buttonStyle: ButtonStyle): HeaderAction[] {
const defaultActions: HeaderAction[] = [
{
id: DefaultHeaderAction.RESTART,
action: ({ item }) => <RestartButton item={item} buttonStyle={buttonStyle} />,
},
{
id: DefaultHeaderAction.SCALE,
action: ({ item }) => <ScaleButton item={item} buttonStyle={buttonStyle} />,
},
{
id: DefaultHeaderAction.EDIT,
action: ({ item, closeMenu }) => (
<EditButton item={item} buttonStyle={buttonStyle} afterConfirm={closeMenu} />
),
},
{
id: DefaultHeaderAction.DELETE,
action: ({ item, closeMenu }) => (
<DeleteButton item={item} buttonStyle={buttonStyle} afterConfirm={closeMenu} />
),
},
];
let hAccs: HeaderAction[] = [];
if (actions !== undefined && actions !== null) {
hAccs = actions;
}

const actionsProcessed: HeaderAction[] = [...hAccs, ...defaultActions];
return actionsProcessed;
}

export default function generateRowActionsMenu(actions: HeaderAction[] | null | undefined) {
const actionsProcessed = generateActions(actions || [], 'menu');
if (actionsProcessed.length === 0) {
return null;
}
return ({ closeMenu, row }: { closeMenu: () => void; row: MRT_Row<Record<string, any>> }) => {
return actionsProcessed.map(action => {
if (action.action === undefined || action.action === null) {
return <MenuItem />;
}
if (typeof action.action === 'function') {
return action.action({ item: row.original, closeMenu });
}
return action.action;
});
};
}
6 changes: 0 additions & 6 deletions frontend/src/redux/actionButtonsSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,12 @@ export type HeaderActionType = ((...args: any[]) => ReactNode) | null | ReactEle
export type DetailsViewFunc = HeaderActionType;

export type AppBarActionType = ((...args: any[]) => ReactNode) | null | ReactElement | ReactNode;
export type RowActionType = ((item: any) => JSX.Element | null | ReactNode) | null;

export type HeaderAction = {
id: string;
action?: HeaderActionType;
};

export type RowAction = {
id: string;
action?: RowActionType;
};

export type AppBarAction = {
id: string;
action?: AppBarActionType;
Expand Down
Loading