Updated console to use React 17 (#469)

This commit is contained in:
Alex
2020-12-04 20:05:32 -06:00
committed by GitHub
parent 41418bcf45
commit cb35dcf971
26 changed files with 791 additions and 18701 deletions

File diff suppressed because one or more lines are too long

17878
portal-ui/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -12,7 +12,7 @@
"@types/jest": "24.0.23",
"@types/lodash": "^4.14.149",
"@types/node": "12.12.8",
"@types/react": "16.9.11",
"@types/react": "17.0.0",
"@types/react-copy-to-clipboard": "^4.3.0",
"@types/react-dom": "16.9.4",
"@types/react-redux": "^7.1.5",
@@ -30,14 +30,14 @@
"local-storage-fallback": "^4.1.1",
"lodash": "^4.17.19",
"moment": "^2.24.0",
"react": "^16.13.1",
"react": "17.0.0",
"react-app-rewire-hot-loader": "^2.0.1",
"react-app-rewired": "^2.1.6",
"react-async-hook": "^3.6.1",
"react-chartjs-2": "^2.9.0",
"react-codemirror2": "^7.1.0",
"react-copy-to-clipboard": "^5.0.2",
"react-dom": "^16.12.0",
"react-dom": "17.0.0",
"react-hot-loader": "^4.13.0",
"react-moment": "^0.9.7",
"react-redux": "^7.1.3",
@@ -50,7 +50,6 @@
"redux-thunk": "^2.3.0",
"superagent": "^5.1.0",
"typeface-roboto": "^0.0.75",
"typescript": "3.6.4",
"use-debounce": "^5.0.1",
"websocket": "^1.0.31"
},
@@ -77,6 +76,7 @@
},
"proxy": "http://localhost:9090/",
"devDependencies": {
"prettier": "^1.19.1"
"prettier": "^1.19.1",
"typescript": "^4.1.2"
}
}

View File

@@ -1,16 +1,16 @@
import React from 'react'
import React from "react";
import Typography from "@material-ui/core/Typography";
import Link from "@material-ui/core/Link";
export default function Copyright() {
return (
<Typography variant="body2" color="textSecondary" align="center">
{'Copyright © '}
<Link color="inherit" href="https://material-ui.com/">
return (
<Typography variant="body2" color="textSecondary" align="center">
{"Copyright © "}
<Link color="inherit" href="https://material-ui.com/">
MinIO
</Link>{' '}
{new Date().getFullYear()}
{'.'}
</Link>{" "}
{new Date().getFullYear()}
{"."}
</Typography>
);
);
}

View File

@@ -19,7 +19,7 @@ import {
createStyles,
makeStyles,
Theme,
useTheme
useTheme,
} from "@material-ui/core/styles";
import React from "react";
import { IconButton } from "@material-ui/core";
@@ -31,8 +31,8 @@ const useStyles1 = makeStyles((theme: Theme) =>
createStyles({
root: {
flexShrink: 0,
marginLeft: theme.spacing(2.5)
}
marginLeft: theme.spacing(2.5),
},
})
);

View File

