Compare commits

..

8 Commits

Author SHA1 Message Date
Minio Trusted
419e94ccec update to v0.4.5 2020-11-13 11:10:13 -08:00
Alex
12bc5265b8 Fixed issue with object browser icons & long names (#389)
Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
Co-authored-by: Daniel Valdivia <hola@danielvaldivia.com>
2020-11-12 14:33:56 -08:00
Kaan Kabalak
32898f0c57 Edit Searchbar styling based on mockups (#385)
Co-authored-by: Daniel Valdivia <hola@danielvaldivia.com>
2020-11-12 12:05:40 -08:00
Kaan Kabalak
125c9abf56 Adjust Modal form clear button font based on mockups (#384)
The font of the clear button for Modal forms were 'sans-serif' instead
of being 'Lato' as specified in the mockups.

Co-authored-by: Daniel Valdivia <hola@danielvaldivia.com>
2020-11-12 10:28:49 -08:00
Alex
bc27db4a69 Migrated tablewrapper to use react-virtualized (#387)
Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
2020-11-11 20:14:48 -08:00
Kaan Kabalak
dd8e2b13d3 Add disabled functionality and fix styling for RadioGroupSelector (#383)
* Adjust RadioGroupSelector label styling based on mockups

* Add disabled support for Radio Group Selector options
2020-11-10 18:59:21 -08:00
Alex
005e3b941c Fixed issue with checkbox selection in table wrapper (#380)
Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
2020-11-10 00:08:45 -08:00
Alex
efa614c773 Fixed default value for nulls in browse buckets (#379)
Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
2020-11-06 16:47:07 -08:00
28 changed files with 423 additions and 380 deletions

View File

@@ -15,7 +15,7 @@ spec:
serviceAccountName: console-sa
containers:
- name: console
image: minio/console:v0.4.4
image: minio/console:v0.4.5
imagePullPolicy: "IfNotPresent"
args:
- server

View File

@@ -15,7 +15,7 @@ spec:
serviceAccountName: console-sa
containers:
- name: console
image: minio/console:v0.4.4
image: minio/console:v0.4.5
imagePullPolicy: "IfNotPresent"
env:
- name: CONSOLE_OPERATOR_MODE

View File

@@ -17,6 +17,7 @@
"@types/react-redux": "^7.1.5",
"@types/react-router": "^5.1.3",
"@types/react-router-dom": "^5.1.2",
"@types/react-virtualized": "^9.21.10",
"@types/recharts": "^1.8.9",
"@types/superagent": "^4.1.4",
"@types/webpack-env": "^1.14.1",
@@ -40,6 +41,8 @@
"react-redux": "^7.1.3",
"react-router-dom": "^5.1.2",
"react-scripts": "3.4.4",
"react-virtualized": "^9.22.2",
"react-window-infinite-loader": "^1.0.5",
"recharts": "^1.8.5",
"redux": "^4.0.4",
"redux-thunk": "^2.3.0",

View File

@@ -21,6 +21,7 @@ import Routes from "./Routes";
import configureStore from "./store";
import * as serviceWorker from "./serviceWorker";
import { ThemeProvider, withStyles } from "@material-ui/core/styles";
import "react-virtualized/styles.css";
import "./index.css";
import theme from "./theme/main";

View File

@@ -197,7 +197,7 @@ const ListBuckets = ({
}
});
const showInPage = filteredRecords.slice(offset, offset + rowsPerPage);
const showInPage = filteredRecords;
return (
<React.Fragment>
@@ -266,26 +266,14 @@ const ListBuckets = ({
label: "Size",
elementKey: "size",
renderFunction: niceBytes,
width: 60,
contentTextAlign: "right",
},
]}
isLoading={loading}
records={showInPage}
entityName="Buckets"
idField="name"
paginatorConfig={{
rowsPerPageOptions: [5, 10, 25],
colSpan: 3,
count: filteredRecords.length,
rowsPerPage: rowsPerPage,
page: page,
SelectProps: {
inputProps: { "aria-label": "rows per page" },
native: true,
},
onChangePage: handleChangePage,
onChangeRowsPerPage: handleChangeRowsPerPage,
ActionsComponent: MinTablePaginationActions,
}}
/>
</Grid>
</Grid>

View File

@@ -16,7 +16,7 @@
import React, { useState } from "react";
import ModalWrapper from "../../../../Common/ModalWrapper/ModalWrapper";
import { Button, Grid, LinearProgress } from "@material-ui/core";
import { Button, Grid } from "@material-ui/core";
import InputBoxWrapper from "../../../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
import { createStyles, Theme, withStyles } from "@material-ui/core/styles";
import { modalBasic } from "../../../../Common/FormComponents/common/styleLibrary";

View File

@@ -46,13 +46,13 @@ import { addRoute, setAllRoutes } from "../../../../ObjectBrowser/actions";
import { connect } from "react-redux";
import { ObjectBrowserState, Route } from "../../../../ObjectBrowser/reducers";
import CreateFolderModal from "./CreateFolderModal";
import { create } from "domain";
import UploadFile from "../../../../../../icons/UploadFile";
const commonIcon = {
backgroundRepeat: "no-repeat",
backgroundPosition: "center center",
width: 16,
minWidth: 16,
height: 40,
marginRight: 10,
};
@@ -91,6 +91,11 @@ const styles = (theme: Theme) =>
display: "flex",
alignItems: "center",
},
fileNameText: {
whiteSpace: "nowrap",
overflow: "hidden",
textOverflow: "ellipsis",
},
iconFolder: {
backgroundImage: "url(/images/ob_folder_clear.svg)",
...commonIcon,
@@ -104,11 +109,14 @@ const styles = (theme: Theme) =>
marginLeft: 10,
},
},
browsePaper: {
height: "calc(100vh - 280px)",
},
"@global": {
".rowElementRaw:hover .iconFileElm": {
".rowLine:hover .iconFileElm": {
backgroundImage: "url(/images/ob_file_filled.svg)",
},
".rowElementRaw:hover .iconFolderElm": {
".rowLine:hover .iconFolderElm": {
backgroundImage: "url(/images/ob_folder_filled.svg)",
},
},
@@ -372,7 +380,9 @@ const ListObjects = ({
return (
<div className={classes.fileName}>
<div className={icon} />
<span>{splitItem[splitItem.length - 1]}</span>
<span className={classes.fileNameText}>
{splitItem[splitItem.length - 1]}
</span>
</div>
);
};
@@ -486,12 +496,15 @@ const ListObjects = ({
label: "Size",
elementKey: "size",
renderFunction: niceBytes,
width: 60,
contentTextAlign: "right",
},
]}
isLoading={loading}
entityName="Objects"
idField="name"
records={filteredRecords}
customPaperHeight={classes.browsePaper}
/>
</Grid>
</Grid>

View File

@@ -642,20 +642,6 @@ class ViewBucket extends React.Component<IViewBucketProps, IViewBucketState> {
records={filteredRecords}
entityName="Events"
idField="id"
paginatorConfig={{
rowsPerPageOptions: [5, 10, 25],
colSpan: 3,
count: totalRecords,
rowsPerPage: rowsPerPage,
page: page,
SelectProps: {
inputProps: { "aria-label": "rows per page" },
native: true,
},
onChangePage: handleChangePage,
onChangeRowsPerPage: handleChangeRowsPerPage,
ActionsComponent: MinTablePaginationActions,
}}
/>
</TabPanel>
<TabPanel index={1} value={curTab}>
@@ -683,20 +669,6 @@ class ViewBucket extends React.Component<IViewBucketProps, IViewBucketState> {
records={filteredRules}
entityName="Replication Rules"
idField="id"
paginatorConfig={{
rowsPerPageOptions: [5, 10, 25],
colSpan: 3,
count: totalRecords,
rowsPerPage: rowsPerPage,
page: page,
SelectProps: {
inputProps: { "aria-label": "rows per page" },
native: true,
},
onChangePage: handleChangePage,
onChangeRowsPerPage: handleChangeRowsPerPage,
ActionsComponent: MinTablePaginationActions,
}}
/>
</TabPanel>
</Grid>

View File

@@ -14,6 +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 from "react";
import clsx from "clsx";
import Grid from "@material-ui/core/Grid";
import RadioGroup from "@material-ui/core/RadioGroup";
import FormControlLabel from "@material-ui/core/FormControlLabel";
@@ -40,6 +41,7 @@ interface RadioGroupProps {
id: string;
name: string;
tooltip?: string;
disableOptions?: boolean;
onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
classes: any;
displayInColumn?: boolean;
@@ -58,8 +60,23 @@ const styles = (theme: Theme) =>
paddingBottom: 10,
marginTop: 11,
},
optionLabel: {
"&.Mui-disabled": {
"& .MuiFormControlLabel-label": {
color: "#9c9c9c",
},
},
"&:last-child": {
marginRight: 0,
},
"& .MuiFormControlLabel-label": {
fontSize: 12,
color: "#000",
},
},
checkedOption: {
"& .MuiFormControlLabel-label": {
fontSize: 12,
color: "#000",
fontWeight: 700,
},
@@ -98,6 +115,7 @@ export const RadioGroupSelector = ({
name,
onChange,
tooltip = "",
disableOptions = false,
classes,
displayInColumn = false,
}: RadioGroupProps) => {
@@ -128,14 +146,14 @@ export const RadioGroupSelector = ({
return (
<FormControlLabel
key={`rd-${name}-${selectorOption.value}`}
value={selectorOption.value}
value={disableOptions ? "disabled" : selectorOption.value}
control={<RadioButton />}
label={selectorOption.label}
className={
selectorOption.value === currentSelection
? classes.checkedOption
: ""
}
disabled={disableOptions}
className={clsx(classes.optionLabel, {
[classes.checkedOption]:
selectorOption.value === currentSelection,
})}
/>
);
})}

View File

@@ -54,6 +54,7 @@ export const modalBasic = {
marginLeft: 0,
},
clearButton: {
fontFamily: "Lato, sans-serif",
border: "0",
backgroundColor: "transparent",
color: "#393939",
@@ -104,6 +105,9 @@ const radioBasic = {
width: 12,
height: 12,
borderRadius: "100%",
"input:disabled ~ &": {
border: "1px solid #9C9C9C",
},
};
export const radioIcons = {
@@ -117,8 +121,7 @@ export const radioIcons = {
export const containerForHeader = (bottomSpacing: any) => ({
container: {
padding: "110px 33px 30px",
paddingBottom: bottomSpacing,
padding: "110px 33px 0",
"& h6": {
color: "#777777",
fontSize: 14,
@@ -153,13 +156,17 @@ export const searchField = {
justifyContent: "center",
padding: "0 16px",
"& input": {
fontSize: 14,
fontSize: 12,
fontWeight: 700,
color: "#000",
"&::placeholder": {
color: "#393939",
opacity: 1,
},
},
"&:hover": {
borderColor: "#000",
},
},
};
@@ -207,3 +214,9 @@ export const objectBrowserCommon = {
},
},
};
export const selectorsCommon = {
multiSelectTable: {
height: 200,
},
};

View File

@@ -25,6 +25,14 @@ import ConsoleIcon from "./TableActionIcons/ConsoleIcon";
import GetAppIcon from "@material-ui/icons/GetApp";
import SvgIcon from "@material-ui/core/SvgIcon";
import { Link } from "react-router-dom";
import { createStyles, withStyles } from "@material-ui/core/styles";
const styles = () =>
createStyles({
spacing: {
margin: "0 8px",
},
});
interface IActionButton {
type: string;
@@ -34,6 +42,7 @@ interface IActionButton {
selected: boolean;
sendOnlyId?: boolean;
idField: string;
classes: any;
}
const defineIcon = (type: string, selected: boolean) => {
@@ -67,6 +76,7 @@ const TableActionButton = ({
selected,
to,
sendOnlyId = false,
classes,
}: IActionButton) => {
const valueClick = sendOnlyId ? valueToSend[idField] : valueToSend;
@@ -82,6 +92,7 @@ const TableActionButton = ({
}
: () => null
}
className={classes.spacing}
>
{defineIcon(type, selected)}
</IconButton>
@@ -107,4 +118,4 @@ const TableActionButton = ({
return null;
};
export default TableActionButton;
export default withStyles(styles)(TableActionButton);

View File

@@ -18,19 +18,13 @@ import get from "lodash/get";
import isString from "lodash/isString";
import {
LinearProgress,
TablePagination,
Table,
TableBody,
TableCell,
TableHead,
TableRow,
Paper,
Grid,
Checkbox,
Typography,
} from "@material-ui/core";
import { createStyles, Theme, withStyles } from "@material-ui/core/styles";
import { TablePaginationActionsProps } from "@material-ui/core/TablePagination/TablePaginationActions";
import { Table, Column, AutoSizer } from "react-virtualized";
import { createStyles, withStyles } from "@material-ui/core/styles";
import TableActionButton from "./TableActionButton";
import history from "../../../../history";
import {
@@ -50,28 +44,13 @@ interface ItemActions {
interface IColumns {
label: string;
elementKey: string;
sortable?: boolean;
renderFunction?: (input: any) => any;
renderFullObject?: boolean;
globalClass?: any;
rowClass?: any;
}
interface IPaginatorConfig {
rowsPerPageOptions: number[];
colSpan: number;
count: number;
rowsPerPage: number;
page: number;
SelectProps: any;
onChangePage: (
event: React.MouseEvent<HTMLButtonElement> | null,
page: number
) => void;
onChangeRowsPerPage?: React.ChangeEventHandler<
HTMLTextAreaElement | HTMLInputElement
>;
ActionsComponent?: React.ElementType<TablePaginationActionsProps>;
width?: number;
headerTextAlign?: string;
contentTextAlign?: string;
}
interface TableWrapperProps {
@@ -84,10 +63,9 @@ interface TableWrapperProps {
classes: any;
entityName: string;
selectedItems?: string[];
stickyHeader?: boolean;
radioSelection?: boolean;
customEmptyMessage?: string;
paginatorConfig?: IPaginatorConfig;
customPaperHeight?: string;
}
const borderColor = "#9c9c9c80";
@@ -104,7 +82,7 @@ const rowText = {
paddingLeft: 6,
};
const styles = (theme: Theme) =>
const styles = () =>
createStyles({
dialogContainer: {
padding: "12px 26px 22px",
@@ -117,7 +95,16 @@ const styles = (theme: Theme) =>
boxShadow: "none",
border: "#EAEDEE 1px solid",
borderRadius: 3,
minHeight: "calc(100vh - 340px)",
minHeight: 200,
overflowY: "scroll",
"&::-webkit-scrollbar": {
width: 3,
height: 3,
},
},
defaultPaperHeight: {
height: "calc(100vh - 205px)",
},
allTableSettings: {
"& .MuiTableCell-sizeSmall:last-child": {
@@ -177,63 +164,143 @@ const styles = (theme: Theme) =>
paddingTop: "100px",
paddingBottom: "100px",
},
rowElement: {
userSelect: "none",
"&:hover": {
backgroundColor: "#ececec",
"& td": {
"@global": {
".rowLine": {
borderBottom: `1px solid ${borderColor}`,
height: 40,
color: "#393939",
fontSize: 14,
transitionDuration: 0.3,
"&:focus": {
outline: "initial",
},
"&:hover:not(.ReactVirtualized__Table__headerRow)": {
userSelect: "none",
backgroundColor: "#ececec",
fontWeight: 600,
"&.canClick": {
cursor: "pointer",
},
},
"& .selected": {
color: "#081C42",
fontWeight: 600,
},
},
},
rowClickable: {
cursor: "pointer",
".headerItem": {
userSelect: "none",
fontWeight: 700,
fontSize: 14,
fontStyle: "initial",
},
".ReactVirtualized__Table__headerRow": {
fontWeight: 700,
fontSize: 14,
borderColor: "#39393980",
textTransform: "initial",
},
".optionsAlignment": {
textAlign: "center",
},
".text-center": {
textAlign: "center",
},
".text-right": {
textAlign: "right",
},
},
...checkboxIcons,
...radioIcons,
});
// Function that renders Title Columns
const titleColumnsMap = (columns: IColumns[]) => {
return columns.map((column: IColumns, index: number) => {
return (
<TableCell
key={`tbCT-${column.elementKey}-${index}`}
className={column.globalClass}
>
{column.label}
</TableCell>
);
});
};
const selectWidth = 45;
// Function that renders Rows
const rowColumnsMap = (
columns: IColumns[],
itemData: any,
classes: any,
// Function to render elements in table
const subRenderFunction = (
rowData: any,
column: IColumns,
isSelected: boolean
) => {
return columns.map((column: IColumns, index: number) => {
const itemElement = isString(itemData)
? itemData
: get(itemData, column.elementKey, null); // If the element is just a string, we render it as it is
const renderConst = column.renderFullObject ? itemData : itemElement;
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.
const renderElement = column.renderFunction
? column.renderFunction(renderConst)
: renderConst; // If render function is set, we send the value to the function.
return (
<React.Fragment>
<span className={isSelected ? "selected" : ""}>{renderElement}</span>
</React.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
) => {
let initialValue = containerWidth;
if (hasSelect) {
initialValue -= selectWidth;
}
if (hasActions) {
initialValue -= actionsWidth;
}
let freeSpacing = columns.reduce((total, currValue) => {
return currValue.width ? total - currValue.width : total;
}, initialValue);
return freeSpacing / columns.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
) => {
const commonRestWidth = calculateColumnRest(
columns,
containerWidth,
actionsWidth,
hasSelect,
hasActions
);
return columns.map((column: IColumns, index: number) => {
return (
<TableCell
key={`tbRE-${column.elementKey}-${index}`}
className={`${column.rowClass} ${
isSelected ? classes.rowSelected : classes.rowUnselected
<Column
key={`col-tb-${index.toString()}`}
dataKey={column.elementKey}
headerClassName={`titleHeader ${
column.headerTextAlign ? `text-${column.headerTextAlign}` : ""
}`}
>
{renderElement}
</TableCell>
headerRenderer={() => <React.Fragment>{column.label}</React.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}
/>
);
});
};
@@ -265,6 +332,22 @@ const elementActions = (
});
};
// Function to calculate the options column width according elements inside
const calculateOptionsSize = (containerWidth: number, totalOptions: number) => {
const minContainerSize = 80;
const sizeOptions = totalOptions * 45;
if (sizeOptions < minContainerSize) {
return minContainerSize;
}
if (sizeOptions > containerWidth) {
return containerWidth;
}
return sizeOptions;
};
// Main function to render the Table Wrapper
const TableWrapper = ({
itemActions,
@@ -276,10 +359,9 @@ const TableWrapper = ({
selectedItems,
idField,
classes,
stickyHeader = false,
radioSelection = false,
customEmptyMessage = "",
paginatorConfig,
customPaperHeight = "",
}: TableWrapperProps) => {
const findView = itemActions
? itemActions.find((el) => el.type === "view")
@@ -301,7 +383,13 @@ const TableWrapper = ({
return (
<Grid item xs={12}>
<Paper className={classes.paper}>
<Paper
className={`${classes.paper} ${
customPaperHeight !== ""
? customPaperHeight
: classes.defaultPaperHeight
}`}
>
{isLoading && (
<Grid container className={classes.loadingBox}>
<Grid item xs={12} style={{ textAlign: "center" }}>
@@ -313,105 +401,133 @@ const TableWrapper = ({
</Grid>
)}
{records && !isLoading && records.length > 0 ? (
<Table
size="small"
stickyHeader={stickyHeader}
className={classes.allTableSettings}
>
<TableHead className={classes.minTableHeader}>
<TableRow>
{onSelect && selectedItems && (
<TableCell align="center" className={classes.checkBoxHeader}>
Select
</TableCell>
)}
{titleColumnsMap(columns)}
{((itemActions && itemActions.length > 1) ||
(itemActions &&
itemActions.length === 1 &&
itemActions[0].type !== "view")) && (
<TableCell
align="center"
className={classes.actionsContainer}
>
Actions
</TableCell>
)}
</TableRow>
</TableHead>
<TableBody>
{records.map((record: any, index: number) => {
const isSelected = selectedItems
? selectedItems.includes(
isString(record) ? record : record[idField]
)
: false;
<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 (
<Table
ref="Table"
disableHeader={false}
headerClassName={"headerItem"}
headerHeight={40}
height={height}
noRowsRenderer={() => (
<React.Fragment>
{customEmptyMessage !== ""
? customEmptyMessage
: `There are no ${entityName} yet.`}
</React.Fragment>
)}
overscanRowCount={10}
rowHeight={40}
width={width}
rowCount={records.length}
rowGetter={({ index }) => records[index]}
onRowClick={({ rowData }) => {
clickAction(rowData);
}}
rowClassName={`rowLine ${findView ? "canClick" : ""}`}
>
{hasSelect && (
<Column
headerRenderer={() => (
<React.Fragment>Select</React.Fragment>
)}
dataKey={idField}
width={selectWidth}
cellRenderer={({ rowData }) => {
const isSelected = selectedItems
? selectedItems.includes(
isString(rowData) ? rowData : rowData[idField]
)
: false;
return (
<TableRow
key={`tb-${entityName}-${index.toString()}`}
className={`${findView ? classes.rowClickable : ""} ${
classes.rowElement
} rowElementRaw`}
onClick={() => {
clickAction(record);
}}
>
{onSelect && selectedItems && (
<TableCell align="center" className={classes.checkBoxRow}>
<Checkbox
value={isString(record) ? record : record[idField]}
color="primary"
inputProps={{ "aria-label": "secondary checkbox" }}
checked={isSelected}
onChange={onSelect}
onClick={(e) => {
e.stopPropagation();
e.preventDefault();
}}
checkedIcon={
<span
className={
radioSelection
? classes.radioSelectedIcon
: classes.checkedIcon
}
/>
}
icon={
<span
className={
radioSelection
? classes.radioUnselectedIcon
: classes.unCheckedIcon
}
/>
}
/>
</TableCell>
)}
{rowColumnsMap(columns, record, classes, isSelected)}
{((itemActions && itemActions.length > 1) ||
(itemActions &&
itemActions.length === 1 &&
itemActions[0].type !== "view")) && (
<TableCell
align="center"
className={classes.actionsContainer}
>
{elementActions(
itemActions,
record,
return (
<Checkbox
value={
isString(rowData) ? rowData : rowData[idField]
}
color="primary"
inputProps={{
"aria-label": "secondary checkbox",
}}
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
)}
{hasOptions && (
<Column
headerRenderer={() => (
<React.Fragment>Options</React.Fragment>
)}
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
)}
</TableCell>
)}
</TableRow>
);
})}
</TableBody>
</Table>
);
}}
/>
)}
</Table>
);
}}
</AutoSizer>
) : (
<React.Fragment>
{!isLoading && (
@@ -424,20 +540,6 @@ const TableWrapper = ({
</React.Fragment>
)}
</Paper>
{paginatorConfig && (
<Grid item xs={12} className={classes.paginatorContainer}>
<Table>
<TableBody>
<TableRow>
<TablePagination
{...paginatorConfig}
className={classes.paginatorComponent}
/>
</TableRow>
</TableBody>
</Table>
</Grid>
)}
</Grid>
);
};

View File

@@ -257,20 +257,6 @@ const Groups = ({ classes }: IGroupsProps) => {
records={filteredRecords}
entityName="Groups"
idField=""
paginatorConfig={{
rowsPerPageOptions: [5, 10, 25],
colSpan: 3,
count: totalRecords,
rowsPerPage: rowsPerPage,
page: page,
SelectProps: {
inputProps: { "aria-label": "rows per page" },
native: true,
},
onChangePage: handleChangePage,
onChangeRowsPerPage: handleChangeRowsPerPage,
ActionsComponent: MinTablePaginationActions,
}}
/>
</Grid>
</Grid>

View File

@@ -27,7 +27,10 @@ import TextField from "@material-ui/core/TextField";
import InputAdornment from "@material-ui/core/InputAdornment";
import SearchIcon from "@material-ui/icons/Search";
import TableWrapper from "../Common/TableWrapper/TableWrapper";
import { actionsTray } from "../Common/FormComponents/common/styleLibrary";
import {
actionsTray,
selectorsCommon,
} from "../Common/FormComponents/common/styleLibrary";
interface IGroupsProps {
classes: any;
@@ -102,6 +105,7 @@ const styles = (theme: Theme) =>
},
},
...actionsTray,
...selectorsCommon,
});
const UsersSelectors = ({
@@ -211,6 +215,7 @@ const UsersSelectors = ({
records={filteredRecords}
entityName="Users"
idField="accessKey"
customPaperHeight={classes.multiSelectTable}
/>
</Grid>
</React.Fragment>

View File

@@ -205,27 +205,6 @@ const ListNotificationEndpoints = ({ classes }: IListNotificationEndpoints) => {
records={filteredRecords}
entityName="Notification Endpoints"
idField="service_name"
paginatorConfig={{
rowsPerPageOptions: [5, 10, 25],
colSpan: 3,
count: totalRecords,
rowsPerPage: rowsPerPage,
page: page,
SelectProps: {
inputProps: { "aria-label": "rows per page" },
native: true,
},
onChangePage: (event: unknown, newPage: number) => {
setPage(newPage);
},
onChangeRowsPerPage: (
event: React.ChangeEvent<HTMLInputElement>
) => {
const rPP = parseInt(event.target.value, 10);
setRowsPerPage(rPP);
},
ActionsComponent: MinTablePaginationActions,
}}
/>
</Grid>
</Grid>

View File

@@ -90,10 +90,13 @@ const styles = (theme: Theme) =>
marginRight: 10,
},
"@global": {
".rowElementRaw:hover .iconBucketElm": {
".rowLine:hover .iconBucketElm": {
backgroundImage: "url(/images/ob_bucket_filled.svg)",
},
},
browsePaper: {
height: "calc(100vh - 280px)",
},
...actionsTray,
...searchField,
...objectBrowserCommon,
@@ -131,10 +134,8 @@ const BrowseBuckets = ({
api
.invoke("GET", `/api/v1/buckets?offset=${offset}&limit=${rowsPerPage}`)
.then((res: BucketList) => {
const buckets = get(res, "buckets", []);
setLoading(false);
setRecords(buckets);
setRecords(res.buckets || []);
setError("");
// if we get 0 results, and page > 0 , go down 1 page
if (
@@ -170,8 +171,6 @@ const BrowseBuckets = ({
return b.name.indexOf(filterBuckets) >= 0;
});
const showInPage = filteredRecords.slice(offset, offset + rowsPerPage);
const handleChangePage = (event: unknown, newPage: number) => {
setPage(newPage);
};
@@ -270,26 +269,16 @@ const BrowseBuckets = ({
renderFunction: niceBytes,
globalClass: classes.usedSpaceCol,
rowClass: classes.usedSpaceCol,
width: 100,
contentTextAlign: "right",
headerTextAlign: "right",
},
]}
isLoading={loading}
records={showInPage}
records={filteredRecords}
entityName="Buckets"
idField="name"
paginatorConfig={{
rowsPerPageOptions: [5, 10, 25],
colSpan: 3,
count: filteredRecords.length,
rowsPerPage: rowsPerPage,
page: page,
SelectProps: {
inputProps: { "aria-label": "rows per page" },
native: true,
},
onChangePage: handleChangePage,
onChangeRowsPerPage: handleChangeRowsPerPage,
ActionsComponent: MinTablePaginationActions,
}}
customPaperHeight={classes.browsePaper}
/>
</Grid>
</Grid>

View File

@@ -257,20 +257,6 @@ const Policies = ({ classes }: IPoliciesProps) => {
records={paginatedRecords}
entityName="Policies"
idField="name"
paginatorConfig={{
rowsPerPageOptions: [5, 10, 25],
colSpan: 3,
count: filteredRecords.length,
rowsPerPage: rowsPerPage,
page: page,
SelectProps: {
inputProps: { "aria-label": "rows per page" },
native: true,
},
onChangePage: handleChangePage,
onChangeRowsPerPage: handleChangeRowsPerPage,
ActionsComponent: MinTablePaginationActions,
}}
/>
</Grid>
</Grid>

View File

@@ -25,7 +25,10 @@ import TextField from "@material-ui/core/TextField";
import api from "../../../common/api";
import { policySort } from "../../../utils/sortFunctions";
import TableWrapper from "../Common/TableWrapper/TableWrapper";
import { actionsTray } from "../Common/FormComponents/common/styleLibrary";
import {
actionsTray,
selectorsCommon,
} from "../Common/FormComponents/common/styleLibrary";
import { PolicyList } from "./types";
interface ISelectPolicyProps {
@@ -100,6 +103,7 @@ const styles = (theme: Theme) =>
},
},
...actionsTray,
...selectorsCommon,
});
const PolicySelectors = ({
@@ -188,6 +192,7 @@ const PolicySelectors = ({
records={filteredRecords}
entityName="Policies"
idField="name"
customPaperHeight={classes.multiSelectTable}
radioSelection
/>
</Grid>

View File

@@ -278,20 +278,6 @@ const ServiceAccounts = ({ classes }: IServiceAccountsProps) => {
idField={""}
columns={[{ label: "Service Account", elementKey: "" }]}
itemActions={tableActions}
paginatorConfig={{
rowsPerPageOptions: [5, 10, 25],
colSpan: 4,
count: records.length,
rowsPerPage: rowsPerPage,
page,
SelectProps: {
inputProps: { "aria-label": "rows per page" },
native: true,
},
onChangePage: handleChangePage,
onChangeRowsPerPage: handleChangeRowsPerPage,
ActionsComponent: MinTablePaginationActions,
}}
/>
</Grid>
</Grid>

View File

@@ -301,20 +301,6 @@ const ListTenants = ({ classes }: ITenantsList) => {
records={filteredRecords}
entityName="Tenants"
idField="name"
paginatorConfig={{
rowsPerPageOptions: [5, 10, 25],
colSpan: 3,
count: filteredRecords.length,
rowsPerPage: rowsPerPage,
page: page,
SelectProps: {
inputProps: { "aria-label": "rows per page" },
native: true,
},
onChangePage: handleChangePage,
onChangeRowsPerPage: handleChangeRowsPerPage,
ActionsComponent: MinTablePaginationActions,
}}
/>
</Grid>
</Grid>

View File

@@ -280,20 +280,6 @@ const TenantDetails = ({ classes, match }: ITenantDetailsProps) => {
records={zones}
entityName="Zones"
idField="name"
paginatorConfig={{
rowsPerPageOptions: [5, 10, 25],
colSpan: 3,
count: zoneCount,
rowsPerPage: 10,
page: 0,
SelectProps: {
inputProps: { "aria-label": "rows per page" },
native: true,
},
ActionsComponent: MinTablePaginationActions,
onChangePage: () => {},
onChangeRowsPerPage: () => {},
}}
/>
)}
</Grid>

View File

@@ -24,7 +24,6 @@ import { createStyles, Theme, withStyles } from "@material-ui/core/styles";
import { niceBytes, timeFromDate } from "../../../../../common/utils";
import { wsProtocol } from "../../../../../utils/wsUtils";
import { containerForHeader } from "../../../Common/FormComponents/common/styleLibrary";
import PageHeader from "../../../Common/PageHeader/PageHeader";
import { Grid } from "@material-ui/core";
import TableWrapper from "../../../Common/TableWrapper/TableWrapper";

View File

@@ -27,7 +27,10 @@ import { stringSort } from "../../../utils/sortFunctions";
import { GroupsList } from "../Groups/types";
import get from "lodash/get";
import TableWrapper from "../Common/TableWrapper/TableWrapper";
import { actionsTray } from "../Common/FormComponents/common/styleLibrary";
import {
actionsTray,
selectorsCommon,
} from "../Common/FormComponents/common/styleLibrary";
interface IGroupsProps {
classes: any;
@@ -101,6 +104,7 @@ const styles = (theme: Theme) =>
},
},
...actionsTray,
...selectorsCommon,
});
const GroupsSelectors = ({
@@ -205,6 +209,7 @@ const GroupsSelectors = ({
records={filteredRecords}
entityName="Groups"
idField=""
customPaperHeight={classes.multiSelectTable}
/>
</Grid>
</React.Fragment>

View File

@@ -361,20 +361,6 @@ class Users extends React.Component<IUsersProps, IUsersState> {
records={paginatedRecords}
entityName="Users"
idField="accessKey"
paginatorConfig={{
rowsPerPageOptions: [5, 10, 25],
colSpan: 3,
count: filteredRecords.length,
rowsPerPage: rowsPerPage,
page: page,
SelectProps: {
inputProps: { "aria-label": "rows per page" },
native: true,
},
onChangePage: handleChangePage,
onChangeRowsPerPage: handleChangeRowsPerPage,
ActionsComponent: MinTablePaginationActions,
}}
/>
</Grid>
</Grid>

View File

@@ -40,7 +40,6 @@ import api from "../../common/api";
import { ILoginDetails, loginStrategyType } from "./types";
import { setSession } from "../../common/utils";
import history from "../../history";
import { isBoolean } from "util";
import { OutlinedInputProps } from "@material-ui/core/OutlinedInput";
const styles = (theme: Theme) =>

View File

@@ -1726,6 +1726,14 @@
dependencies:
"@types/react" "*"
"@types/react-virtualized@^9.21.10":
version "9.21.10"
resolved "https://registry.yarnpkg.com/@types/react-virtualized/-/react-virtualized-9.21.10.tgz#cd072dc9c889291ace2c4c9de8e8c050da8738b7"
integrity sha512-f5Ti3A7gGdLkPPFNHTrvKblpsPNBiQoSorOEOD+JPx72g/Ng2lOt4MYfhvQFQNgyIrAro+Z643jbcKafsMW2ag==
dependencies:
"@types/prop-types" "*"
"@types/react" "*"
"@types/react@*":
version "16.9.53"
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.53.tgz#40cd4f8b8d6b9528aedd1fff8fcffe7a112a3d23"
@@ -4038,7 +4046,7 @@ dom-helpers@^3.4.0:
dependencies:
"@babel/runtime" "^7.1.2"
dom-helpers@^5.0.1:
dom-helpers@^5.0.1, dom-helpers@^5.1.3:
version "5.2.0"
resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.2.0.tgz#57fd054c5f8f34c52a3eeffdb7e7e93cd357d95b"
integrity sha512-Ru5o9+V8CpunKnz5LGgWXkmrH/20cGKwcHwS4m73zIvs54CN9epEmT/HLqFJW3kXpakAFkEdzgy1hzlJe3E4OQ==
@@ -9290,6 +9298,23 @@ react-transition-group@^4.4.0:
loose-envify "^1.4.0"
prop-types "^15.6.2"
react-virtualized@^9.22.2:
version "9.22.2"
resolved "https://registry.yarnpkg.com/react-virtualized/-/react-virtualized-9.22.2.tgz#217a870bad91e5438f46f01a009e1d8ce1060a5a"
integrity sha512-5j4h4FhxTdOpBKtePSs1yk6LDNT4oGtUwjT7Nkh61Z8vv3fTG/XeOf8J4li1AYaexOwTXnw0HFVxsV0GBUqwRw==
dependencies:
"@babel/runtime" "^7.7.2"
clsx "^1.0.4"
dom-helpers "^5.1.3"
loose-envify "^1.4.0"
prop-types "^15.7.2"
react-lifecycles-compat "^3.0.4"
react-window-infinite-loader@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/react-window-infinite-loader/-/react-window-infinite-loader-1.0.5.tgz#6fe094d538a88978c2c9b623052bc50cb28c2abc"
integrity sha512-IcPIq8lADK3zsAcqoLqQGyduicqR6jWkiK2VUX5sKSI9X/rou6OWlOEexnGyujdNTG7hSG8OVBFEhLSDs4qrxg==
react@^16.13.1:
version "16.14.0"
resolved "https://registry.yarnpkg.com/react/-/react-16.14.0.tgz#94d776ddd0aaa37da3eda8fc5b6b18a4c9a3114d"

View File

@@ -681,7 +681,7 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create
return nil, prepareError(errorGeneric)
}
const consoleVersion = "minio/console:v0.4.4"
const consoleVersion = "minio/console:v0.4.5"
minInst.Spec.Console = &operator.ConsoleConfiguration{
Replicas: 1,
Image: consoleVersion,

View File

@@ -1016,7 +1016,7 @@ func Test_UpdateTenantAction(t *testing.T) {
},
params: admin_api.UpdateTenantParams{
Body: &models.UpdateTenantRequest{
ConsoleImage: "minio/console:v0.4.4",
ConsoleImage: "minio/console:v0.4.5",
},
},
},