Removed TableWrapper (#3032)

Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
This commit is contained in:
Alex
2023-09-05 11:06:33 -06:00
committed by GitHub
parent 248215cc77
commit 1dc21b9a21
14 changed files with 65 additions and 1202 deletions

View File

@@ -14,9 +14,8 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import { listModeColumns, rewindModeColumns } from "./ListObjectsHelpers";
import { ItemActions } from "../../../../Common/TableWrapper/TableWrapper";
import React, { useState } from "react";
import { listModeColumns, rewindModeColumns } from "./ListObjectsHelpers";
import makeStyles from "@mui/styles/makeStyles";
import { Theme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles";
@@ -42,7 +41,7 @@ import {
} from "../../../../../../common/SecureComponent/permissions";
import { hasPermission } from "../../../../../../common/SecureComponent";
import { downloadObject } from "../../../../ObjectBrowser/utils";
import { DataTable } from "mds";
import { DataTable, ItemActions } from "mds";
import { BucketObject } from "api/consoleApi";
const useStyles = makeStyles((theme: Theme) =>
@@ -186,7 +185,7 @@ const ListObjectsTable = ({ internalPaths }: IListObjectTable) => {
const tableActions: ItemActions[] = [
{
type: "view",
label: "View",
tooltip: "View",
onClick: openPath,
sendOnlyId: false,
},

View File

@@ -140,25 +140,6 @@ export const checkboxIcons = {
},
};
const radioBasic = {
width: 16,
height: 16,
borderRadius: "100%",
"input:disabled ~ &": {
border: "1px solid #E5E5E5",
},
padding: 1,
};
export const radioIcons = {
radioUnselectedIcon: { ...radioBasic, border: "2px solid #E5E5E5" },
radioSelectedIcon: {
...radioBasic,
border: "2px solid #E5E5E5",
backgroundColor: "#072C4F",
},
};
export const containerForHeader = {
container: {
position: "relative" as const,
@@ -665,13 +646,6 @@ export const inputFieldStyles = {
},
};
export const inlineCheckboxes = {
inlineCheckboxes: {
display: "flex",
justifyContent: "flex-start",
},
};
const commonStateIcon = {
marginRight: 10,
lineHeight: 1,
@@ -933,14 +907,3 @@ export const twoColCssGridLayoutConfig = {
gridAutoFlow: "dense",
},
};
// These classes are meant to be used as React.CSSProperties for TableWrapper
export const TableRowPredefStyles: any = {
deleted: {
color: "#707070",
backgroundColor: "#f1f0f0",
"&.selected": {
color: "#b2b2b2",
},
},
};

View File

@@ -1,161 +0,0 @@
// This file is part of MinIO Console Server
// Copyright (c) 2021 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import React from "react";
import isString from "lodash/isString";
import { Link } from "react-router-dom";
import createStyles from "@mui/styles/createStyles";
import withStyles from "@mui/styles/withStyles";
import { IconButton, Tooltip } from "@mui/material";
import CloudIcon from "./TableActionIcons/CloudIcon";
import ConsoleIcon from "./TableActionIcons/ConsoleIcon";
import DisableIcon from "./TableActionIcons/DisableIcon";
import FormatDriveIcon from "./TableActionIcons/FormatDriveIcon";
import {
DownloadIcon,
EditIcon,
IAMPoliciesIcon,
PreviewIcon,
ShareIcon,
TrashIcon,
} from "mds";
const styles = () =>
createStyles({
spacing: {
margin: "0 8px",
},
buttonDisabled: {
"&.MuiButtonBase-root.Mui-disabled": {
cursor: "not-allowed",
filter: "grayscale(100%)",
opacity: "30%",
},
},
});
interface IActionButton {
label?: string;
type: string | React.ReactNode;
onClick?: (id: string) => any;
to?: string;
valueToSend: any;
selected: boolean;
sendOnlyId?: boolean;
idField: string;
disabled: boolean;
classes: any;
}
const defineIcon = (type: string, selected: boolean) => {
switch (type) {
case "view":
return <PreviewIcon />;
case "edit":
return <EditIcon />;
case "delete":
return <TrashIcon />;
case "description":
return <IAMPoliciesIcon />;
case "share":
return <ShareIcon />;
case "cloud":
return <CloudIcon active={selected} />;
case "console":
return <ConsoleIcon active={selected} />;
case "download":
return <DownloadIcon />;
case "disable":
return <DisableIcon active={selected} />;
case "format":
return <FormatDriveIcon />;
case "preview":
return <PreviewIcon />;
}
return null;
};
const TableActionButton = ({
type,
onClick,
valueToSend,
idField,
selected,
to,
sendOnlyId = false,
disabled = false,
classes,
label,
}: IActionButton) => {
const valueClick = sendOnlyId ? valueToSend[idField] : valueToSend;
const icon = typeof type === "string" ? defineIcon(type, selected) : type;
let buttonElement = (
<IconButton
aria-label={typeof type === "string" ? type : ""}
size={"small"}
className={`${classes.spacing} ${disabled ? classes.buttonDisabled : ""}`}
disabled={disabled}
onClick={
onClick
? (e) => {
e.stopPropagation();
if (!disabled) {
onClick(valueClick);
} else {
e.preventDefault();
}
}
: () => null
}
sx={{
width: "30px",
height: "30px",
}}
>
{icon}
</IconButton>
);
if (label && label !== "") {
buttonElement = <Tooltip title={label}>{buttonElement}</Tooltip>;
}
if (onClick) {
return buttonElement;
}
if (isString(to)) {
if (!disabled) {
return (
<Link
to={`${to}/${valueClick}`}
onClick={(e) => {
e.stopPropagation();
}}
>
{buttonElement}
</Link>
);
}
return buttonElement;
}
return null;
};
export default withStyles(styles)(TableActionButton);

View File

@@ -1,20 +0,0 @@
import React from "react";
import { IIcon, selected, unSelected } from "./common";
const CloudIcon = ({ active = false }: IIcon) => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 24 24"
>
<path
fill={active ? selected : unSelected}
d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96z"
/>
</svg>
);
};
export default CloudIcon;

View File

@@ -1,20 +0,0 @@
import React from "react";
import { IIcon, selected, unSelected } from "./common";
const ConsoleIcon = ({ active = false }: IIcon) => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 24 24"
>
<path
fill={active ? selected : unSelected}
d="M21 3H3c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H3v-3h18v3z"
/>
</svg>
);
};
export default ConsoleIcon;

View File

@@ -1,20 +0,0 @@
import React from "react";
import { IIcon, selected, unSelected } from "./common";
const DescriptionIcon = ({ active = false }: IIcon) => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
viewBox="0 0 24 24"
>
<path
fill={active ? selected : unSelected}
d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm5 11H7v-2h10v2z"
></path>
</svg>
);
};
export default DescriptionIcon;

