diff --git a/Makefile b/Makefile index 4e27fd4d1..972af1a67 100644 --- a/Makefile +++ b/Makefile @@ -79,4 +79,4 @@ clean: @rm -vf console docker: - @docker build -t $(TAG) --build-arg build_version=$(BUILD_VERSION) --build-arg build_time='$(BUILD_TIME)' . + @docker buildx build --output=type=docker --platform linux/amd64 -t $(TAG) --build-arg build_version=$(BUILD_VERSION) --build-arg build_time='$(BUILD_TIME)' . diff --git a/iconos/Lambda.svg b/iconos/Lambda.svg deleted file mode 100644 index eb7c631e0..000000000 --- a/iconos/Lambda.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/iconos/Tiers.svg b/iconos/Tiers.svg deleted file mode 100644 index d7d85d772..000000000 --- a/iconos/Tiers.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/iconos/Tools.svg b/iconos/Tools.svg new file mode 100644 index 000000000..7e22782c2 --- /dev/null +++ b/iconos/Tools.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/pkg/acl/endpoints.go b/pkg/acl/endpoints.go index 5b43d5e80..da87aea41 100644 --- a/pkg/acl/endpoints.go +++ b/pkg/acl/endpoints.go @@ -67,11 +67,13 @@ var ( remoteBuckets = "/remote-buckets" replication = "/replication" license = "/license" - watch = "/watch" - heal = "/heal" - trace = "/trace" - logs = "/logs" - healthInfo = "/health-info" + watch = "/tools/watch" + heal = "/tools/heal" + trace = "/tools/trace" + tools = "/tools" + logs = "/tools/logs" + auditLogs = "/tools/audit-logs" + healthInfo = "/tools/diagnostics" ) type ConfigurationActionSet struct { @@ -261,6 +263,16 @@ var logsActionSet = ConfigurationActionSet{ ), } +// toolsActionSet contains the list of admin actions required for this endpoint to work +var toolsActionSet = ConfigurationActionSet{ + actionTypes: iampolicy.NewActionSet( + iampolicy.AllAdminActions, + ), + actions: iampolicy.NewActionSet( + iampolicy.ConsoleLogAdminAction, + ), +} + // traceActionSet contains the list of admin actions required for this endpoint to work var traceActionSet = ConfigurationActionSet{ actionTypes: iampolicy.NewActionSet( @@ -327,6 +339,8 @@ var endpointRules = map[string]ConfigurationActionSet{ heal: healActionSet, trace: traceActionSet, logs: logsActionSet, + auditLogs: logsActionSet, + tools: toolsActionSet, healthInfo: healthInfoActionSet, } diff --git a/pkg/acl/endpoints_test.go b/pkg/acl/endpoints_test.go index 0e74c54a6..70709f12b 100644 --- a/pkg/acl/endpoints_test.go +++ b/pkg/acl/endpoints_test.go @@ -70,7 +70,7 @@ func TestGetAuthorizedEndpoints(t *testing.T) { "admin:*", }, }, - want: 30, + want: 32, }, { name: "all s3 endpoints", @@ -89,7 +89,7 @@ func TestGetAuthorizedEndpoints(t *testing.T) { "s3:*", }, }, - want: 32, + want: 34, }, { name: "Console User - default endpoints", diff --git a/portal-ui/src/common/BackLink.tsx b/portal-ui/src/common/BackLink.tsx index 8a25cd90b..ed584af88 100644 --- a/portal-ui/src/common/BackLink.tsx +++ b/portal-ui/src/common/BackLink.tsx @@ -27,6 +27,10 @@ const styles = (theme: Theme) => link: { textDecoration: "none", color: theme.palette.primary.main, + fontSize: 18, + fontWeight: 600, + marginBottom: 10, + marginTop: 10, }, }); diff --git a/portal-ui/src/common/Title.tsx b/portal-ui/src/common/Title.tsx deleted file mode 100644 index 078dc4f9b..000000000 --- a/portal-ui/src/common/Title.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import React from "react"; -import PropTypes from "prop-types"; -import Typography from "@mui/material/Typography"; - -export default function Title(props: React.Props) { - return ( - - {props.children} - - ); -} - -Title.propTypes = { - children: PropTypes.node, -}; diff --git a/portal-ui/src/icons/DeleteIcon.tsx b/portal-ui/src/icons/DeleteIcon.tsx index 3b5bca927..647a17916 100644 --- a/portal-ui/src/icons/DeleteIcon.tsx +++ b/portal-ui/src/icons/DeleteIcon.tsx @@ -16,7 +16,6 @@ import React from "react"; import { SvgIcon, SvgIconProps } from "@mui/material"; -import { IIcon } from "./props"; const DeleteIcon = (props: SvgIconProps) => { return ( diff --git a/portal-ui/src/icons/ToolsIcon.tsx b/portal-ui/src/icons/ToolsIcon.tsx new file mode 100644 index 000000000..4922ee8bd --- /dev/null +++ b/portal-ui/src/icons/ToolsIcon.tsx @@ -0,0 +1,45 @@ +// 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 . + +import * as React from "react"; +import { SvgIcon, SvgIconProps } from "@mui/material"; + +const ToolsIcon = (props: SvgIconProps) => { + return ( + + + + + + + + + + + + ); +}; + +export default ToolsIcon; diff --git a/portal-ui/src/icons/index.ts b/portal-ui/src/icons/index.ts index 2527ce846..3a8be98a8 100644 --- a/portal-ui/src/icons/index.ts +++ b/portal-ui/src/icons/index.ts @@ -102,3 +102,4 @@ export { default as UptimeIcon } from "./UptimeIcon"; export { default as LambdaIcon } from "./LambdaIcon"; export { default as TiersIcon } from "./TiersIcon"; export { default as OpenListIcon } from "./OpenListIcon"; +export { default as ToolsIcon } from "./ToolsIcon"; diff --git a/portal-ui/src/screens/Console/Account/Account.tsx b/portal-ui/src/screens/Console/Account/Account.tsx index 3fe355761..fc41b282c 100644 --- a/portal-ui/src/screens/Console/Account/Account.tsx +++ b/portal-ui/src/screens/Console/Account/Account.tsx @@ -14,7 +14,7 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -import React, { useEffect, useState } from "react"; +import React, { Fragment, useEffect, useState } from "react"; import { connect } from "react-redux"; import { Theme } from "@mui/material/styles"; import createStyles from "@mui/styles/createStyles"; @@ -22,13 +22,12 @@ import withStyles from "@mui/styles/withStyles"; import Grid from "@mui/material/Grid"; import api from "../../../common/api"; import { Button, IconButton, Tooltip } from "@mui/material"; -import Typography from "@mui/material/Typography"; import { NewServiceAccount } from "../Common/CredentialsPrompt/types"; import { setErrorSnackMessage } from "../../../actions"; import AddServiceAccount from "./AddServiceAccount"; import DeleteServiceAccount from "./DeleteServiceAccount"; import CredentialsPrompt from "../Common/CredentialsPrompt/CredentialsPrompt"; -import { AddIcon, LockIcon } from "../../../icons"; +import { AccountIcon, AddIcon, LockIcon } from "../../../icons"; import TextField from "@mui/material/TextField"; import InputAdornment from "@mui/material/InputAdornment"; import TableWrapper from "../Common/TableWrapper/TableWrapper"; @@ -42,6 +41,7 @@ import { import { ErrorResponseHandler } from "../../../common/types"; import ChangePasswordModal from "./ChangePasswordModal"; import SearchIcon from "../../../icons/SearchIcon"; +import HelpBox from "../../../common/HelpBox"; const styles = (theme: Theme) => createStyles({ @@ -75,6 +75,9 @@ const styles = (theme: Theme) => }, }, }, + twHeight: { + minHeight: 600, + }, imageIcon: { height: "100%", }, @@ -212,7 +215,7 @@ const Account = ({ closeModal={() => setChangePasswordModalOpen(false)} /> {changePassword && ( @@ -231,60 +234,79 @@ const Account = ({ } /> - - - - - Service Accounts - - - -
-
- - - - - ), - }} - onChange={(e) => { - setFilter(e.target.value); - }} - variant="standard" - /> - - - -
-
- - - + + + + + + ), + }} + onChange={(e) => { + setFilter(e.target.value); + }} + variant="standard" + /> + + + +
+
+ + + + + } + help={ + + MinIO service accounts are child identities of an authenticated + MinIO user, including externally managed identities. Each + service account inherits its privileges based on the policies + attached to it’s parent user or those groups in which the parent + user has membership. Service accounts also support an optional + inline policy which further restricts access to a subset of + actions and resources available to the parent user. +
+
+ You can learn more at our{" "} + + documentation + + . +
+ } + />
diff --git a/portal-ui/src/screens/Console/Buckets/ListBuckets/ListBuckets.tsx b/portal-ui/src/screens/Console/Buckets/ListBuckets/ListBuckets.tsx index b21e8e6f8..45755a574 100644 --- a/portal-ui/src/screens/Console/Buckets/ListBuckets/ListBuckets.tsx +++ b/portal-ui/src/screens/Console/Buckets/ListBuckets/ListBuckets.tsx @@ -25,15 +25,14 @@ import TextField from "@mui/material/TextField"; import InputAdornment from "@mui/material/InputAdornment"; import FileCopyIcon from "@mui/icons-material/FileCopy"; import { Bucket, BucketList, HasPermissionResponse } from "../types"; -import { - AddIcon, - BucketsIcon, - WatchIcon, -} from "../../../../icons"; +import { AddIcon, BucketsIcon, WatchIcon } from "../../../../icons"; import { AppState } from "../../../../store"; import { addBucketOpen, addBucketReset } from "../actions"; import { setErrorSnackMessage } from "../../../../actions"; -import { containerForHeader, linkStyles } from "../../Common/FormComponents/common/styleLibrary"; +import { + containerForHeader, + linkStyles, +} from "../../Common/FormComponents/common/styleLibrary"; import { ErrorResponseHandler } from "../../../../common/types"; import api from "../../../../common/api"; import AddBucket from "./AddBucket"; diff --git a/portal-ui/src/screens/Console/Common/SettingsCard/SettingsCard.tsx b/portal-ui/src/screens/Console/Common/SettingsCard/SettingsCard.tsx index 617dbca8f..465aa5244 100644 --- a/portal-ui/src/screens/Console/Common/SettingsCard/SettingsCard.tsx +++ b/portal-ui/src/screens/Console/Common/SettingsCard/SettingsCard.tsx @@ -24,6 +24,7 @@ import { IElement } from "../../Configurations/types"; interface ISettingsCard { classes: any; configuration: IElement; + prefix?: string; } const styles = (theme: Theme) => @@ -55,10 +56,14 @@ const styles = (theme: Theme) => }, }); -const SettingsCard = ({ classes, configuration }: ISettingsCard) => { +const SettingsCard = ({ + classes, + configuration, + prefix = "settings", +}: ISettingsCard) => { return ( {configuration.icon} diff --git a/portal-ui/src/screens/Console/Common/SlideOptions/SlideOptions.tsx b/portal-ui/src/screens/Console/Common/SlideOptions/SlideOptions.tsx deleted file mode 100644 index eaf187e3c..000000000 --- a/portal-ui/src/screens/Console/Common/SlideOptions/SlideOptions.tsx +++ /dev/null @@ -1,84 +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 . - -import React, { Fragment } from "react"; -import { AutoSizer } from "react-virtualized"; -import createStyles from "@mui/styles/createStyles"; -import withStyles from "@mui/styles/withStyles"; - -interface ISlideOptions { - classes: any; - slideOptions: any; - currentSlide: number; -} - -const styles = () => - createStyles({ - masterContainer: { - overflowX: "hidden", - overflowY: "auto", - }, - sliderContainer: { - width: "auto", - transitionDuration: "0.3s", - position: "relative", - }, - slide: { - float: "left", - }, - }); - -const SlideOptions = ({ - classes, - slideOptions, - currentSlide, -}: ISlideOptions) => { - return ( - - {({ width, height }: any) => { - const currentSliderPosition = currentSlide * width; - const containerSize = width * slideOptions.length; - return ( - -
-
- {slideOptions.map((block: any, index: number) => { - return ( -
- {block} -
- ); - })} -
-
-
- ); - }} -
- ); -}; - -export default withStyles(styles)(SlideOptions); diff --git a/portal-ui/src/screens/Console/Common/TableWrapper/TableActionIcons/DescriptionIcon.tsx b/portal-ui/src/screens/Console/Common/TableWrapper/TableActionIcons/DescriptionIcon.tsx deleted file mode 100644 index 03674dfd9..000000000 --- a/portal-ui/src/screens/Console/Common/TableWrapper/TableActionIcons/DescriptionIcon.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import React from "react"; -import { IIcon, selected, unSelected } from "./common"; - -const DescriptionIcon = ({ active = false }: IIcon) => { - return ( - - - - ); -}; - -export default DescriptionIcon; diff --git a/portal-ui/src/screens/Console/Configurations/ConfigurationPanels/ConfigurationOptions.tsx b/portal-ui/src/screens/Console/Configurations/ConfigurationPanels/ConfigurationOptions.tsx index 52f03e2d0..8b173fa6f 100644 --- a/portal-ui/src/screens/Console/Configurations/ConfigurationPanels/ConfigurationOptions.tsx +++ b/portal-ui/src/screens/Console/Configurations/ConfigurationPanels/ConfigurationOptions.tsx @@ -28,6 +28,8 @@ import { } from "../../Common/FormComponents/common/styleLibrary"; import PageHeader from "../../Common/PageHeader/PageHeader"; import SettingsCard from "../../Common/SettingsCard/SettingsCard"; +import HelpBox from "../../../../common/HelpBox"; +import { SettingsIcon } from "../../../../icons"; interface IConfigurationOptions { classes: any; @@ -91,6 +93,29 @@ const ConfigurationOptions = ({ classes }: IConfigurationOptions) => {
+ + } + help={ + + MinIO supports a variety of configurations ranging from + encryption, compression, region, notifications, etc. +
+
+ You can learn more at our{" "} + + documentation + + . +
+ } + /> +
); diff --git a/portal-ui/src/screens/Console/Configurations/ConfigurationPanels/ConfigurationsList.tsx b/portal-ui/src/screens/Console/Configurations/ConfigurationPanels/ConfigurationsList.tsx deleted file mode 100644 index bf2711d34..000000000 --- a/portal-ui/src/screens/Console/Configurations/ConfigurationPanels/ConfigurationsList.tsx +++ /dev/null @@ -1,152 +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 . - -import React, { useState, Fragment } from "react"; -import get from "lodash/get"; -import { Theme } from "@mui/material/styles"; -import createStyles from "@mui/styles/createStyles"; -import withStyles from "@mui/styles/withStyles"; -import Grid from "@mui/material/Grid"; -import history from "../../../../history"; -import TableWrapper from "../../Common/TableWrapper/TableWrapper"; -import { configurationElements } from "../utils"; -import { IConfigurationElement } from "../types"; -import EditConfiguration from "../../NotificationEndpoints/CustomForms/EditConfiguration"; -import { - actionsTray, - containerForHeader, - searchField, - settingsCommon, -} from "../../Common/FormComponents/common/styleLibrary"; -import SlideOptions from "../../Common/SlideOptions/SlideOptions"; -import BackSettingsIcon from "../../../../icons/BackSettingsIcon"; - -interface IListConfiguration { - classes: any; - history: any; -} - -const styles = (theme: Theme) => - createStyles({ - strongText: { - fontWeight: 700, - }, - keyName: { - marginLeft: 5, - }, - iconText: { - lineHeight: "24px", - }, - customConfigurationPage: { - height: "calc(100vh - 324px)", - scrollbarWidth: "none" as const, - "&::-webkit-scrollbar": { - display: "none", - }, - }, - ...searchField, - ...actionsTray, - ...settingsCommon, - ...containerForHeader(theme.spacing(4)), - }); - -const initialConfiguration = { - configuration_id: "", - configuration_label: "", -}; - -const ConfigurationsList = ({ classes, history }: IListConfiguration) => { - const [selectedConfiguration, setSelectedConfiguration] = - useState(initialConfiguration); - const [currentConfiguration, setCurrentConfiguration] = useState(0); - - const tableActions = [ - { - type: "edit", - onClick: (element: IConfigurationElement) => { - const url = get(element, "url", ""); - if (url !== "") { - // We redirect Browser - history.push(url); - } else { - setCurrentConfiguration(1); - setSelectedConfiguration(element); - } - }, - }, - ]; - - const backToInitialConfig = () => { - setCurrentConfiguration(0); - setSelectedConfiguration(initialConfiguration); - }; - - return ( - - - - -
- - - , - - - - - - {currentConfiguration === 1 ? ( - - ) : null} - - , - ]} - currentSlide={currentConfiguration} - /> -
-
-
-
-
- ); -}; - -export default withStyles(styles)(ConfigurationsList); diff --git a/portal-ui/src/screens/Console/Configurations/TiersConfiguration/ListTiersConfiguration.tsx b/portal-ui/src/screens/Console/Configurations/TiersConfiguration/ListTiersConfiguration.tsx index e9649b086..991e6f5ec 100644 --- a/portal-ui/src/screens/Console/Configurations/TiersConfiguration/ListTiersConfiguration.tsx +++ b/portal-ui/src/screens/Console/Configurations/TiersConfiguration/ListTiersConfiguration.tsx @@ -20,7 +20,7 @@ import { connect } from "react-redux"; import { Theme } from "@mui/material/styles"; import createStyles from "@mui/styles/createStyles"; import withStyles from "@mui/styles/withStyles"; -import { IconButton, LinearProgress, TextField } from "@mui/material"; +import { LinearProgress, TextField } from "@mui/material"; import Grid from "@mui/material/Grid"; import Button from "@mui/material/Button"; import InputAdornment from "@mui/material/InputAdornment"; diff --git a/portal-ui/src/screens/Console/Console.tsx b/portal-ui/src/screens/Console/Console.tsx index ec541b47b..12fee6ec3 100644 --- a/portal-ui/src/screens/Console/Console.tsx +++ b/portal-ui/src/screens/Console/Console.tsx @@ -47,7 +47,6 @@ import ConfigurationMain from "./Configurations/ConfigurationMain"; import TenantDetails from "./Tenants/TenantDetails/TenantDetails"; import License from "./License/License"; import Trace from "./Trace/Trace"; -import LogsMain from "./Logs/LogsMain"; import Heal from "./Heal/Heal"; import Watch from "./Watch/Watch"; import HealthInfo from "./HealthInfo/HealthInfo"; @@ -63,6 +62,9 @@ import ListTiersConfiguration from "./Configurations/TiersConfiguration/ListTier import TierTypeSelector from "./Configurations/TiersConfiguration/TierTypeSelector"; import AddTierConfiguration from "./Configurations/TiersConfiguration/AddTierConfiguration"; import ListTenants from "./Tenants/ListTenants/ListTenants"; +import Tools from "./Tools/Tools"; +import ErrorLogs from "./Logs/ErrorLogs/ErrorLogs"; +import LogsSearchMain from "./Logs/LogSearch/LogsSearchMain"; const drawerWidth = 245; @@ -243,7 +245,7 @@ const Console = ({ }, { component: Watch, - path: "/watch", + path: "/tools/watch", }, { component: Users, @@ -267,19 +269,27 @@ const Console = ({ }, { component: Heal, - path: "/heal", + path: "/tools/heal", }, { component: Trace, - path: "/trace", - }, - { - component: LogsMain, - path: "/logs", + path: "/tools/trace", }, { component: HealthInfo, - path: "/health-info", + path: "/tools/diagnostics", + }, + { + component: ErrorLogs, + path: "/tools/logs", + }, + { + component: LogsSearchMain, + path: "/tools/audit-logs", + }, + { + component: Tools, + path: "/tools", }, { component: ConfigurationMain, diff --git a/portal-ui/src/screens/Console/Dashboard/Chart.tsx b/portal-ui/src/screens/Console/Dashboard/Chart.tsx deleted file mode 100644 index 5f2a4bda1..000000000 --- a/portal-ui/src/screens/Console/Dashboard/Chart.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import React from "react"; -import { useTheme } from "@mui/material/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 }; -} - -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), -]; - -export default function Chart() { - const theme = useTheme(); - - return ( - - Today - - - - - - - - - - - ); -} diff --git a/portal-ui/src/screens/Console/Dashboard/Deposits.tsx b/portal-ui/src/screens/Console/Dashboard/Deposits.tsx deleted file mode 100644 index 50dd3dc19..000000000 --- a/portal-ui/src/screens/Console/Dashboard/Deposits.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import React from "react"; -import Link from "@mui/material/Link"; -import makeStyles from "@mui/styles/makeStyles"; -import Typography from "@mui/material/Typography"; -import Title from "../../../common/Title"; - -function preventDefault(event: React.MouseEvent) { - event.preventDefault(); -} - -const useStyles = makeStyles({ - depositContext: { - flex: 1, - }, -}); - -export default function Deposits() { - const classes = useStyles(); - return ( - - Recent Deposits - - $3,024.00 - - - on 15 March, 2019 - -
- - View balance - -
-
- ); -} diff --git a/portal-ui/src/screens/Console/Dashboard/Orders.tsx b/portal-ui/src/screens/Console/Dashboard/Orders.tsx deleted file mode 100644 index fe4a18ef5..000000000 --- a/portal-ui/src/screens/Console/Dashboard/Orders.tsx +++ /dev/null @@ -1,110 +0,0 @@ -import * as React from "react"; -import Link from "@mui/material/Link"; -import makeStyles from "@mui/styles/makeStyles"; -import Table from "@mui/material/Table"; -import TableBody from "@mui/material/TableBody"; -import TableCell from "@mui/material/TableCell"; -import TableHead from "@mui/material/TableHead"; -import TableRow from "@mui/material/TableRow"; -import Title from "../../../common/Title"; - -// Generate Order Data -function createData( - id: number, - date: string, - name: string, - shipTo: string, - paymentMethod: string, - amount: number -) { - return { id, date, name, shipTo, paymentMethod, amount }; -} - -const rows = [ - createData( - 0, - "16 Mar, 2019", - "Elvis Presley", - "Tupelo, MS", - "VISA ⠀•••• 3719", - 312.44 - ), - createData( - 1, - "16 Mar, 2019", - "Paul McCartney", - "London, UK", - "VISA ⠀•••• 2574", - 866.99 - ), - createData( - 2, - "16 Mar, 2019", - "Tom Scholz", - "Boston, MA", - "MC ⠀•••• 1253", - 100.81 - ), - createData( - 3, - "16 Mar, 2019", - "Michael Jackson", - "Gary, IN", - "AMEX ⠀•••• 2000", - 654.39 - ), - createData( - 4, - "15 Mar, 2019", - "Bruce Springsteen", - "Long Branch, NJ", - "VISA ⠀•••• 5919", - 212.79 - ), -]; - -function preventDefault(event: React.MouseEvent) { - event.preventDefault(); -} - -const useStyles = makeStyles((theme) => ({ - seeMore: { - marginTop: theme.spacing(3), - }, -})); - -export default function Orders() { - const classes = useStyles(); - return ( - - Recent Orders - - - - Date - Name - Ship To - Payment Method - Sale Amount - - - - {rows.map((row) => ( - - {row.date} - {row.name} - {row.shipTo} - {row.paymentMethod} - {row.amount} - - ))} - -
-
- - See more orders - -
-
- ); -} diff --git a/portal-ui/src/screens/Console/Groups/Groups.tsx b/portal-ui/src/screens/Console/Groups/Groups.tsx index 606ccd441..6ca2035f4 100644 --- a/portal-ui/src/screens/Console/Groups/Groups.tsx +++ b/portal-ui/src/screens/Console/Groups/Groups.tsx @@ -73,6 +73,9 @@ const styles = (theme: Theme) => whiteSpace: "normal", wordWrap: "break-word", }, + twHeight: { + minHeight: 600, + }, minTableHeader: { color: "#393939", "& tr": { @@ -241,6 +244,7 @@ const Groups = ({ classes, setErrorSnackMessage }: IGroupsProps) => { records={filteredRecords} entityName="Groups" idField="" + customPaperHeight={classes.twHeight} /> diff --git a/portal-ui/src/screens/Console/Heal/Heal.tsx b/portal-ui/src/screens/Console/Heal/Heal.tsx index d0b915952..9e4b3472d 100644 --- a/portal-ui/src/screens/Console/Heal/Heal.tsx +++ b/portal-ui/src/screens/Console/Heal/Heal.tsx @@ -17,27 +17,35 @@ import React, { useEffect, useState } from "react"; import { connect } from "react-redux"; import { HorizontalBar } from "react-chartjs-2"; -import { Button, Grid, TextField, InputBase } from "@mui/material"; +import { + Button, + FormControl, + Grid, + InputBase, + MenuItem, + Select, + TextField, +} from "@mui/material"; import { IMessageEvent, w3cwebsocket as W3CWebSocket } from "websocket"; import { Theme } from "@mui/material/styles"; import createStyles from "@mui/styles/createStyles"; import withStyles from "@mui/styles/withStyles"; import { wsProtocol } from "../../../utils/wsUtils"; -import { FormControl, MenuItem, Select } from "@mui/material"; -import { BucketList, Bucket } from "../Watch/types"; -import { HealStatus, colorH } from "./types"; +import { Bucket, BucketList } from "../Watch/types"; +import { colorH, HealStatus } from "./types"; import { niceBytes } from "../../../common/utils"; import { actionsTray, containerForHeader, - searchField, inlineCheckboxes, + searchField, } from "../Common/FormComponents/common/styleLibrary"; import { AppState } from "../../../store"; import { ErrorResponseHandler } from "../../../common/types"; import CheckboxWrapper from "../Common/FormComponents/CheckboxWrapper/CheckboxWrapper"; import PageHeader from "../Common/PageHeader/PageHeader"; import api from "../../../common/api"; +import BackLink from "../../../common/BackLink"; const styles = (theme: Theme) => createStyles({ @@ -242,123 +250,124 @@ const Heal = ({ classes, distributedSetup }: IHeal) => { - - - - - + + + + + + { + setPrefix(e.target.value); + }} + variant="standard" + /> + + + + { + setRecursive(e.target.checked); + }} + disabled={false} + label="Recursive" + /> + { + setForceStart(e.target.checked); + }} + disabled={false} + label="Force Start" + /> + { + setForceStop(e.target.checked); + }} + disabled={false} + label="Force Stop" + /> + + +
+
+ + + +
+ Size scanned: {hStatus.sizeScanned} +
+
+ Objects healed: {hStatus.objectsHealed} /{" "} + {hStatus.objectsScanned} +
+
+ Healing time: {hStatus.healDuration}s +
diff --git a/portal-ui/src/screens/Console/HealthInfo/HealthInfo.tsx b/portal-ui/src/screens/Console/HealthInfo/HealthInfo.tsx index 68302e3b6..f1f38e978 100644 --- a/portal-ui/src/screens/Console/HealthInfo/HealthInfo.tsx +++ b/portal-ui/src/screens/Console/HealthInfo/HealthInfo.tsx @@ -13,38 +13,39 @@ // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -import React, { useState, useEffect } from "react"; +import React, { useEffect, useState } from "react"; import { + ICloseEvent, IMessageEvent, w3cwebsocket as W3CWebSocket, - ICloseEvent, } from "websocket"; import { AppState } from "../../../store"; import { connect } from "react-redux"; import { healthInfoMessageReceived, healthInfoResetMessage } from "./actions"; import { - HealthInfoMessage, + DiagStatError, DiagStatInProgress, DiagStatSuccess, - DiagStatError, + HealthInfoMessage, } from "./types"; import { Theme } from "@mui/material/styles"; import createStyles from "@mui/styles/createStyles"; import withStyles from "@mui/styles/withStyles"; import { - wsProtocol, + WSCloseAbnormalClosure, WSCloseInternalServerErr, WSClosePolicyViolation, - WSCloseAbnormalClosure, + wsProtocol, } from "../../../utils/wsUtils"; import { actionsTray, containerForHeader, } from "../Common/FormComponents/common/styleLibrary"; -import { Grid, Button } from "@mui/material"; +import { Button, Grid } from "@mui/material"; import PageHeader from "../Common/PageHeader/PageHeader"; -import { setSnackBarMessage, setServerDiagStat } from "../../../actions"; +import { setServerDiagStat, setSnackBarMessage } from "../../../actions"; import CircularProgress from "@mui/material/CircularProgress"; +import BackLink from "../../../common/BackLink"; const styles = (theme: Theme) => createStyles({ @@ -66,6 +67,12 @@ const styles = (theme: Theme) => justifyContent: "flex-start", gap: 20, }, + boxy: { + border: "#E5E5E5 1px solid", + borderRadius: 2, + padding: 40, + backgroundColor: "#fff", + }, ...actionsTray, ...containerForHeader(theme.spacing(4)), }); @@ -200,8 +207,11 @@ const HealthInfo = ({ - - + + + + + - - - - - ( - - - {element.response_status_code} ({element.response_status}) - - - ), - renderFullObject: true, - }, - { - label: LogSearchColumnLabels.request_content_length, - elementKey: "request_content_length", - renderFunction: niceBytes, - }, - { - label: LogSearchColumnLabels.response_content_length, - elementKey: "response_content_length", - renderFunction: niceBytes, - }, - { - label: LogSearchColumnLabels.time_to_response_ns, - elementKey: "time_to_response_ns", - renderFunction: nsToSeconds, - contentTextAlign: "right", - }, - ]} - isLoading={loading} - records={records} - entityName="Logs" - customEmptyMessage={"There is no information with this criteria"} - idField="request_id" - columnsSelector - columnsShown={columnsShown} - onColumnChange={selectColumn} - customPaperHeight={ - filterOpen ? classes.tableFOpen : classes.tableFClosed - } - sortConfig={{ - currentSort: "time", - currentDirection: sortOrder, - triggerSort: sortChange, - }} - infiniteScrollConfig={{ - recordsCount: 1000000, - loadMoreRecords: loadMoreRecords, - }} - itemActions={[ - { - type: "view", - onClick: openExtraInformation, - }, - ]} - textSelectable - /> +
+ +
+ +
+ + ( + + + {element.response_status_code} ( + {element.response_status}) + + + ), + renderFullObject: true, + }, + { + label: LogSearchColumnLabels.request_content_length, + elementKey: "request_content_length", + renderFunction: niceBytes, + }, + { + label: LogSearchColumnLabels.response_content_length, + elementKey: "response_content_length", + renderFunction: niceBytes, + }, + { + label: LogSearchColumnLabels.time_to_response_ns, + elementKey: "time_to_response_ns", + renderFunction: nsToSeconds, + contentTextAlign: "right", + }, + ]} + isLoading={loading} + records={records} + entityName="Logs" + customEmptyMessage={"There is no information with this criteria"} + idField="request_id" + columnsSelector + columnsShown={columnsShown} + onColumnChange={selectColumn} + customPaperHeight={ + filterOpen ? classes.tableFOpen : classes.tableFClosed + } + sortConfig={{ + currentSort: "time", + currentDirection: sortOrder, + triggerSort: sortChange, + }} + infiniteScrollConfig={{ + recordsCount: 1000000, + loadMoreRecords: loadMoreRecords, + }} + itemActions={[ + { + type: "view", + onClick: openExtraInformation, + }, + ]} + textSelectable + /> +
diff --git a/portal-ui/src/screens/Console/Logs/LogsMain.tsx b/portal-ui/src/screens/Console/Logs/LogsMain.tsx deleted file mode 100644 index 888f81dd4..000000000 --- a/portal-ui/src/screens/Console/Logs/LogsMain.tsx +++ /dev/null @@ -1,102 +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 . - -import React, { Fragment, useState } from "react"; -import { connect } from "react-redux"; -import PageHeader from "../Common/PageHeader/PageHeader"; -import { Grid, List, ListItem, ListItemText } from "@mui/material"; -import { Theme } from "@mui/material/styles"; -import createStyles from "@mui/styles/createStyles"; -import withStyles from "@mui/styles/withStyles"; -import { containerForHeader } from "../Common/FormComponents/common/styleLibrary"; -import ErrorLogs from "./ErrorLogs/ErrorLogs"; -import LogsSearchMain from "./LogSearch/LogsSearchMain"; -import { AppState } from "../../../store"; - -interface ILogsMainProps { - classes: any; - features: string[] | null; -} - -const styles = (theme: Theme) => - createStyles({ - headerLabel: { - fontSize: 22, - fontWeight: 600, - color: "#000", - marginTop: 4, - }, - ...containerForHeader(theme.spacing(4)), - }); - -const LogsMain = ({ classes, features }: ILogsMainProps) => { - const [currentTab, setCurrentTab] = useState(0); - - const logSearchEnabled = features && features.includes("log-search"); - - return ( - - - - - - { - setCurrentTab(0); - }} - > - - - { - setCurrentTab(1); - }} - > - - - - - - {currentTab === 0 && ( - -

Error Logs

- -
- )} - {currentTab === 1 && logSearchEnabled && ( - -

Audit Logs

- -
- )} -
-
-
- ); -}; - -const mapState = (state: AppState) => ({ - features: state.console.session.features, -}); - -const connector = connect(mapState, null); - -export default withStyles(styles)(connector(LogsMain)); diff --git a/portal-ui/src/screens/Console/Menu/Menu.tsx b/portal-ui/src/screens/Console/Menu/Menu.tsx index be9d164d3..833103633 100644 --- a/portal-ui/src/screens/Console/Menu/Menu.tsx +++ b/portal-ui/src/screens/Console/Menu/Menu.tsx @@ -36,7 +36,7 @@ import { IAMPoliciesIcon, LambdaIcon, TiersIcon, - TraceIcon, + ToolsIcon, UsersIcon, VersionIcon, } from "../../../icons"; @@ -45,15 +45,12 @@ import { clearSession } from "../../../common/utils"; import LicenseIcon from "../../../icons/LicenseIcon"; import LogoutIcon from "../../../icons/LogoutIcon"; import HealIcon from "../../../icons/HealIcon"; -import WatchIcon from "../../../icons/WatchIcon"; import OperatorLogo from "../../../icons/OperatorLogo"; import ConsoleLogo from "../../../icons/ConsoleLogo"; import history from "../../../history"; import api from "../../../common/api"; import AccountIcon from "../../../icons/AccountIcon"; -import DiagnosticsIcon from "../../../icons/DiagnosticsIcon"; import DocumentationIcon from "../../../icons/DocumentationIcon"; -import LogsIcon from "../../../icons/LogsIcon"; import SettingsIcon from "../../../icons/SettingsIcon"; import StorageIcon from "../../../icons/StorageIcon"; import TenantsOutlinedIcon from "../../../icons/TenantsOutlineIcon"; @@ -383,28 +380,12 @@ const Menu = ({ icon: , }, { - group: "Tools", + group: "common", type: "item", component: NavLink, - to: "/logs", - name: "Logs", - icon: , - }, - { - group: "Tools", - type: "item", - component: NavLink, - to: "/watch", - name: "Watch", - icon: , - }, - { - group: "Tools", - type: "item", - component: NavLink, - to: "/trace", - name: "Trace", - icon: , + to: "/tools", + name: "Tools", + icon: , }, { group: "Tools", @@ -415,14 +396,6 @@ const Menu = ({ icon: , fsHidden: distributedSetup, }, - { - group: "Tools", - type: "item", - component: NavLink, - to: "/health-info", - name: "Diagnostic", - icon: , - }, { group: "Operator", diff --git a/portal-ui/src/screens/Console/NotificationEndpoints/ListNotificationEndpoints.tsx b/portal-ui/src/screens/Console/NotificationEndpoints/ListNotificationEndpoints.tsx index fc35fd2e2..a63837184 100644 --- a/portal-ui/src/screens/Console/NotificationEndpoints/ListNotificationEndpoints.tsx +++ b/portal-ui/src/screens/Console/NotificationEndpoints/ListNotificationEndpoints.tsx @@ -19,7 +19,7 @@ import { connect } from "react-redux"; import { Theme } from "@mui/material/styles"; import createStyles from "@mui/styles/createStyles"; import withStyles from "@mui/styles/withStyles"; -import { IconButton, LinearProgress, TextField } from "@mui/material"; +import { LinearProgress, TextField } from "@mui/material"; import { red } from "@mui/material/colors"; import Grid from "@mui/material/Grid"; import FiberManualRecordIcon from "@mui/icons-material/FiberManualRecord"; diff --git a/portal-ui/src/screens/Console/Policies/ListPolicies.tsx b/portal-ui/src/screens/Console/Policies/ListPolicies.tsx index eac0cb804..f3088ce93 100644 --- a/portal-ui/src/screens/Console/Policies/ListPolicies.tsx +++ b/portal-ui/src/screens/Console/Policies/ListPolicies.tsx @@ -14,7 +14,7 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -import React, { useState, useEffect } from "react"; +import React, { Fragment, useEffect, useState } from "react"; import { connect } from "react-redux"; import get from "lodash/get"; import { Theme } from "@mui/material/styles"; @@ -25,7 +25,7 @@ import Grid from "@mui/material/Grid"; import TextField from "@mui/material/TextField"; import InputAdornment from "@mui/material/InputAdornment"; import { Policy, PolicyList } from "./types"; -import { AddIcon } from "../../../icons"; +import { AddIcon, IAMPoliciesIcon } from "../../../icons"; import { setErrorSnackMessage } from "../../../actions"; import { actionsTray, @@ -40,6 +40,7 @@ import PageHeader from "../Common/PageHeader/PageHeader"; import api from "../../../common/api"; import history from "../../../history"; import SearchIcon from "../../../icons/SearchIcon"; +import HelpBox from "../../../common/HelpBox"; const styles = (theme: Theme) => createStyles({ @@ -68,6 +69,9 @@ const styles = (theme: Theme) => }, }, }, + twHeight: { + minHeight: 600, + }, ...actionsTray, ...searchField, ...containerForHeader(theme.spacing(4)), @@ -175,52 +179,84 @@ const ListPolicies = ({ classes, setErrorSnackMessage }: IPoliciesProps) => { /> )} - - - - { - setFilterPolicies(val.target.value); - }} - InputProps={{ - disableUnderline: true, - startAdornment: ( - - - - ), - }} - variant="standard" - /> - - - -
-
- - - + + + { + setFilterPolicies(val.target.value); + }} + InputProps={{ + disableUnderline: true, + startAdornment: ( + + + + ), + }} + variant="standard" + /> + + + +
+
+ + + + + } + help={ + + MinIO uses Policy-Based Access Control (PBAC) to define the + authorized actions and resources to which an authenticated user + has access. Each policy describes one or more actions and + conditions that outline the permissions of a user or group of + users. +
+
+ MinIO PBAC is built for compatibility with AWS IAM policy + syntax, structure, and behavior. The MinIO documentation makes a + best-effort to cover IAM-specific behavior and functionality. + Consider deferring to the IAM documentation for more complete + documentation on AWS IAM-specific topics. +
+
+ You can learn more at our{" "} + + documentation + + . +
+ } + />
diff --git a/portal-ui/src/screens/Console/Tenants/AddTenant/Steps/Preview.tsx b/portal-ui/src/screens/Console/Tenants/AddTenant/Steps/Preview.tsx deleted file mode 100644 index b43188c47..000000000 --- a/portal-ui/src/screens/Console/Tenants/AddTenant/Steps/Preview.tsx +++ /dev/null @@ -1,150 +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 . - -import React, { Fragment } from "react"; -import { connect } from "react-redux"; -import { Theme } from "@mui/material/styles"; -import createStyles from "@mui/styles/createStyles"; -import withStyles from "@mui/styles/withStyles"; -import Table from "@mui/material/Table"; -import TableBody from "@mui/material/TableBody"; -import TableCell from "@mui/material/TableCell"; -import TableRow from "@mui/material/TableRow"; -import { AppState } from "../../../../../store"; -import { - modalBasic, - wizardCommon, -} from "../../../Common/FormComponents/common/styleLibrary"; -import { Paper } from "@mui/material"; - -interface IPreviewProps { - classes: any; - tenantName: string; - customImage: boolean; - imageName: string; - namespace: string; - selectedStorageClass: string; - volumeSize: string; - sizeFactor: string; - advancedMode: boolean; - enableTLS: boolean; -} - -const styles = (theme: Theme) => - createStyles({ - buttonContainer: { - textAlign: "right", - }, - ...modalBasic, - ...wizardCommon, - }); - -const Preview = ({ - classes, - tenantName, - customImage, - imageName, - namespace, - selectedStorageClass, - volumeSize, - sizeFactor, - advancedMode, - enableTLS, -}: IPreviewProps) => { - return ( - -
-

Review

- - Review the details of the new tenant - -
- - - - - Tenant Name - - {tenantName} - - - {customImage && ( - - - - MinIO Image - - {imageName} - - - )} - - {namespace !== "" && ( - - - Namespace - - {namespace} - - )} - - - - Storage Class - - {selectedStorageClass} - - - - - Total Size - - - {volumeSize} {sizeFactor} - - - {advancedMode && ( - - - - Enable TLS - - {enableTLS ? "Enabled" : "Disabled"} - - - )} - -
-
- ); -}; - -const mapState = (state: AppState) => ({ - advancedMode: state.tenants.createTenant.advancedModeOn, - enableTLS: state.tenants.createTenant.fields.security.enableTLS, - tenantName: state.tenants.createTenant.fields.nameTenant.tenantName, - selectedStorageClass: - state.tenants.createTenant.fields.nameTenant.selectedStorageClass, - customImage: state.tenants.createTenant.fields.configure.customImage, - imageName: state.tenants.createTenant.fields.configure.imageName, - namespace: state.tenants.createTenant.fields.nameTenant.namespace, - volumeSize: state.tenants.createTenant.fields.tenantSize.volumeSize, - sizeFactor: state.tenants.createTenant.fields.tenantSize.sizeFactor, -}); - -const connector = connect(mapState, {}); - -export default withStyles(styles)(connector(Preview)); diff --git a/portal-ui/src/screens/Console/Tenants/ListTenants/ListTenants.tsx b/portal-ui/src/screens/Console/Tenants/ListTenants/ListTenants.tsx index 1ee2d3346..8345b0306 100644 --- a/portal-ui/src/screens/Console/Tenants/ListTenants/ListTenants.tsx +++ b/portal-ui/src/screens/Console/Tenants/ListTenants/ListTenants.tsx @@ -19,7 +19,7 @@ import { connect } from "react-redux"; import Grid from "@mui/material/Grid"; import TextField from "@mui/material/TextField"; import InputAdornment from "@mui/material/InputAdornment"; -import { Box, Button, IconButton, LinearProgress } from "@mui/material"; +import { Box, Button, LinearProgress } from "@mui/material"; import { Theme } from "@mui/material/styles"; import createStyles from "@mui/styles/createStyles"; import withStyles from "@mui/styles/withStyles"; diff --git a/portal-ui/src/screens/Console/Tenants/TenantDetails/ReplicationSetup.tsx b/portal-ui/src/screens/Console/Tenants/TenantDetails/ReplicationSetup.tsx deleted file mode 100644 index 2d839ef36..000000000 --- a/portal-ui/src/screens/Console/Tenants/TenantDetails/ReplicationSetup.tsx +++ /dev/null @@ -1,219 +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 . -import React, { useState } from "react"; -import { Theme } from "@mui/material/styles"; -import createStyles from "@mui/styles/createStyles"; -import withStyles from "@mui/styles/withStyles"; -import { modalBasic } from "../../Common/FormComponents/common/styleLibrary"; -import Grid from "@mui/material/Grid"; -import InputBoxWrapper from "../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper"; -import SelectWrapper from "../../Common/FormComponents/SelectWrapper/SelectWrapper"; -import { Button, LinearProgress, SelectChangeEvent } from "@mui/material"; -import ModalWrapper from "../../Common/ModalWrapper/ModalWrapper"; -import Tab from "@mui/material/Tab"; -import Tabs from "@mui/material/Tabs"; - -interface IReplicationProps { - classes: any; - open: boolean; - closeModalAndRefresh: (refreshList: boolean) => void; -} - -interface IDropDownElements { - label: string; - value: string; -} - -const styles = (theme: Theme) => - createStyles({ - buttonContainer: { - textAlign: "right", - }, - multiContainer: { - display: "flex", - alignItems: "center" as const, - justifyContent: "flex-start" as const, - }, - sizeFactorContainer: { - marginLeft: 8, - }, - ...modalBasic, - }); - -const ReplicationSetup = ({ - classes, - open, - closeModalAndRefresh, -}: IReplicationProps) => { - const [addSending, setAddSending] = useState(false); - const [selectedTab, setSelectedTab] = useState(0); - const [sourceBucket, setSourceBucket] = useState(""); - const [clusterSelected, setClusterSelected] = useState(""); - const [destinationBucket, setDestinationBucket] = useState(""); - const [address, setAddress] = useState(""); - const [bucket, setBucket] = useState(""); - const [accessKey, setAccessKey] = useState(""); - const [secretKey, setSecretKey] = useState(""); - - const clustersList: IDropDownElements[] = []; - const sourceBuckets: IDropDownElements[] = []; - const destinationBuckets: IDropDownElements[] = []; - - return ( - { - closeModalAndRefresh(false); - }} - > -
) => { - e.preventDefault(); - setAddSending(true); - }} - > - - ) => { - setSourceBucket(e.target.value as string); - }} - value={sourceBucket} - name="source_bucket" - id="source_bucket" - /> - - - { - setSelectedTab(newValue); - }} - aria-label="cluster-tabs" - variant="scrollable" - scrollButtons="auto" - > - - - - - -
-
- {selectedTab === 0 && ( - - - ) => { - setClusterSelected(e.target.value as string); - }} - value={clusterSelected} - name="cluster" - id="cluster" - /> - - - ) => { - setDestinationBucket(e.target.value as string); - }} - value={destinationBucket} - name="destination_bucket" - id="destination_bucket" - /> - - - )} - - {selectedTab === 1 && ( - - - ) => { - setAddress(e.target.value); - }} - label="Address" - value={address} - /> - - - ) => { - setBucket(e.target.value); - }} - label="Bucket" - value={bucket} - /> - - - ) => { - setAccessKey(e.target.value); - }} - label="Access Key" - value={accessKey} - /> - - - ) => { - setSecretKey(e.target.value); - }} - label="Secret Key" - value={secretKey} - /> - - - )} - - - - {addSending && ( - - - - )} -
-
- ); -}; - -export default withStyles(styles)(ReplicationSetup); diff --git a/portal-ui/src/screens/Console/Account/types.tsx b/portal-ui/src/screens/Console/Tools/Tools.tsx similarity index 61% rename from portal-ui/src/screens/Console/Account/types.tsx rename to portal-ui/src/screens/Console/Tools/Tools.tsx index dfb1f210f..ee2b2e030 100644 --- a/portal-ui/src/screens/Console/Account/types.tsx +++ b/portal-ui/src/screens/Console/Tools/Tools.tsx @@ -14,7 +14,21 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -export interface ServiceAccountsList { - service_accounts: string[]; - total: number; -} +import React from "react"; +import { Route, Router, Switch } from "react-router-dom"; +import history from "../../../history"; +import NotFoundPage from "../../NotFoundPage"; +import ToolsList from "./ToolsPanel/ToolsList"; + +const Tools = () => { + return ( + + + + + + + ); +}; + +export default Tools; diff --git a/portal-ui/src/screens/Console/Tools/ToolsPanel/ToolsList.tsx b/portal-ui/src/screens/Console/Tools/ToolsPanel/ToolsList.tsx new file mode 100644 index 000000000..50eb01edd --- /dev/null +++ b/portal-ui/src/screens/Console/Tools/ToolsPanel/ToolsList.tsx @@ -0,0 +1,100 @@ +// 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 . + +import React, { Fragment } from "react"; +import { Theme } from "@mui/material/styles"; +import createStyles from "@mui/styles/createStyles"; +import withStyles from "@mui/styles/withStyles"; +import Grid from "@mui/material/Grid"; + +import { configurationElements } from "../utils"; +import { + actionsTray, + containerForHeader, + searchField, +} from "../../Common/FormComponents/common/styleLibrary"; +import PageHeader from "../../Common/PageHeader/PageHeader"; +import SettingsCard from "../../Common/SettingsCard/SettingsCard"; + +interface IConfigurationOptions { + classes: any; +} + +const styles = (theme: Theme) => + createStyles({ + strongText: { + fontWeight: 700, + }, + keyName: { + marginLeft: 5, + }, + iconText: { + lineHeight: "24px", + }, + customConfigurationPage: { + height: "calc(100vh - 324px)", + scrollbarWidth: "none" as const, + "&::-webkit-scrollbar": { + display: "none", + }, + }, + settingsOptionsContainer: { + display: "flex" as const, + flexDirection: "row" as const, + justifyContent: "flex-start" as const, + flexWrap: "wrap" as const, + border: "#E5E5E5 1px solid", + borderRadius: 2, + padding: 5, + backgroundColor: "#fff", + }, + configurationLink: { + border: "#E5E5E5 1px solid", + borderRadius: 2, + padding: 20, + width: 190, + height: 80, + margin: 15, + }, + ...searchField, + ...actionsTray, + ...containerForHeader(theme.spacing(4)), + }); + +const ToolsList = ({ classes }: IConfigurationOptions) => { + return ( + + + + + +
+ {configurationElements.map((element) => ( + + ))} +
+
+
+
+
+ ); +}; + +export default withStyles(styles)(ToolsList); diff --git a/portal-ui/src/screens/Console/Tools/types.ts b/portal-ui/src/screens/Console/Tools/types.ts new file mode 100644 index 000000000..b035fef61 --- /dev/null +++ b/portal-ui/src/screens/Console/Tools/types.ts @@ -0,0 +1,61 @@ +// 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 . + +import { SelectorTypes } from "../Common/FormComponents/RadioGroupSelector/RadioGroupSelector"; + +export type KVFieldType = + | "string" + | "number" + | "on|off" + | "enum" + | "path" + | "url" + | "address" + | "duration" + | "uri" + | "sentence" + | "csv" + | "comment" + | "switch"; + +export interface KVField { + name: string; + label: string; + tooltip: string; + required?: boolean; + type: KVFieldType; + options?: SelectorTypes[]; + multiline?: boolean; + placeholder?: string; + withBorder?: boolean; +} + +export interface IConfigurationElement { + configuration_id: string; + configuration_label: string; + url?: string; +} + +export interface IElementValue { + key: string; + value: string; +} + +export interface IElement { + configuration_id: string; + configuration_label: string; + icon?: any; +} diff --git a/portal-ui/src/screens/Console/Tools/utils.tsx b/portal-ui/src/screens/Console/Tools/utils.tsx new file mode 100644 index 000000000..1d0f36c12 --- /dev/null +++ b/portal-ui/src/screens/Console/Tools/utils.tsx @@ -0,0 +1,58 @@ +// 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 . +import React from "react"; +import { IElement } from "./types"; +import { + DiagnosticsIcon, + HealIcon, + LogsIcon, + SearchIcon, + TraceIcon, + WatchIcon, +} from "../../../icons"; + +export const configurationElements: IElement[] = [ + { + icon: , + configuration_id: "logs", + configuration_label: "Logs", + }, + { + icon: , + configuration_id: "audit-logs", + configuration_label: "Audit Logs", + }, + { + icon: , + configuration_id: "watch", + configuration_label: "Watch", + }, + { + icon: , + configuration_id: "trace", + configuration_label: "trace", + }, + { + icon: , + configuration_id: "heal", + configuration_label: "heal", + }, + { + icon: , + configuration_id: "diagnostics", + configuration_label: "Diagnostics", + }, +]; diff --git a/portal-ui/src/screens/Console/Trace/Trace.tsx b/portal-ui/src/screens/Console/Trace/Trace.tsx index 8a6e376a4..2865f692b 100644 --- a/portal-ui/src/screens/Console/Trace/Trace.tsx +++ b/portal-ui/src/screens/Console/Trace/Trace.tsx @@ -14,15 +14,15 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -import React, { useState, Fragment } from "react"; -import { Grid, Button, TextField } from "@mui/material"; +import React, { Fragment, useState } from "react"; +import { Button, Grid, TextField } from "@mui/material"; import { IMessageEvent, w3cwebsocket as W3CWebSocket } from "websocket"; import { AppState } from "../../../store"; import { connect } from "react-redux"; import { + setTraceStarted, traceMessageReceived, traceResetMessages, - setTraceStarted, } from "./actions"; import { TraceMessage } from "./types"; import { Theme } from "@mui/material/styles"; @@ -31,16 +31,17 @@ import withStyles from "@mui/styles/withStyles"; import { niceBytes, timeFromDate } from "../../../common/utils"; import { wsProtocol } from "../../../utils/wsUtils"; import { - containerForHeader, - searchField, actionsTray, + containerForHeader, hrClass, inlineCheckboxes, + searchField, } from "../Common/FormComponents/common/styleLibrary"; import TableWrapper from "../Common/TableWrapper/TableWrapper"; import PageHeader from "../Common/PageHeader/PageHeader"; import CheckboxWrapper from "../Common/FormComponents/CheckboxWrapper/CheckboxWrapper"; import moment from "moment/moment"; +import BackLink from "../../../common/BackLink"; const styles = (theme: Theme) => createStyles({ @@ -192,246 +193,247 @@ const Trace = ({ return ( - - - - { - setStatusCode(e.target.value); - }} - disabled={traceStarted} - variant="standard" - /> - { - setMethod(e.target.value); - }} - disabled={traceStarted} - variant="standard" - /> - { - setFunc(e.target.value); - }} - variant="standard" - /> - { - setPath(e.target.value); - }} - variant="standard" - /> - { - setThreshold(parseInt(e.target.value)); - }} - variant="standard" - /> - - - Calls to trace: - { - setAll(item.target.checked); - }} - value={"all"} - disabled={traceStarted} - /> - { - setS3(item.target.checked); - }} - value={"s3"} - disabled={all || traceStarted} - /> - { - setInternal(item.target.checked); - }} - value={"internal"} - disabled={all || traceStarted} - /> - { - setStorage(item.target.checked); - }} - value={"storage"} - disabled={all || traceStarted} - /> - { - setOS(item.target.checked); - }} - value={"os"} - disabled={all || traceStarted} - /> - -       |       - - { - setErrors(item.target.checked); - }} - value={"only_errors"} - disabled={traceStarted} - /> - - - {!traceStarted && ( - - )} - {traceStarted && ( - - )} - - - -
-
- - { - const timeParse = new Date(time); - return timeFromDate(timeParse); - }, - globalClass: classes.timeItem, - }, - { label: "Name", elementKey: "api" }, - { - label: "Status", - elementKey: "", - renderFunction: (fullElement: TraceMessage) => - `${fullElement.statusCode} ${fullElement.statusMsg}`, - renderFullObject: true, - }, - { - label: "Location", - elementKey: "configuration_id", - renderFunction: (fullElement: TraceMessage) => - `${fullElement.host} ${fullElement.client}`, - renderFullObject: true, - }, - { - label: "Load Time", - elementKey: "callStats.duration", - globalClass: classes.timeItem, - }, - { - label: "Upload", - elementKey: "callStats.rx", - renderFunction: niceBytes, - globalClass: classes.sizeItem, - }, - { - label: "Download", - elementKey: "callStats.tx", - renderFunction: niceBytes, - globalClass: classes.sizeItem, - }, - ]} - isLoading={false} - records={messages} - entityName="Traces" - idField="api" - customEmptyMessage={ - traceStarted - ? "No Traced elements received yet" - : "Trace is not started yet" - } - customPaperHeight={classes.tableWrapper} - autoScrollToBottom + + + + + + { + setStatusCode(e.target.value); + }} + disabled={traceStarted} + variant="standard" + /> + { + setMethod(e.target.value); + }} + disabled={traceStarted} + variant="standard" + /> + { + setFunc(e.target.value); + }} + variant="standard" + /> + { + setPath(e.target.value); + }} + variant="standard" + /> + { + setThreshold(parseInt(e.target.value)); + }} + variant="standard" /> + + Calls to trace: + { + setAll(item.target.checked); + }} + value={"all"} + disabled={traceStarted} + /> + { + setS3(item.target.checked); + }} + value={"s3"} + disabled={all || traceStarted} + /> + { + setInternal(item.target.checked); + }} + value={"internal"} + disabled={all || traceStarted} + /> + { + setStorage(item.target.checked); + }} + value={"storage"} + disabled={all || traceStarted} + /> + { + setOS(item.target.checked); + }} + value={"os"} + disabled={all || traceStarted} + /> + +       |       + + { + setErrors(item.target.checked); + }} + value={"only_errors"} + disabled={traceStarted} + /> + + + {!traceStarted && ( + + )} + {traceStarted && ( + + )} + + + +
+
+ + { + const timeParse = new Date(time); + return timeFromDate(timeParse); + }, + globalClass: classes.timeItem, + }, + { label: "Name", elementKey: "api" }, + { + label: "Status", + elementKey: "", + renderFunction: (fullElement: TraceMessage) => + `${fullElement.statusCode} ${fullElement.statusMsg}`, + renderFullObject: true, + }, + { + label: "Location", + elementKey: "configuration_id", + renderFunction: (fullElement: TraceMessage) => + `${fullElement.host} ${fullElement.client}`, + renderFullObject: true, + }, + { + label: "Load Time", + elementKey: "callStats.duration", + globalClass: classes.timeItem, + }, + { + label: "Upload", + elementKey: "callStats.rx", + renderFunction: niceBytes, + globalClass: classes.sizeItem, + }, + { + label: "Download", + elementKey: "callStats.tx", + renderFunction: niceBytes, + globalClass: classes.sizeItem, + }, + ]} + isLoading={false} + records={messages} + entityName="Traces" + idField="api" + customEmptyMessage={ + traceStarted + ? "No Traced elements received yet" + : "Trace is not started yet" + } + customPaperHeight={classes.tableWrapper} + autoScrollToBottom + />
); diff --git a/portal-ui/src/screens/Console/Watch/Watch.tsx b/portal-ui/src/screens/Console/Watch/Watch.tsx index 736bfba7b..7eeda7f78 100644 --- a/portal-ui/src/screens/Console/Watch/Watch.tsx +++ b/portal-ui/src/screens/Console/Watch/Watch.tsx @@ -14,7 +14,15 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . import React, { useEffect, useState } from "react"; -import { Button, Grid, TextField, InputBase } from "@mui/material"; +import { + Button, + FormControl, + Grid, + InputBase, + MenuItem, + Select, + TextField, +} from "@mui/material"; import { IMessageEvent, w3cwebsocket as W3CWebSocket } from "websocket"; import { connect } from "react-redux"; import { Theme } from "@mui/material/styles"; @@ -22,10 +30,9 @@ import createStyles from "@mui/styles/createStyles"; import withStyles from "@mui/styles/withStyles"; import { AppState } from "../../../store"; import { watchMessageReceived, watchResetMessages } from "./actions"; -import { EventInfo, BucketList, Bucket } from "./types"; +import { Bucket, BucketList, EventInfo } from "./types"; import { niceBytes, timeFromDate } from "../../../common/utils"; import { wsProtocol } from "../../../utils/wsUtils"; -import { FormControl, MenuItem, Select } from "@mui/material"; import { actionsTray, containerForHeader, @@ -35,6 +42,7 @@ import { ErrorResponseHandler } from "../../../common/types"; import TableWrapper from "../Common/TableWrapper/TableWrapper"; import PageHeader from "../Common/PageHeader/PageHeader"; import api from "../../../common/api"; +import BackLink from "../../../common/BackLink"; const styles = (theme: Theme) => createStyles({ @@ -183,8 +191,11 @@ const Watch = ({ return ( - - + + + + +