diff --git a/portal-ui/src/screens/Console/Common/TableWrapper/TableActionButton.tsx b/portal-ui/src/screens/Console/Common/TableWrapper/TableActionButton.tsx new file mode 100644 index 0000000000..699ffad48a --- /dev/null +++ b/portal-ui/src/screens/Console/Common/TableWrapper/TableActionButton.tsx @@ -0,0 +1,60 @@ +// This file is part of MinIO Console Server +// Copyright (c) 2020 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 . +import React from "react"; +import { IconButton } from "@material-ui/core"; +import ViewIcon from "./TableActionIcons/ViewIcon"; +import PencilIcon from "./TableActionIcons/PencilIcon"; +import DeleteIcon from "./TableActionIcons/DeleteIcon"; + +interface IActionButton { + type: string; + onClick: (id: string) => any; + valueToSend: any; + selected: boolean; +} + +const defineIcon = (type: string, selected: boolean) => { + switch (type) { + case "view": + return ; + case "edit": + return ; + case "delete": + return ; + } + + return null; +}; + +const TableActionButton = ({ + type, + onClick, + valueToSend, + selected +}: IActionButton) => { + return ( + { + onClick(valueToSend); + }} + > + {defineIcon(type, selected)} + + ); +}; + +export default TableActionButton; diff --git a/portal-ui/src/screens/Console/Common/TableWrapper/TableActionIcons/DeleteIcon.tsx b/portal-ui/src/screens/Console/Common/TableWrapper/TableActionIcons/DeleteIcon.tsx new file mode 100644 index 0000000000..83275386ab --- /dev/null +++ b/portal-ui/src/screens/Console/Common/TableWrapper/TableActionIcons/DeleteIcon.tsx @@ -0,0 +1,23 @@ +import React from "react"; +import { IIcon, selected, unSelected } from "./common"; + +const DeleteIcon = ({ active = false }: IIcon) => { + return ( + + + + + + ); +}; + +export default DeleteIcon; diff --git a/portal-ui/src/screens/Console/Common/TableWrapper/TableActionIcons/PencilIcon.tsx b/portal-ui/src/screens/Console/Common/TableWrapper/TableActionIcons/PencilIcon.tsx new file mode 100644 index 0000000000..b7252c4c39 --- /dev/null +++ b/portal-ui/src/screens/Console/Common/TableWrapper/TableActionIcons/PencilIcon.tsx @@ -0,0 +1,21 @@ +import React from "react"; +import { IIcon, selected, unSelected } from "./common"; + +const PencilIcon = ({ active = false }: IIcon) => { + return ( + + + + ); +}; + +export default PencilIcon; diff --git a/portal-ui/src/screens/Console/Common/TableWrapper/TableActionIcons/ViewIcon.tsx b/portal-ui/src/screens/Console/Common/TableWrapper/TableActionIcons/ViewIcon.tsx new file mode 100644 index 0000000000..6fa5179e16 --- /dev/null +++ b/portal-ui/src/screens/Console/Common/TableWrapper/TableActionIcons/ViewIcon.tsx @@ -0,0 +1,21 @@ +import React from "react"; +import { IIcon, selected, unSelected } from "./common"; + +const ViewIcon = ({ active = false }: IIcon) => { + return ( + + + + ); +}; + +export default ViewIcon; diff --git a/portal-ui/src/screens/Console/Common/TableWrapper/TableActionIcons/common.ts b/portal-ui/src/screens/Console/Common/TableWrapper/TableActionIcons/common.ts new file mode 100644 index 0000000000..3456bf7afe --- /dev/null +++ b/portal-ui/src/screens/Console/Common/TableWrapper/TableActionIcons/common.ts @@ -0,0 +1,6 @@ +export interface IIcon { + active: boolean; +} + +export const unSelected = "#adadad"; +export const selected = "#201763"; diff --git a/portal-ui/src/screens/Console/Common/TableWrapper/TableWrapper.tsx b/portal-ui/src/screens/Console/Common/TableWrapper/TableWrapper.tsx new file mode 100644 index 0000000000..62b5742ac9 --- /dev/null +++ b/portal-ui/src/screens/Console/Common/TableWrapper/TableWrapper.tsx @@ -0,0 +1,301 @@ +// This file is part of MinIO Console Server +// Copyright (c) 2020 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 . +import React from "react"; +import get from "lodash/get"; +import { + LinearProgress, + TablePagination, + Table, + TableBody, + TableCell, + TableHead, + TableRow, + Paper, + Grid, + Checkbox +} from "@material-ui/core"; +import { createStyles, Theme, withStyles } from "@material-ui/core/styles"; +import { TablePaginationActionsProps } from "@material-ui/core/TablePagination/TablePaginationActions"; +import TableActionButton from "./TableActionButton"; + +interface ItemActions { + type: string; + onClick(valueToSend: any): any; +} + +interface IColumns { + label: string; + elementKey: string; + sortable?: boolean; +} + +interface IPaginatorConfig { + rowsPerPageOptions: number[]; + colSpan: number; + count: number; + rowsPerPage: number; + page: number; + SelectProps: any; + onChangePage: ( + event: React.MouseEvent | null, + page: number + ) => void; + onChangeRowsPerPage?: React.ChangeEventHandler< + HTMLTextAreaElement | HTMLInputElement + >; + ActionsComponent?: React.ElementType; +} + +interface TableWrapperProps { + itemActions?: ItemActions[] | null; + columns: IColumns[]; + onSelect?: (e: React.ChangeEvent) => any; + idField: string; + isLoading: boolean; + records: any[]; + classes: any; + entityName: string; + selectedItems?: string[]; + stickyHeader?: boolean; + paginatorConfig?: IPaginatorConfig; +} + +const borderColor = "#eaeaea"; + +const rowText = { + fontWeight: 400, + fontSize: 14, + borderColor: borderColor +}; + +const checkBoxBasic = { + width: 16, + height: 16, + borderRadius: 3 +}; + +const styles = (theme: Theme) => + createStyles({ + dialogContainer: { + padding: "12px 26px 22px" + }, + paper: { + display: "flex", + overflow: "auto", + flexDirection: "column", + padding: "19px 38px" + }, + minTableHeader: { + color: "#393939", + "& tr": { + "& th": { + fontWeight: 700, + fontSize: 14, + paddingBottom: 15, + borderColor: borderColor + } + } + }, + rowUnselected: { + ...rowText + }, + rowSelected: { + ...rowText, + color: "#201763" + }, + paginatorContainer: { + display: "flex", + justifyContent: "flex-end", + padding: "5px 38px" + }, + checkBoxHeader: { + "&.MuiTableCell-paddingCheckbox": { + paddingBottom: 9 + } + }, + actionsContainer: { + width: 120, + borderColor: borderColor + }, + paginatorComponent: { + borderBottom: 0 + }, + unCheckedIcon: { ...checkBoxBasic, border: "1px solid #d0d0d0" }, + checkedIcon: { + ...checkBoxBasic, + border: "1px solid #201763", + backgroundColor: "#201763" + }, + checkBoxRow: { + borderColor: borderColor + } + }); + +const titleColumnsMap = (columns: IColumns[]) => { + const columnsList = columns.map((column: IColumns, index: number) => { + return ( + + {column.label} + + ); + }); + + return columnsList; +}; + +const rowColumnsMap = ( + columns: IColumns[], + itemData: any, + classes: any, + isSelected: boolean +) => { + const rowElements = columns.map((column: IColumns, index: number) => { + const itemElement = get(itemData, column.elementKey, null); + return ( + + {itemElement} + + ); + }); + + return rowElements; +}; + +const elementActions = ( + actions: ItemActions[], + valueToSend: any, + selected: boolean +) => { + const actionsElements = actions.map((action: ItemActions, index: number) => { + return ( + + ); + }); + + return actionsElements; +}; + +const TableWrapper = ({ + itemActions, + columns, + onSelect, + records, + isLoading, + entityName, + selectedItems, + idField, + classes, + stickyHeader = false, + paginatorConfig +}: TableWrapperProps) => { + return ( + + + {isLoading && } + {records && records.length > 0 ? ( + + + + {onSelect && selectedItems && ( + + Select + + )} + {titleColumnsMap(columns)} + {itemActions && itemActions.length > 0 && ( + + Actions + + )} + + + + {records.map((record: any, index: number) => { + const isSelected = selectedItems + ? selectedItems.includes(record[idField]) + : false; + return ( + + {onSelect && selectedItems && ( + + } + icon={} + /> + + )} + {rowColumnsMap(columns, record, classes, isSelected)} + {itemActions && itemActions.length > 0 && ( + + {elementActions(itemActions, record, isSelected)} + + )} + + ); + })} + +
+ ) : ( +
{`There are no ${entityName} yet.`}
+ )} +
+ {paginatorConfig && ( + + + + + + + +
+
+ )} +
+ ); +}; + +export default withStyles(styles)(TableWrapper); diff --git a/portal-ui/src/screens/Console/Users/Users.tsx b/portal-ui/src/screens/Console/Users/Users.tsx index 2b7c7dacd1..cdc8ac1342 100644 --- a/portal-ui/src/screens/Console/Users/Users.tsx +++ b/portal-ui/src/screens/Console/Users/Users.tsx @@ -19,25 +19,12 @@ import { createStyles, Theme, withStyles } from "@material-ui/core/styles"; import api from "../../../common/api"; import { Button, - IconButton, - LinearProgress, - TableFooter, - TablePagination, - Table, - TableBody, - TableCell, - TableHead, - TableRow, - Paper, Grid, Typography, TextField, InputAdornment } from "@material-ui/core"; import SearchIcon from "@material-ui/icons/Search"; -import Checkbox from "@material-ui/core/Checkbox"; -import DeleteIcon from "@material-ui/icons/Delete"; -import ViewIcon from "@material-ui/icons/Visibility"; import GroupIcon from "@material-ui/icons/Group"; import { User, UsersList } from "./types"; import { usersSort } from "../../../utils/sortFunctions"; @@ -46,6 +33,7 @@ import { CreateIcon } from "../../../icons"; import AddUser from "./AddUser"; import DeleteUser from "./DeleteUser"; import AddToGroup from "./AddToGroup"; +import TableWrapper from "../Common/TableWrapper/TableWrapper"; const styles = (theme: Theme) => createStyles({ @@ -251,6 +239,25 @@ class Users extends React.Component { return elements; }; + const viewAction = (selectionElement: any): void => { + this.setState({ + addScreenOpen: true, + selectedUser: selectionElement + }); + }; + + const deleteAction = (selectionElement: any): void => { + this.setState({ + deleteOpen: true, + selectedUser: selectionElement + }); + }; + + const tableActions = [ + { type: "view", onClick: viewAction }, + { type: "delete", onClick: deleteAction } + ]; + return ( {addScreenOpen && ( @@ -340,82 +347,30 @@ class Users extends React.Component {
- - {loading && } - {records != null && records.length > 0 ? ( - - - - Select - Access Key - Actions - - - - {filteredRecords.map(row => ( - - - - - - {row.accessKey} - - - { - this.setState({ - addScreenOpen: true, - selectedUser: row - }); - }} - > - - - { - this.setState({ - deleteOpen: true, - selectedUser: row - }); - }} - > - - - - - ))} - - - - - - -
- ) : ( -
No Users
- )} -
+