View File

@@ -1,15 +0,0 @@
import React, { SVGProps } from "react";
const FormatDriveIcon = (props: SVGProps<SVGSVGElement>) => (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
className={`min-icon`}
fill={"currentcolor"}
{...props}
>
<path d="M20 16h2v-2h-2v2zm0-9v5h2V7h-2zM10 4c-4.42 0-8 3.58-8 8s3.58 8 8 8 8-3.58 8-8-3.58-8-8-8zm0 10c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z"></path>
</svg>
);
export default FormatDriveIcon;

View File

@@ -1,6 +0,0 @@
export interface IIcon {
active: boolean;
}
export const unSelected = "#081C42";
export const selected = "#081C42";

View File

@@ -1,821 +0,0 @@
// This file is part of MinIO Console Server
// Copyright (c) 2021 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import React, { Fragment, useState } from "react";
import {
Checkbox,
Grid,
IconButton,
Paper,
Popover,
Typography,
} from "@mui/material";
import { useNavigate } from "react-router-dom";
import { AutoSizer, Column, InfiniteLoader, Table } from "react-virtualized";
import get from "lodash/get";
import isString from "lodash/isString";
import createStyles from "@mui/styles/createStyles";
import withStyles from "@mui/styles/withStyles";
import ViewColumnIcon from "@mui/icons-material/ViewColumn";
import ArrowDropDownIcon from "@mui/icons-material/ArrowDropDown";
import ArrowDropUpIcon from "@mui/icons-material/ArrowDropUp";
import TableActionButton from "./TableActionButton";
import CheckboxWrapper from "../FormComponents/CheckboxWrapper/CheckboxWrapper";
import {
checkboxIcons,
radioIcons,
TableRowPredefStyles,
} from "../FormComponents/common/styleLibrary";
import { Loader, ProgressBar } from "mds";
import TooltipWrapper from "../TooltipWrapper/TooltipWrapper";
//Interfaces for table Items
export interface ItemActions {
label?: string;
type: string | any;
to?: string;
sendOnlyId?: boolean;
disableButtonFunction?: (itemValue: any) => boolean;
showLoaderFunction?: (itemValue: any) => boolean;
onClick?(valueToSend: any): any;
}
interface IColumns {
label: string;
elementKey?: string;
renderFunction?: (input: any) => any;
renderFullObject?: boolean;
globalClass?: any;
rowClass?: any;
width?: number;
headerTextAlign?: string;
contentTextAlign?: string;
enableSort?: boolean;
}
interface IInfiniteScrollConfig {
loadMoreRecords: (indexElements: {
startIndex: number;
stopIndex: number;
}) => Promise<any>;
recordsCount: number;
}
interface ISortConfig {
triggerSort: (val: any) => any;
currentSort: string;
currentDirection: "ASC" | "DESC" | undefined;
}
interface TableWrapperProps {
itemActions?: ItemActions[] | null;
columns: IColumns[];
onSelect?: (e: React.ChangeEvent<HTMLInputElement>) => any;
idField: string;
isLoading: boolean;
loadingMessage?: React.ReactNode;
records: any[];
classes: any;
entityName: string;
selectedItems?: string[];
radioSelection?: boolean;
customEmptyMessage?: string;
customPaperHeight?: string;
noBackground?: boolean;
columnsSelector?: boolean;
textSelectable?: boolean;
columnsShown?: string[];
onColumnChange?: (column: string, state: boolean) => any;
autoScrollToBottom?: boolean;
infiniteScrollConfig?: IInfiniteScrollConfig;
sortConfig?: ISortConfig;
disabled?: boolean;
onSelectAll?: () => void;
rowStyle?: ({
index,
}: {
index: number;
}) => "deleted" | "" | React.CSSProperties;
parentClassName?: string;
tooltip?: any;
}
const borderColor = "#9c9c9c80";
const styles = () =>
createStyles({
paper: {
display: "flex",
overflow: "auto",
flexDirection: "column",
padding: "0 16px 8px",
boxShadow: "none",
border: "#EAEDEE 1px solid",
borderRadius: 3,
minHeight: 200,
overflowY: "scroll",
position: "relative",
"&::-webkit-scrollbar": {
width: 0,
height: 3,
},
},
noBackground: {
backgroundColor: "transparent",
border: 0,
},
disabled: {
backgroundColor: "#fbfafa",
color: "#cccccc",
},
defaultPaperHeight: {
height: "calc(100vh - 205px)",
},
loadingBox: {
paddingTop: "100px",
paddingBottom: "100px",
},
overlayColumnSelection: {
position: "absolute",
right: 0,
top: 0,
},
popoverContent: {
maxHeight: 250,
overflowY: "auto",
padding: "0 10px 10px",
},
shownColumnsLabel: {
color: "#9c9c9c",
fontSize: 12,
padding: 10,
borderBottom: "#eaeaea 1px solid",
width: "100%",
},
checkAllWrapper: {
marginTop: -16,
},
"@global": {
".rowLine": {
borderBottom: `1px solid ${borderColor}`,
height: 40,
fontSize: 14,
transitionDuration: 0.3,
"&:focus": {
outline: "initial",
},
"&:hover:not(.ReactVirtualized__Table__headerRow)": {
userSelect: "none",
backgroundColor: "#ececec",
fontWeight: 600,
"&.canClick": {
cursor: "pointer",
},
"&.canSelectText": {
userSelect: "text",
},
},
"& .selected": {
fontWeight: 600,
},
"&:not(.deleted) .selected": {
color: "#081C42",
},
"&.deleted .selected": {
color: "#C51B3F",
},
},
".headerItem": {
userSelect: "none",
fontWeight: 700,
fontSize: 14,
fontStyle: "initial",
display: "flex",
alignItems: "center",
outline: "none",
},
".ReactVirtualized__Table__row": {
width: "100% !important",
},
".ReactVirtualized__Table__headerRow": {
fontWeight: 700,
fontSize: 14,
borderColor: "#39393980",
textTransform: "initial",
},
".optionsAlignment": {
textAlign: "center",
"& .min-icon": {
width: 16,
height: 16,
},
},
".text-center": {
textAlign: "center",
},
".text-right": {
textAlign: "right",
},
".progress-enabled": {
paddingTop: 3,
display: "inline-block",
margin: "0 10px",
position: "relative",
width: 18,
height: 18,
},
".progress-enabled > .MuiCircularProgress-root": {
position: "absolute",
left: 0,
top: 3,
},
},
...checkboxIcons,
...radioIcons,
});
const selectWidth = 45;
// Function to render elements in table
const subRenderFunction = (
rowData: any,
column: IColumns,
isSelected: boolean,
) => {
const itemElement = isString(rowData)
? rowData
: get(rowData, column.elementKey!, null); // If the element is just a string, we render it as it is
const renderConst = column.renderFullObject ? rowData : itemElement;
const renderElement = column.renderFunction
? column.renderFunction(renderConst)
: renderConst; // If render function is set, we send the value to the function.
return (
<Fragment>
<span className={isSelected ? "selected" : ""}>{renderElement}</span>
</Fragment>
);
};
// Function to calculate common column width for elements with no with size
const calculateColumnRest = (
columns: IColumns[],
containerWidth: number,
actionsWidth: number,
hasSelect: boolean,
hasActions: boolean,
columnsSelector: boolean,
columnsShown: string[],
) => {
let colsItems = [...columns];
if (columnsSelector) {
colsItems = columns.filter((column) =>
columnsShown.includes(column.elementKey!),
);
}
let initialValue = containerWidth;
if (hasSelect) {
initialValue -= selectWidth;
}
if (hasActions) {
initialValue -= actionsWidth;
}
let freeSpacing = colsItems.reduce((total, currValue) => {
return currValue.width ? total - currValue.width : total;
}, initialValue);
return freeSpacing / colsItems.filter((el) => !el.width).length;
};
// Function that renders Columns in table
const generateColumnsMap = (
columns: IColumns[],
containerWidth: number,
actionsWidth: number,
hasSelect: boolean,
hasActions: boolean,
selectedItems: string[],
idField: string,
columnsSelector: boolean,
columnsShown: string[],
sortColumn: string,
sortDirection: "ASC" | "DESC" | undefined,
) => {
const commonRestWidth = calculateColumnRest(
columns,
containerWidth,
actionsWidth,
hasSelect,
hasActions,
columnsSelector,
columnsShown,
);
return columns.map((column: IColumns, index: number) => {
if (columnsSelector && !columnsShown.includes(column.elementKey!)) {
return null;
}
const disableSort = column.enableSort ? !column.enableSort : true;
return (
// @ts-ignore
<Column
key={`col-tb-${index.toString()}`}
dataKey={column.elementKey!}
headerClassName={`titleHeader ${
column.headerTextAlign ? `text-${column.headerTextAlign}` : ""
}`}
headerRenderer={() => (
<Fragment>
{sortColumn === column.elementKey && (
<Fragment>
{sortDirection === "ASC" ? (
<ArrowDropUpIcon />
) : (
<ArrowDropDownIcon />
)}
</Fragment>
)}
{column.label}
</Fragment>
)}
className={
column.contentTextAlign ? `text-${column.contentTextAlign}` : ""
}
cellRenderer={({ rowData }) => {
const isSelected = selectedItems
? selectedItems.includes(
isString(rowData) ? rowData : rowData[idField],
)
: false;
return subRenderFunction(rowData, column, isSelected);
}}
width={column.width || commonRestWidth}
disableSort={disableSort}
defaultSortDirection={"ASC"}
/>
);
});
};
// Function to render the action buttons
const elementActions = (
actions: ItemActions[],
valueToSend: any,
selected: boolean,
idField: string,
) => {
return actions.map((action: ItemActions, index: number) => {
if (action.type === "view") {
return null;
}
const vlSend =
typeof valueToSend === "string" ? valueToSend : valueToSend[idField];
let disabled = false;
if (action.disableButtonFunction) {
if (action.disableButtonFunction(vlSend)) {
disabled = true;
}
}
if (action.showLoaderFunction) {
if (action.showLoaderFunction(vlSend)) {
return (
<div className={"progress-enabled"}>
<Loader
style={{ width: 18, height: 18 }}
key={`actions-loader-${action.type}-${index.toString()}`}
/>
</div>
);
}
}
return (
<TableActionButton
label={action.label}
type={action.type}
onClick={action.onClick}
to={action.to}
valueToSend={valueToSend}
selected={selected}
key={`actions-${action.type}-${index.toString()}`}
idField={idField}
sendOnlyId={!!action.sendOnlyId}
disabled={disabled}
/>
);
});
};
// Function to calculate the options column width according elements inside
const calculateOptionsSize = (containerWidth: number, totalOptions: number) => {
const minContainerSize = 80;
const sizeOptions = totalOptions * 45 + 15;
if (sizeOptions < minContainerSize) {
return minContainerSize;
}
if (sizeOptions > containerWidth) {
return containerWidth;
}
return sizeOptions;
};
// Main function to render the Table Wrapper
const TableWrapper = ({
itemActions,
columns,
onSelect,
records,
isLoading,
loadingMessage = <Typography component="h3">Loading...</Typography>,
entityName,
selectedItems,
idField,
classes,
radioSelection = false,
customEmptyMessage = "",
customPaperHeight = "",
noBackground = false,
columnsSelector = false,
textSelectable = false,
columnsShown = [],
onColumnChange = (column: string, state: boolean) => {},
infiniteScrollConfig,
sortConfig,
autoScrollToBottom = false,
disabled = false,
onSelectAll,
rowStyle,
parentClassName = "",
tooltip,
}: TableWrapperProps) => {
const navigate = useNavigate();
const [columnSelectorOpen, setColumnSelectorOpen] = useState<boolean>(false);
const [anchorEl, setAnchorEl] = React.useState<any>(null);
const findView = itemActions
? itemActions.find((el) => el.type === "view")
: null;
const clickAction = (rowItem: any) => {
if (findView) {
const valueClick = findView.sendOnlyId ? rowItem[idField] : rowItem;
let disabled = false;
if (findView.disableButtonFunction) {
if (findView.disableButtonFunction(valueClick)) {
disabled = true;
}
}
if (findView.to && !disabled) {
navigate(`${findView.to}/${valueClick}`);
return;
}
if (findView.onClick && !disabled) {
findView.onClick(valueClick);
}
}
};
const openColumnsSelector = (event: { currentTarget: any }) => {
setColumnSelectorOpen(!columnSelectorOpen);
setAnchorEl(event.currentTarget);
};
const closeColumnSelector = () => {
setColumnSelectorOpen(false);
setAnchorEl(null);
};
const columnsSelection = (columns: IColumns[]) => {
return (
<Fragment>
<IconButton
aria-describedby={"columnsSelector"}
color="primary"
onClick={openColumnsSelector}
size="large"
>
<ViewColumnIcon fontSize="inherit" />
</IconButton>
<Popover
anchorEl={anchorEl}
id={"columnsSelector"}
open={columnSelectorOpen}
anchorOrigin={{
vertical: "bottom",
horizontal: "left",
}}
transformOrigin={{
vertical: "top",
horizontal: "left",
}}
onClose={closeColumnSelector}
>
<div className={classes.shownColumnsLabel}>Shown Columns</div>
<div className={classes.popoverContent}>
{columns.map((column: IColumns) => {
return (
<CheckboxWrapper
key={`tableColumns-${column.label}`}
label={column.label}
checked={columnsShown.includes(column.elementKey!)}
onChange={(e) => {
onColumnChange(column.elementKey!, e.target.checked);
}}
id={`chbox-${column.label}`}
name={`chbox-${column.label}`}
value={column.label}
/>
);
})}
</div>
</Popover>
</Fragment>
);
};
return (
<Grid item xs={12} className={parentClassName}>
<TooltipWrapper tooltip={tooltip ? tooltip : ""}>
<Paper
style={{ overflow: "hidden" }}
className={`${classes.paper} ${
noBackground ? classes.noBackground : ""
}
${disabled ? classes.disabled : ""}
${
customPaperHeight !== ""
? customPaperHeight
: classes.defaultPaperHeight
}`}
>
{isLoading && (
<Grid container className={classes.loadingBox}>
<Grid item xs={12} style={{ textAlign: "center" }}>
{loadingMessage}
</Grid>
<Grid item xs={12}>
<ProgressBar />
</Grid>
</Grid>
)}
{columnsSelector && !isLoading && records.length > 0 && (
<div className={classes.overlayColumnSelection}>
{columnsSelection(columns)}
</div>
)}
{records && !isLoading && records.length > 0 ? (
// @ts-ignore
<InfiniteLoader
isRowLoaded={({ index }) => !!records[index]}
loadMoreRows={
infiniteScrollConfig
? infiniteScrollConfig.loadMoreRecords
: () => new Promise(() => true)
}
rowCount={
infiniteScrollConfig
? infiniteScrollConfig.recordsCount
: records.length
}
>
{({ onRowsRendered, registerChild }) => (
// @ts-ignore
<AutoSizer>
{({ width, height }: any) => {
const optionsWidth = calculateOptionsSize(
width,
itemActions
? itemActions.filter((el) => el.type !== "view").length
: 0,
);
const hasSelect: boolean = !!(onSelect && selectedItems);
const hasOptions: boolean = !!(
(itemActions && itemActions.length > 1) ||
(itemActions &&
itemActions.length === 1 &&
itemActions[0].type !== "view")
);
return (
// @ts-ignore
<Table
ref={registerChild}
disableHeader={false}
headerClassName={"headerItem"}
headerHeight={40}
height={height + 8}
noRowsRenderer={() => (
<Fragment>
{customEmptyMessage !== ""
? customEmptyMessage
: `There are no ${entityName} yet.`}
</Fragment>
)}
overscanRowCount={10}
rowHeight={40}
width={width}
rowCount={records.length}
rowGetter={({ index }) => records[index]}
onRowClick={({ rowData }) => {
clickAction(rowData);
}}
rowClassName={(r) =>
`rowLine ${findView ? "canClick" : ""} ${
!findView && textSelectable ? "canSelectText" : ""
} ${rowStyle ? rowStyle(r) : ""}`
}
onRowsRendered={onRowsRendered}
sort={sortConfig ? sortConfig.triggerSort : undefined}
sortBy={sortConfig ? sortConfig.currentSort : undefined}
sortDirection={
sortConfig ? sortConfig.currentDirection : undefined
}
scrollToIndex={
autoScrollToBottom ? records.length - 1 : -1
}
rowStyle={(r) => {
if (rowStyle) {
const returnElement = rowStyle(r);
if (typeof returnElement === "string") {
return get(
TableRowPredefStyles,
returnElement,
{},
);
}
return returnElement;
}
return {};
}}
>
{hasSelect && (
// @ts-ignore
<Column
headerRenderer={() => (
<Fragment>
{onSelectAll ? (
<div className={classes.checkAllWrapper}>
<CheckboxWrapper
label={""}
onChange={onSelectAll}
value="all"
id={"selectAll"}
name={"selectAll"}
checked={
selectedItems?.length === records.length
}
/>
</div>
) : (
<Fragment>Select</Fragment>
)}
</Fragment>
)}
dataKey={`select-${idField}`}
width={selectWidth}
disableSort
cellRenderer={({ rowData }) => {
const isSelected = selectedItems
? selectedItems.includes(
isString(rowData)
? rowData
: rowData[idField],
)
: false;
return (
<Checkbox
value={
isString(rowData)
? rowData
: rowData[idField]
}
color="primary"
inputProps={{
"aria-label": "secondary checkbox",
}}
className="TableCheckbox"
checked={isSelected}
onChange={onSelect}
onClick={(e) => {
e.stopPropagation();
}}
checkedIcon={
<span
className={
radioSelection
? classes.radioSelectedIcon
: classes.checkedIcon
}
/>
}
icon={
<span
className={
radioSelection
? classes.radioUnselectedIcon
: classes.unCheckedIcon
}
/>
}
/>
);
}}
/>
)}
{generateColumnsMap(
columns,
width,
optionsWidth,
hasSelect,
hasOptions,
selectedItems || [],
idField,
columnsSelector,
columnsShown,
sortConfig ? sortConfig.currentSort : "",
sortConfig ? sortConfig.currentDirection : undefined,
)}
{hasOptions && (
// @ts-ignore
<Column
dataKey={idField}
width={optionsWidth}
headerClassName="optionsAlignment"
className="optionsAlignment"
cellRenderer={({ rowData }) => {
const isSelected = selectedItems
? selectedItems.includes(
isString(rowData)
? rowData
: rowData[idField],
)
: false;
return elementActions(
itemActions || [],
rowData,
isSelected,
idField,
);
}}
/>
)}
</Table>
);
}}
</AutoSizer>
)}
</InfiniteLoader>
) : (
<Fragment>
{!isLoading && (
<div id={"empty-results"}>
{customEmptyMessage !== ""
? customEmptyMessage
: `There are no ${entityName} yet.`}
</div>
)}
</Fragment>
)}
</Paper>
</TooltipWrapper>
</Grid>
);
};
export default withStyles(styles)(TableWrapper);

