diff --git a/portal-ui/Makefile b/portal-ui/Makefile
index cc60ce412..1fd676e0d 100644
--- a/portal-ui/Makefile
+++ b/portal-ui/Makefile
@@ -13,3 +13,5 @@ test-prettier:
prettify:
yarn prettier --write . --loglevel warn
+
+pretty: prettify
diff --git a/portal-ui/src/common/HelpBox.tsx b/portal-ui/src/common/HelpBox.tsx
index cc663fd8f..67fa45b29 100644
--- a/portal-ui/src/common/HelpBox.tsx
+++ b/portal-ui/src/common/HelpBox.tsx
@@ -52,7 +52,7 @@ const styles = (theme: Theme) =>
interface IHelpBox {
classes: any;
iconComponent: any;
- title: string;
+ title: string | React.ReactNode;
help: any;
}
diff --git a/portal-ui/src/icons/ExtraFeaturesIcon.tsx b/portal-ui/src/icons/ExtraFeaturesIcon.tsx
new file mode 100644
index 000000000..4d8ddc5fb
--- /dev/null
+++ b/portal-ui/src/icons/ExtraFeaturesIcon.tsx
@@ -0,0 +1,48 @@
+// 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 { SVGProps } from "react";
+
+const AccountIcon = (props: SVGProps) => (
+
+);
+export default AccountIcon;
diff --git a/portal-ui/src/icons/StarIcon.tsx b/portal-ui/src/icons/StarIcon.tsx
new file mode 100644
index 000000000..b3114b290
--- /dev/null
+++ b/portal-ui/src/icons/StarIcon.tsx
@@ -0,0 +1,33 @@
+// This file is part of MinIO Console Server
+// Copyright (c) 2022 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 { SVGProps } from "react";
+
+const StarIcon = (props: SVGProps) => (
+
+);
+
+export default StarIcon;
diff --git a/portal-ui/src/icons/index.ts b/portal-ui/src/icons/index.ts
index 1d5090151..ea9213e53 100644
--- a/portal-ui/src/icons/index.ts
+++ b/portal-ui/src/icons/index.ts
@@ -202,3 +202,5 @@ export { default as StandardLightLogo } from "./StandardLightLogo";
export { default as AGPLV3DarkLogo } from "./AGPLV3DarkLogo";
export { default as LDAPIcon } from "./LDAPIcon";
export { default as OIDCIcon } from "./OIDCIcon";
+export { default as StarIcon } from "./StarIcon";
+export { default as ExtraFeaturesIcon } from "./ExtraFeaturesIcon";
diff --git a/portal-ui/src/screens/Console/Common/IconsScreen.tsx b/portal-ui/src/screens/Console/Common/IconsScreen.tsx
index 51bd07761..40635b41a 100644
--- a/portal-ui/src/screens/Console/Common/IconsScreen.tsx
+++ b/portal-ui/src/screens/Console/Common/IconsScreen.tsx
@@ -457,6 +457,12 @@ const IconsScreen = ({ classes }: IIconsScreenSimple) => {
EventSubscriptionIcon
+
+
+
+ ExtraFeaturesIcon
+
+
@@ -979,6 +985,12 @@ const IconsScreen = ({ classes }: IIconsScreenSimple) => {
SpeedtestIcon
+
+
+
+ StarIcon
+
+
diff --git a/portal-ui/src/screens/Console/HealthInfo/HealthInfo.tsx b/portal-ui/src/screens/Console/HealthInfo/HealthInfo.tsx
index 80afd5a37..4f8c4ddc6 100644
--- a/portal-ui/src/screens/Console/HealthInfo/HealthInfo.tsx
+++ b/portal-ui/src/screens/Console/HealthInfo/HealthInfo.tsx
@@ -22,6 +22,7 @@ import {
} from "websocket";
import { AppState, useAppDispatch } from "../../../store";
import { useSelector } from "react-redux";
+import { useNavigate } from "react-router-dom";
import { Button } from "mds";
import {
DiagStatError,
@@ -56,6 +57,7 @@ import {
healthInfoMessageReceived,
healthInfoResetMessage,
} from "./healthInfoSlice";
+import RegisterCluster from "../Support/RegisterCluster";
const styles = (theme: Theme) =>
createStyles({
@@ -100,9 +102,17 @@ interface IHealthInfo {
const HealthInfo = ({ classes }: IHealthInfo) => {
const dispatch = useAppDispatch();
+ const navigate = useNavigate();
const message = useSelector((state: AppState) => state.healthInfo.message);
+ const licenseInfo = useSelector(
+ (state: AppState) => state?.system?.licenseInfo
+ );
+
+ const { plan = "" } = licenseInfo || {};
+ const registeredCluster = plan === "STANDARD" || plan === "ENTERPRISE";
+
const serverDiagnosticStatus = useSelector(
(state: AppState) => state.system.serverDiagnosticStatus
);
@@ -249,10 +259,19 @@ const HealthInfo = ({ classes }: IHealthInfo) => {
}
}, [startDiagnostic, dispatch]);
+ const startDiagnosticAction = () => {
+ if (plan !== "STANDARD" && plan !== "ENTERPRISE") {
+ navigate("/support/register");
+ return;
+ }
+ setStartDiagnostic(true);
+ };
+
return (
+ {!registeredCluster && }
@@ -290,9 +309,9 @@ const HealthInfo = ({ classes }: IHealthInfo) => {
@@ -302,7 +321,7 @@ const HealthInfo = ({ classes }: IHealthInfo) => {
- {!startDiagnostic && (
+ {!startDiagnostic && registeredCluster && (
...}>
+ {item.badge ? : null}
)}
diff --git a/portal-ui/src/screens/Console/Speedtest/Speedtest.tsx b/portal-ui/src/screens/Console/Speedtest/Speedtest.tsx
index 0d5d1be35..f5c478b70 100644
--- a/portal-ui/src/screens/Console/Speedtest/Speedtest.tsx
+++ b/portal-ui/src/screens/Console/Speedtest/Speedtest.tsx
@@ -19,6 +19,8 @@ import { useSelector } from "react-redux";
import { IMessageEvent, w3cwebsocket as W3CWebSocket } from "websocket";
import { Grid } from "@mui/material";
import { Theme } from "@mui/material/styles";
+import { useNavigate } from "react-router-dom";
+import { AppState } from "../../../store";
import { Button } from "mds";
import createStyles from "@mui/styles/createStyles";
import moment from "moment/moment";
@@ -49,6 +51,7 @@ import WarnIcon from "../../../icons/WarnIcon";
import Loader from "../Common/Loader/Loader";
import { selDistSet } from "../../../systemSlice";
import makeStyles from "@mui/styles/makeStyles";
+import RegisterCluster from "../Support/RegisterCluster";
const useStyles = makeStyles((theme: Theme) =>
createStyles({
@@ -80,6 +83,14 @@ const useStyles = makeStyles((theme: Theme) =>
const Speedtest = () => {
const distributedSetup = useSelector(selDistSet);
+ const licenseInfo = useSelector(
+ (state: AppState) => state?.system?.licenseInfo
+ );
+ const navigate = useNavigate();
+
+ const { plan = "" } = licenseInfo || {};
+ const registeredCluster = plan === "STANDARD" || plan === "ENTERPRISE";
+
const classes = useStyles();
const [start, setStart] = useState(false);
@@ -187,10 +198,21 @@ const Speedtest = () => {
const buttonLabel = start ? "Start" : stoppedLabel;
+ const startSpeedtestButton = () => {
+ if (plan !== "STANDARD" && plan !== "ENTERPRISE") {
+ navigate("/support/register");
+ return;
+ }
+
+ setCurrStatus(null);
+ setStart(true);
+ };
+
return (
+ {!registeredCluster && }
{!distributedSetup ? (
}
@@ -286,15 +308,14 @@ const Speedtest = () => {
- {!start && !currStatus && (
+ {!start && !currStatus && registeredCluster && (
createStyles({
@@ -57,6 +61,14 @@ interface IProfileProps {
var c: any = null;
const Profile = ({ classes }: IProfileProps) => {
+ const licenseInfo = useSelector(
+ (state: AppState) => state?.system?.licenseInfo
+ );
+ const navigate = useNavigate();
+
+ const { plan = "" } = licenseInfo || {};
+ const registeredCluster = plan === "STANDARD" || plan === "ENTERPRISE";
+
const [profilingStarted, setProfilingStarted] = useState(false);
const [types, setTypes] = useState([
"cpu",
@@ -138,6 +150,7 @@ const Profile = ({ classes }: IProfileProps) => {
+ {!registeredCluster && }
{