@@ -1,6 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
import Typography from '@material-ui/core/Typography';
import React from "react";
import PropTypes from "prop-types";
import Typography from "@material-ui/core/Typography";
export default function Title(props: React.Props<any>) {
return (

View File

@@ -15,20 +15,25 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import React from "react";
import {SvgIcon} from "@material-ui/core";
import { SvgIcon } from "@material-ui/core";
class PermissionIcon extends React.Component {
render() {
return (<SvgIcon>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 14 16">
<title>ic_permissions</title>
<g id="Layer_2" data-name="Layer 2">
<g id="Layer_1-2" data-name="Layer 1">
<polygon className="cls-1" points="14 16 7.035 12.13 0 16 0 0 14 0 14 16"/>
</g>
</g>
</svg>
</SvgIcon>)
}
render() {
return (
<SvgIcon>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 14 16">
<title>ic_permissions</title>
<g id="Layer_2" data-name="Layer 2">
<g id="Layer_1-2" data-name="Layer 1">
<polygon
className="cls-1"
points="14 16 7.035 12.13 0 16 0 0 14 0 14 16"
/>
</g>
</g>
</svg>
</SvgIcon>
);
}
}
export default PermissionIcon;

View File

@@ -15,113 +15,33 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import React from "react";
import {
createStyles,
StyledProps,
Theme,
withStyles,
} from "@material-ui/core/styles";
import { createStyles, Theme } from "@material-ui/core/styles";
import history from "../../../history";
import {
Route,
RouteComponentProps,
Router,
Switch,
withRouter,
} from "react-router-dom";
import { Route, Router, Switch, withRouter } from "react-router-dom";
import { connect } from "react-redux";
import { AppState } from "../../../store";
import { setMenuOpen } from "../../../actions";
import { ThemedComponentProps } from "@material-ui/core/styles/withTheme";
import NotFoundPage from "../../NotFoundPage";
import ListBuckets from "./ListBuckets/ListBuckets";
import ViewBucket from "./ViewBucket/ViewBucket";
const styles = (theme: Theme) =>
createStyles({
root: {
display: "flex",
},
toolbar: {
background: theme.palette.background.default,
color: "black",
paddingRight: 24, // keep right padding when drawer closed
},
toolbarIcon: {
display: "flex",
alignItems: "center",
justifyContent: "flex-end",
padding: "0 8px",
...theme.mixins.toolbar,
},
appBar: {
zIndex: theme.zIndex.drawer + 1,
transition: theme.transitions.create(["width", "margin"], {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
},
menuButton: {
marginRight: 36,
},
menuButtonHidden: {
display: "none",
},
title: {
flexGrow: 1,
},
appBarSpacer: {
height: "5px",
},
content: {
flexGrow: 1,
height: "100vh",
overflow: "auto",
},
container: {
paddingTop: theme.spacing(4),
paddingBottom: theme.spacing(4),
},
paper: {
padding: theme.spacing(2),
display: "flex",
overflow: "auto",
flexDirection: "column",
},
fixedHeight: {
minHeight: 240,
},
});
const mapState = (state: AppState) => ({
open: state.system.sidebarOpen,
});
const connector = connect(mapState, { setMenuOpen });
interface BucketsProps {
open: boolean;
title: string;
classes: any;
setMenuOpen: typeof setMenuOpen;
}
const Buckets = () => {
return (
<Router history={history}>
<Switch>
<Route path="/buckets/:bucketName" component={ViewBucket} />
<Route path="/" component={ListBuckets} />
<Route component={NotFoundPage} />
</Switch>
</Router>
);
};
class Buckets extends React.Component<
BucketsProps & RouteComponentProps & StyledProps & ThemedComponentProps
> {
render() {
return (
<Router history={history}>
<Switch>
<Route path="/buckets/:bucketName" component={ViewBucket} />
<Route path="/" component={ListBuckets} />
<Route component={NotFoundPage} />
</Switch>
</Router>
);
}
}
export default withRouter(connector(withStyles(styles)(Buckets)));
export default withRouter(connector(Buckets));

View File

@@ -256,7 +256,7 @@ const ListObjects = ({
xhr.open("POST", uploadUrl, true);
xhr.withCredentials = false;
xhr.onload = function(event) {
xhr.onload = function (event) {
// TODO: handle status
if (xhr.status === 401 || xhr.status === 403) {
showSnackBarMessage("An error occurred while uploading the file.");

View File

@@ -6,7 +6,6 @@ import {
DialogContent,
DialogContentText,
DialogTitle,
Grid,
LinearProgress,
} from "@material-ui/core";
import { createStyles, Theme, withStyles } from "@material-ui/core/styles";
@@ -19,7 +18,7 @@ interface IDeleteTagModal {
currentTags: any;
bucketName: string;
versionId: string | null;
selectedTag: [string, string];
selectedTag: string[];
onCloseAndUpdate: (refresh: boolean) => void;
selectedObject: string;
classes: any;

View File

@@ -160,7 +160,7 @@ const ObjectDetails = ({
const [retentionModalOpen, setRetentionModalOpen] = useState<boolean>(false);
const [tagModalOpen, setTagModalOpen] = useState<boolean>(false);
const [deleteTagModalOpen, setDeleteTagModalOpen] = useState<boolean>(false);
const [selectedTag, setSelectedTag] = useState<[string, string]>(["", ""]);
const [selectedTag, setSelectedTag] = useState<string[]>(["", ""]);
const [legalholdOpen, setLegalholdOpen] = useState<boolean>(false);
const [actualInfo, setActualInfo] = useState<IFileInfo>(emptyFile);
const [versions, setVersions] = useState<IFileInfo[]>([]);
@@ -447,25 +447,26 @@ const ObjectDetails = ({
</Grid>
<Grid item xs={12} className={classes.tagsContainer}>
<div className={classes.tagText}>Tags:</div>
{tagKeys.map((tagKey, index) => {
const tag = get(actualInfo, `tags.${tagKey}`, "");
if (tag !== "") {
return (
<Chip
key={`chip-${index}`}
className={classes.tag}
size="small"
label={`${tagKey} : ${tag}`}
color="primary"
deleteIcon={<CloseIcon />}
onDelete={() => {
deleteTag(tagKey, tag);
}}
/>
);
}
return null;
})}
{tagKeys &&
tagKeys.map((tagKey, index) => {
const tag = get(actualInfo, `tags.${tagKey}`, "");
if (tag !== "") {
return (
<Chip
key={`chip-${index}`}
className={classes.tag}
size="small"
label={`${tagKey} : ${tag}`}
color="primary"
deleteIcon={<CloseIcon />}
onDelete={() => {
deleteTag(tagKey, tag);
}}
/>
);
}
return null;
})}
<Chip
className={classes.tag}
icon={<AddIcon />}

View File

@@ -35,7 +35,7 @@ export const download = (
xhr.open("GET", path, true);
xhr.responseType = "blob";
xhr.onload = function(e) {
xhr.onload = function (e) {
if (this.status === 200) {
const blob = new Blob([this.response], {
type: "octet/stream",

View File

@@ -38,11 +38,7 @@ export const years = Array.from(
(_, numYear) => numYear + currentYear
);
export const validDate = (
year: string,
month: string,
day: string
): [boolean, string] => {
export const validDate = (year: string, month: string, day: string): any[] => {
const currentDate = Date.parse(`${year}-${month}-${day}`);
if (isNaN(currentDate)) {

View File

@@ -350,4 +350,4 @@ const connector = connect(mapState, {
serverIsLoading,
});
export default connector(withStyles(styles)(Console));
export default withStyles(styles)(connector(Console));

View File

@@ -1,22 +1,29 @@
import React from 'react';
import {useTheme} from '@material-ui/core/styles';
import {LineChart, Line, XAxis, YAxis, Label, ResponsiveContainer} from 'recharts';
import React from "react";
import { useTheme } from "@material-ui/core/styles";
import {
LineChart,
Line,
XAxis,
YAxis,
Label,
ResponsiveContainer,
} from "recharts";
import Title from "../../../common/Title";
// Generate Sales Data
function createData(time: string, amount: number) {
return {time, amount};
return { time, amount };
}
const data = [
createData('00:00', 0),
createData('03:00', 300),
createData('06:00', 600),
createData('09:00', 800),
createData('12:00', 1500),
createData('15:00', 2000),
createData('18:00', 2400),
createData('21:00', 2400),
createData("00:00", 0),
createData("03:00", 300),
createData("06:00", 600),
createData("09:00", 800),
createData("12:00", 1500),
createData("15:00", 2000),
createData("18:00", 2400),
createData("21:00", 2400),
];
export default function Chart() {
@@ -35,17 +42,22 @@ export default function Chart() {
left: 24,
}}
>
<XAxis dataKey="time" stroke={theme.palette.text.secondary}/>
<XAxis dataKey="time" stroke={theme.palette.text.secondary} />
<YAxis stroke={theme.palette.text.secondary}>
<Label
angle={270}
position="left"
style={{textAnchor: 'middle', fill: theme.palette.text.primary}}
style={{ textAnchor: "middle", fill: theme.palette.text.primary }}
>
Sales ($)
</Label>
</YAxis>
<Line type="monotone" dataKey="amount" stroke={theme.palette.primary.main} dot={false}/>
<Line
type="monotone"
dataKey="amount"
stroke={theme.palette.primary.main}
dot={false}
/>
</LineChart>
</ResponsiveContainer>
</React.Fragment>

View File

@@ -1,7 +1,7 @@
import React from 'react';
import Link from '@material-ui/core/Link';
import {makeStyles} from '@material-ui/core/styles';
import Typography from '@material-ui/core/Typography';
import React from "react";
import Link from "@material-ui/core/Link";
import { makeStyles } from "@material-ui/core/styles";
import Typography from "@material-ui/core/Typography";
import Title from "../../../common/Title";
function preventDefault(event: React.MouseEvent) {

View File

@@ -60,17 +60,17 @@ const rows = [
"Long Branch, NJ",
"VISA ⠀•••• 5919",
212.79
)
),
];
function preventDefault(event: React.MouseEvent) {
event.preventDefault();
}
const useStyles = makeStyles(theme => ({
const useStyles = makeStyles((theme) => ({
seeMore: {
marginTop: theme.spacing(3)
}
marginTop: theme.spacing(3),
},
}));
export default function Orders() {
@@ -89,7 +89,7 @@ export default function Orders() {
</TableRow>
</TableHead>
<TableBody>
{rows.map(row => (
{rows.map((row) => (
<TableRow key={row.id}>
<TableCell>{row.date}</TableCell>
<TableCell>{row.name}</TableCell>

View File

@@ -23,7 +23,7 @@ import {
DialogContent,
DialogContentText,
DialogTitle,
LinearProgress
LinearProgress,
} from "@material-ui/core";
import api from "../../../common/api";
import Typography from "@material-ui/core/Typography";
@@ -39,15 +39,15 @@ interface IDeleteGroup {
const styles = (theme: Theme) =>
createStyles({
errorBlock: {
color: "red"
}
color: "red",
},
});
const DeleteGroup = ({
selectedGroup,
deleteOpen,
closeDeleteModalAndRefresh,
classes
classes,
}: IDeleteGroup) => {
const [isDeleting, setDeleteLoading] = useState<boolean>(false);
const [deleteError, setError] = useState<string>("");
@@ -67,7 +67,7 @@ const DeleteGroup = ({
closeDeleteModalAndRefresh(true);
})
.catch(err => {
.catch((err) => {
setDeleteLoading(false);
setError(err);
});

View File

@@ -23,7 +23,7 @@ import {
DialogContent,
DialogContentText,
DialogTitle,
LinearProgress
LinearProgress,
} from "@material-ui/core";
import api from "../../../common/api";
import { Permission, PermissionList } from "./types";
@@ -32,8 +32,8 @@ import Typography from "@material-ui/core/Typography";
const styles = (theme: Theme) =>
createStyles({
errorBlock: {
color: "red"
}
color: "red",
},
});
interface IDeletePermissionProps {
@@ -54,7 +54,7 @@ class DeletePermission extends React.Component<
> {
state: IDeletePermissionState = {
deleteLoading: false,
deleteError: ""
deleteError: "",
};
removeRecord() {
@@ -69,23 +69,23 @@ class DeletePermission extends React.Component<
this.setState({ deleteLoading: true }, () => {
api
.invoke("DELETE", `/api/v1/permissions/${selectedPermission.id}`, {
id: selectedPermission.id
id: selectedPermission.id,
})
.then((res: PermissionList) => {
this.setState(
{
deleteLoading: false,
deleteError: ""
deleteError: "",
},
() => {
this.props.closeDeleteModalAndRefresh(true);
}
);
})
.catch(err => {
.catch((err) => {
this.setState({
deleteLoading: false,
deleteError: err
deleteError: err,
});
});
});
@@ -114,7 +114,8 @@ class DeletePermission extends React.Component<
<DialogContent>
{deleteLoading && <LinearProgress />}
<DialogContentText id="alert-dialog-description">
Are you sure you want to delete permission{" "}<b>{selectedPermission.name}</b>?
Are you sure you want to delete permission{" "}
<b>{selectedPermission.name}</b>?
{deleteError !== "" && (
<React.Fragment>
<br />

View File

@@ -29,7 +29,7 @@ import {
IconButton,
LinearProgress,
TableFooter,
TablePagination
TablePagination,
} from "@material-ui/core";
import Typography from "@material-ui/core/Typography";
import DeleteIcon from "@material-ui/icons/Delete";
@@ -48,49 +48,49 @@ import PlayArrowRoundedIcon from "@material-ui/icons/PlayArrowRounded";
const styles = (theme: Theme) =>
createStyles({
seeMore: {
marginTop: theme.spacing(3)
marginTop: theme.spacing(3),
},
paper: {
display: "flex",
overflow: "auto",
flexDirection: "column"
flexDirection: "column",
},
addSideBar: {
width: "320px",
padding: "20px"
padding: "20px",
},
errorBlock: {
color: "red"
color: "red",
},
tableToolbar: {
paddingLeft: theme.spacing(2),
paddingRight: theme.spacing(0)
paddingRight: theme.spacing(0),
},
wrapCell: {
maxWidth: "200px",
whiteSpace: "normal",
wordWrap: "break-word"
wordWrap: "break-word",
},
minTableHeader: {
color: "#393939",
"& tr": {
"& th": {
fontWeight: "bold"
}
}
fontWeight: "bold",
},
},
},
actionsTray: {
textAlign: "right",
"& button": {
marginLeft: 10
}
marginLeft: 10,
},
},
searchField: {
background: "#FFFFFF",
padding: 12,
borderRadius: 5,
boxShadow: "0px 3px 6px #00000012"
}
boxShadow: "0px 3px 6px #00000012",
},
});
interface IPermissionsProps {
@@ -124,7 +124,7 @@ class Permissions extends React.Component<
page: 0,
rowsPerPage: 10,
deleteOpen: false,
selectedPermission: null
selectedPermission: null,
};
fetchRecords() {
@@ -141,7 +141,7 @@ class Permissions extends React.Component<
loading: false,
records: res.permissions,
totalRecords: res.total,
error: ""
error: "",
});
// if we get 0 results, and page > 0 , go down 1 page
if (
@@ -156,7 +156,7 @@ class Permissions extends React.Component<
});
}
})
.catch(err => {
.catch((err) => {
this.setState({ loading: false, error: err });
});
});
@@ -190,7 +190,7 @@ class Permissions extends React.Component<
page,
rowsPerPage,
deleteOpen,
selectedPermission
selectedPermission,
} = this.state;
const handleChangePage = (event: unknown, newPage: number) => {
@@ -211,14 +211,14 @@ class Permissions extends React.Component<
const confirmDeletePermission = (selectedPermission: Permission) => {
this.setState({
deleteOpen: true,
selectedPermission: selectedPermission
selectedPermission: selectedPermission,
});
};
const editPermission = (selectedPermission: Permission) => {
this.setState({
addScreenOpen: true,
selectedPermission: selectedPermission
selectedPermission: selectedPermission,
});
};
@@ -266,7 +266,7 @@ class Permissions extends React.Component<
<InputAdornment position="start">
<SearchIcon />
</InputAdornment>
)
),
}}
/>
<Button
@@ -276,7 +276,7 @@ class Permissions extends React.Component<
onClick={() => {
this.setState({
addScreenOpen: true,
selectedPermission: null
selectedPermission: null,
});
}}
>
@@ -288,7 +288,7 @@ class Permissions extends React.Component<
startIcon={<PlayArrowRoundedIcon />}
onClick={() => {
this.setState({
addScreenOpen: true
addScreenOpen: true,
});
}}
>
@@ -315,7 +315,7 @@ class Permissions extends React.Component<
</TableRow>
</TableHead>
<TableBody>
{records.map(row => (
{records.map((row) => (
<TableRow key={row.name}>
<TableCell padding="checkbox">
<Checkbox
@@ -332,7 +332,7 @@ class Permissions extends React.Component<
</TableCell>
<TableCell>{row.effect}</TableCell>
<TableCell className={classes.wrapCell}>
{row.resources.map(r => r.bucket_name).join(", ")}
{row.resources.map((r) => r.bucket_name).join(", ")}
</TableCell>
<TableCell>
{actionLabel(row.actions[0].type)}
@@ -368,7 +368,7 @@ class Permissions extends React.Component<
page={page}
SelectProps={{
inputProps: { "aria-label": "rows per page" },
native: true
native: true,
}}
onChangePage={handleChangePage}
onChangeRowsPerPage={handleChangeRowsPerPage}

View File

@@ -15,16 +15,16 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
export interface Permission {
id: string;
name: string;
slug: string;
description: string;
effect: string;
resources: any[];
actions: any[];
id: string;
name: string;
slug: string;
description: string;
effect: string;
resources: any[];
actions: any[];
}
export interface PermissionList {
permissions: Permission[];
total:number;
permissions: Permission[];
total: number;
}

View File

@@ -23,7 +23,7 @@ import {
DialogContent,
DialogContentText,
DialogTitle,
LinearProgress
LinearProgress,
} from "@material-ui/core";
import api from "../../../common/api";
import { User, UsersList } from "./types";
@@ -32,8 +32,8 @@ import Typography from "@material-ui/core/Typography";
const styles = (theme: Theme) =>
createStyles({
errorBlock: {
color: "red"
}
color: "red",
},
});
interface IDeleteUserProps {
@@ -51,7 +51,7 @@ interface IDeleteUserState {
class DeleteUser extends React.Component<IDeleteUserProps, IDeleteUserState> {
state: IDeleteUserState = {
deleteLoading: false,
deleteError: ""
deleteError: "",
};
removeRecord() {
@@ -66,23 +66,23 @@ class DeleteUser extends React.Component<IDeleteUserProps, IDeleteUserState> {
this.setState({ deleteLoading: true }, () => {
api
.invoke("DELETE", `/api/v1/users/${selectedUser.accessKey}`, {
id: selectedUser.id
id: selectedUser.id,
})
.then((res: UsersList) => {
this.setState(
{
deleteLoading: false,
deleteError: ""
deleteError: "",
},
() => {
this.props.closeDeleteModalAndRefresh(true);
}
);
})
.catch(err => {
.catch((err) => {
this.setState({
deleteLoading: false,
deleteError: err
deleteError: err,
});
});
});

View File

@@ -0,0 +1,6 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"jsx": "react-jsxdev"
}
}

View File

@@ -1,6 +1,6 @@
{
"compilerOptions": {
"target": "es5",
"target": "es2015",
"lib": [
"dom",
"dom.iterable",
@@ -17,10 +17,10 @@
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react",
"jsx": "react-jsx",
"downlevelIteration": true
},
"include": [
"src"
]
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +0,0 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1