View File

@@ -15,16 +15,14 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import React, { Fragment, useEffect } from "react";
import Grid from "@mui/material/Grid";
import { BackLink, Grid } from "mds";
import { useNavigate } from "react-router-dom";
import { IAM_PAGES } from "../../../common/SecureComponent/permissions";
import { ErrorResponseHandler } from "../../../common/types";
import { setErrorSnackMessage, setHelpName } from "../../../systemSlice";
import { useNavigate } from "react-router-dom";
import { useAppDispatch } from "../../../store";
import AddKeyForm from "./AddKeyForm";
import PageHeaderWrapper from "../Common/PageHeaderWrapper/PageHeaderWrapper";
import { BackLink } from "mds";
import HelpMenu from "../HelpMenu";
const AddKey = () => {

View File

@@ -15,14 +15,12 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import React, { useState } from "react";
import { Box } from "@mui/material";
import Grid from "@mui/material/Grid";
import { AddAccessRuleIcon, Button, FormLayout, PageLayout } from "mds";
import { AddAccessRuleIcon, Button, FormLayout, PageLayout, Grid } from "mds";
import InputBoxWrapper from "../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
import { ErrorResponseHandler } from "../../../common/types";
import useApi from "../Common/Hooks/useApi";
import KMSHelpBox from "./KMSHelpbox";
import { modalStyleUtils } from "../Common/FormComponents/common/styleLibrary";
interface IAddKeyFormProps {
onSuccess: () => void;
@@ -71,7 +69,7 @@ const AddKeyForm = ({ onSuccess, onError }: IAddKeyFormProps) => {
addRecord(e);
}}
>
<Grid container item spacing={1}>
<Grid container>
<Grid item xs={12}>
<InputBoxWrapper
id="key-name"
@@ -85,33 +83,23 @@ const AddKeyForm = ({ onSuccess, onError }: IAddKeyFormProps) => {
}}
/>
</Grid>
<Grid item xs={12} textAlign={"right"}>
<Box
sx={{
display: "flex",
alignItems: "center",
justifyContent: "flex-end",
marginTop: "20px",
gap: "15px",
}}
>
<Button
id={"clear"}
type="button"
variant="regular"
onClick={resetForm}
label={"Clear"}
/>
<Grid item xs={12} sx={modalStyleUtils.modalButtonBar}>
<Button
id={"clear"}
type="button"
variant="regular"
onClick={resetForm}
label={"Clear"}
/>
<Button
id={"save-key"}
type="submit"
variant="callAction"
color="primary"
disabled={loading || !validSave}
label={"Save"}
/>
</Box>
<Button
id={"save-key"}
type="submit"
variant="callAction"
color="primary"
disabled={loading || !validSave}
label={"Save"}
/>
</Grid>
</Grid>
</form>

View File

@@ -14,9 +14,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import React, { useState } from "react";
import { DialogContentText, Grid } from "@mui/material";
import React, { useState, Fragment } from "react";
import { ErrorResponseHandler } from "../../../common/types";
import useApi from "../Common/Hooks/useApi";
import ConfirmDialog from "../Common/ModalWrapper/ConfirmDialog";
@@ -24,7 +22,7 @@ import { setErrorSnackMessage } from "../../../systemSlice";
import { useAppDispatch } from "../../../store";
import WarningMessage from "../Common/WarningMessage/WarningMessage";
import InputBoxWrapper from "../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
import { ConfirmDeleteIcon } from "mds";
import { ConfirmDeleteIcon, Grid } from "mds";
interface IDeleteKMSModalProps {
closeDeleteModalAndRefresh: (refresh: boolean) => void;
@@ -71,7 +69,7 @@ const DeleteKMSModal = ({
disabled: retypeKey !== selectedItem || deleteLoading,
}}
confirmationContent={
<DialogContentText>
<Fragment>
<Grid item xs={12}>
<WarningMessage
title={"WARNING"}
@@ -93,7 +91,7 @@ const DeleteKMSModal = ({
value={retypeKey}
/>
</Grid>
</DialogContentText>
</Fragment>
}
/>
);

View File

@@ -15,14 +15,12 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import React, { Fragment, useEffect, useState } from "react";
import { Box } from "@mui/material";
import Grid from "@mui/material/Grid";
import {
AddAccessRuleIcon,
BackLink,
Button,
FormLayout,
Grid,
PageLayout,
} from "mds";
import InputBoxWrapper from "../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
@@ -36,6 +34,7 @@ import KMSHelpBox from "./KMSHelpbox";
import CodeMirrorWrapper from "../Common/FormComponents/CodeMirrorWrapper/CodeMirrorWrapper";
import PageHeaderWrapper from "../Common/PageHeaderWrapper/PageHeaderWrapper";
import HelpMenu from "../HelpMenu";
import { modalStyleUtils } from "../Common/FormComponents/common/styleLibrary";
export const emptyContent = '{\n "bytes": ""\n}';
@@ -108,7 +107,7 @@ const ImportKey = () => {
importRecord(e);
}}
>
<Grid container item spacing={1}>
<Grid container>
<Grid item xs={12}>
<InputBoxWrapper
id="key-name"
@@ -132,33 +131,23 @@ const ImportKey = () => {
editorHeight={"350px"}
/>
</Grid>
<Grid item xs={12} textAlign={"right"}>
<Box
sx={{
display: "flex",
alignItems: "center",
justifyContent: "flex-end",
marginTop: "20px",
gap: "15px",
}}
>
<Button
id={"clear"}
type="button"
variant="regular"
onClick={resetForm}
label={"Clear"}
/>
<Grid item xs={12} sx={modalStyleUtils.modalButtonBar}>
<Button
id={"clear"}
type="button"
variant="regular"
onClick={resetForm}
label={"Clear"}
/>
<Button
id={"import-key"}
type="submit"
variant="callAction"
color="primary"
disabled={loading || !validSave}
label={"Import"}
/>
</Box>
<Button
id={"import-key"}
type="submit"
variant="callAction"
color="primary"
disabled={loading || !validSave}
label={"Import"}
/>
</Grid>
</Grid>
</form>

View File

@@ -14,10 +14,16 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import { Grid, Theme } from "@mui/material";
import { createStyles, withStyles } from "@mui/styles";
import { AddIcon, Button, PageLayout, RefreshIcon, UploadIcon } from "mds";
import React, { useEffect, useState } from "react";
import {
AddIcon,
Button,
DataTable,
Grid,
PageLayout,
RefreshIcon,
UploadIcon,
} from "mds";
import { useNavigate } from "react-router-dom";
import api from "../../../common/api";
import {
@@ -33,12 +39,7 @@ import { ErrorResponseHandler } from "../../../common/types";
import { useAppDispatch } from "../../../store";
import { setErrorSnackMessage, setHelpName } from "../../../systemSlice";
import withSuspense from "../Common/Components/withSuspense";
import {
containerForHeader,
searchField,
} from "../Common/FormComponents/common/styleLibrary";
import SearchBox from "../Common/SearchBox";
import TableWrapper from "../Common/TableWrapper/TableWrapper";
import TooltipWrapper from "../Common/TooltipWrapper/TooltipWrapper";
import PageHeaderWrapper from "../Common/PageHeaderWrapper/PageHeaderWrapper";
import HelpMenu from "../HelpMenu";
@@ -47,17 +48,7 @@ const DeleteKMSModal = withSuspense(
React.lazy(() => import("./DeleteKMSModal")),
);
const styles = (theme: Theme) =>
createStyles({
...searchField,
...containerForHeader,
});
interface IKeysProps {
classes: any;
}
const ListKeys = ({ classes }: IKeysProps) => {
const ListKeys = () => {
const dispatch = useAppDispatch();
const navigate = useNavigate();
@@ -149,15 +140,15 @@ const ListKeys = ({ classes }: IKeysProps) => {
actions={<HelpMenu />}
/>
<PageLayout className={classes.pageContainer}>
<Grid container spacing={1}>
<PageLayout>
<Grid container>
<Grid
item
xs={12}
display={"flex"}
alignItems={"center"}
justifyContent={"flex-end"}
sx={{
display: "flex",
alignItems: "center",
justifyContent: "flex-end",
"& button": {
marginLeft: "8px",
},
@@ -221,13 +212,13 @@ const ListKeys = ({ classes }: IKeysProps) => {
</TooltipWrapper>
</SecureComponent>
</Grid>
<Grid item xs={12} className={classes.tableBlock}>
<Grid item xs={12}>
<SecureComponent
scopes={[IAM_SCOPES.KMS_LIST_KEYS]}
resource={CONSOLE_UI_RESOURCE}
errorProps={{ disabled: true }}
>
<TableWrapper
<DataTable
itemActions={tableActions}
columns={[
{ label: "Name", elementKey: "name" },
@@ -247,4 +238,4 @@ const ListKeys = ({ classes }: IKeysProps) => {
);
};
export default withStyles(styles)(ListKeys);
export default ListKeys;