Interactive Bucket Naming Rules component (#2262)
This commit is contained in:
54
portal-ui/src/icons/HideTextIcon.tsx
Normal file
54
portal-ui/src/icons/HideTextIcon.tsx
Normal file
@@ -0,0 +1,54 @@
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
import * as React from "react";
|
||||
import { SVGProps } from "react";
|
||||
|
||||
const HideTextIcon = (props: SVGProps<SVGSVGElement>) => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className={`min-icon`}
|
||||
fill={"currentcolor"}
|
||||
viewBox="0 0 15 15"
|
||||
{...props}
|
||||
>
|
||||
<g id="Grupo_2449" data-name="Grupo 2449" transform="translate(-140 -181)">
|
||||
<g id="OpenListIcon-full" transform="translate(144 250.612)">
|
||||
<g
|
||||
id="noun_chevron_2320228"
|
||||
transform="translate(6.827 -63.612) rotate(90)"
|
||||
>
|
||||
<path
|
||||
id="Trazado_6842"
|
||||
data-name="Trazado 6842"
|
||||
d="M.422,6.661a.433.433,0,0,1-.3-.117.37.37,0,0,1,0-.557L2.983,3.335.126.675a.37.37,0,0,1,0-.557.443.443,0,0,1,.6,0L3.889,3.052a.373.373,0,0,1,.126.274.344.344,0,0,1-.126.274L.727,6.533a.443.443,0,0,1-.306.127Z"
|
||||
transform="translate(0 0)"
|
||||
/>
|
||||
</g>
|
||||
<rect
|
||||
id="Rectángulo_896"
|
||||
data-name="Rectángulo 896"
|
||||
width="0.462"
|
||||
height="0.462"
|
||||
transform="translate(0 -61.808)"
|
||||
fill="none"
|
||||
/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
|
||||
export default HideTextIcon;
|
||||
52
portal-ui/src/icons/ShowTextIcon.tsx
Normal file
52
portal-ui/src/icons/ShowTextIcon.tsx
Normal file
@@ -0,0 +1,52 @@
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
import * as React from "react";
|
||||
import { SVGProps } from "react";
|
||||
|
||||
const ShowTextIcon = (props: SVGProps<SVGSVGElement>) => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className={`min-icon`}
|
||||
fill={"currentcolor"}
|
||||
viewBox="0 0 15 15"
|
||||
{...props}
|
||||
>
|
||||
<g id="OpenListIcon-full" transform="translate(4 4.984)">
|
||||
<g
|
||||
id="noun_chevron_2320228"
|
||||
transform="translate(0.167 4.016) rotate(-90)"
|
||||
>
|
||||
<path
|
||||
id="Trazado_6842"
|
||||
data-name="Trazado 6842"
|
||||
d="M.422,0a.433.433,0,0,0-.3.117.37.37,0,0,0,0,.557L2.983,3.325.126,5.986a.37.37,0,0,0,0,.557.443.443,0,0,0,.6,0L3.889,3.609a.373.373,0,0,0,.126-.274.344.344,0,0,0-.126-.274L.727.127A.443.443,0,0,0,.422,0Z"
|
||||
transform="translate(0 0)"
|
||||
/>
|
||||
</g>
|
||||
<rect
|
||||
id="Rectángulo_896"
|
||||
data-name="Rectángulo 896"
|
||||
width="0.462"
|
||||
height="0.462"
|
||||
transform="translate(0 1.75)"
|
||||
fill="none"
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
|
||||
export default ShowTextIcon;
|
||||
@@ -14,9 +14,9 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import React, { Fragment, useEffect } from "react";
|
||||
import React, { Fragment, useEffect, useState } from "react";
|
||||
import Grid from "@mui/material/Grid";
|
||||
import { Box, Button, LinearProgress } from "@mui/material";
|
||||
import { Button, LinearProgress } from "@mui/material";
|
||||
import { Theme } from "@mui/material/styles";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
@@ -31,7 +31,10 @@ import FormSwitchWrapper from "../../../Common/FormComponents/FormSwitchWrapper/
|
||||
import PageHeader from "../../../Common/PageHeader/PageHeader";
|
||||
import BackLink from "../../../../../common/BackLink";
|
||||
import { BucketsIcon, InfoIcon } from "../../../../../icons";
|
||||
|
||||
import { setErrorSnackMessage } from "../../../../../systemSlice";
|
||||
import { ErrorResponseHandler } from "../../../../../common/types";
|
||||
import { BucketList } from "../../types";
|
||||
import api from "../../../../../common/api";
|
||||
import PageLayout from "../../../Common/Layout/PageLayout";
|
||||
import InputUnitMenu from "../../../Common/FormComponents/InputUnitMenu/InputUnitMenu";
|
||||
import FormLayout from "../../../Common/FormLayout";
|
||||
@@ -54,6 +57,7 @@ import { addBucketAsync } from "./addBucketThunks";
|
||||
import AddBucketName from "./AddBucketName";
|
||||
import { IAM_SCOPES } from "../../../../../common/SecureComponent/permissions";
|
||||
import { hasPermission } from "../../../../../common/SecureComponent";
|
||||
import BucketNamingRules from "./BucketNamingRules";
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
createStyles({
|
||||
@@ -108,6 +112,15 @@ const AddBucket = ({ classes }: IsetProps) => {
|
||||
const dispatch = useAppDispatch();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const validBucketCharacters = new RegExp(`^[a-z0-9.-]*$`);
|
||||
const ipAddressFormat = new RegExp(
|
||||
"^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(.|$)){4}$"
|
||||
);
|
||||
const bucketName = useSelector((state: AppState) => state.addBucket.name);
|
||||
const [validationResult, setValidationResult] = useState<boolean[]>([]);
|
||||
const errorList = validationResult.filter((v) => !v);
|
||||
const hasErrors = errorList.length > 0;
|
||||
const [records, setRecords] = useState<string[]>([]);
|
||||
const versioningEnabled = useSelector(
|
||||
(state: AppState) => state.addBucket.versioningEnabled
|
||||
);
|
||||
@@ -149,6 +162,44 @@ const AddBucket = ({ classes }: IsetProps) => {
|
||||
IAM_SCOPES.S3_PUT_BUCKET_OBJECT_LOCK_CONFIGURATION,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
const bucketNameErrors = [
|
||||
!(bucketName.length < 3 || bucketName.length > 63),
|
||||
validBucketCharacters.test(bucketName),
|
||||
!(
|
||||
bucketName.includes(".-") ||
|
||||
bucketName.includes("-.") ||
|
||||
bucketName.includes("..")
|
||||
),
|
||||
!ipAddressFormat.test(bucketName),
|
||||
!bucketName.startsWith("xn--"),
|
||||
!bucketName.endsWith("-s3alias"),
|
||||
!records.includes(bucketName),
|
||||
];
|
||||
setValidationResult(bucketNameErrors);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [bucketName]);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchRecords = () => {
|
||||
api
|
||||
.invoke("GET", `/api/v1/buckets`)
|
||||
.then((res: BucketList) => {
|
||||
var bucketList: string[] = [];
|
||||
if (res.buckets != null && res.buckets.length > 0) {
|
||||
res.buckets.forEach((bucket) => {
|
||||
bucketList.push(bucket.name);
|
||||
});
|
||||
}
|
||||
setRecords(bucketList);
|
||||
})
|
||||
.catch((err: ErrorResponseHandler) => {
|
||||
dispatch(setErrorSnackMessage(err));
|
||||
});
|
||||
};
|
||||
fetchRecords();
|
||||
}, [dispatch]);
|
||||
|
||||
const resForm = () => {
|
||||
dispatch(resetForm());
|
||||
};
|
||||
@@ -212,85 +263,6 @@ const AddBucket = ({ classes }: IsetProps) => {
|
||||
)}
|
||||
<br />
|
||||
<br />
|
||||
<b>Bucket Naming Rules</b>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexFlow: "column",
|
||||
fontSize: "14px",
|
||||
flex: "2",
|
||||
"& .step-number": {
|
||||
color: "#ffffff",
|
||||
height: "25px",
|
||||
width: "25px",
|
||||
background: "#081C42",
|
||||
marginRight: "10px",
|
||||
textAlign: "center",
|
||||
fontWeight: 600,
|
||||
borderRadius: "50%",
|
||||
},
|
||||
|
||||
"& .step-row": {
|
||||
fontSize: "14px",
|
||||
display: "flex",
|
||||
marginTop: "15px",
|
||||
marginBottom: "2px",
|
||||
|
||||
"&.step-text": {
|
||||
fontWeight: 400,
|
||||
},
|
||||
"&:before": {
|
||||
content: "' '",
|
||||
height: "7px",
|
||||
width: "7px",
|
||||
backgroundColor: "#2781B0",
|
||||
marginRight: "10px",
|
||||
marginTop: "7px",
|
||||
flexShrink: 0,
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Box className="step-row">
|
||||
<div className="step-text">
|
||||
Bucket names must be between 3 (min) and 63 (max)
|
||||
characters long.
|
||||
</div>
|
||||
</Box>
|
||||
<Box className="step-row">
|
||||
<div className="step-text">
|
||||
Bucket names can consist only of lowercase letters,
|
||||
numbers, dots (.), and hyphens (-).
|
||||
</div>
|
||||
</Box>
|
||||
<Box className="step-row">
|
||||
<div className="step-text">
|
||||
Bucket names must not contain two adjacent periods.
|
||||
</div>
|
||||
</Box>
|
||||
<Box className="step-row">
|
||||
<div className="step-text">
|
||||
Bucket names must not be formatted as an IP address (for
|
||||
example, 192.168.5.4).
|
||||
</div>
|
||||
</Box>
|
||||
<Box className="step-row">
|
||||
<div className="step-text">
|
||||
Bucket names must not start with the prefix xn--.
|
||||
</div>
|
||||
</Box>
|
||||
<Box className="step-row">
|
||||
<div className="step-text">
|
||||
Bucket names must not end with the suffix -s3alias. This
|
||||
suffix is reserved for access point alias names.
|
||||
</div>
|
||||
</Box>
|
||||
<Box className="step-row">
|
||||
<div className="step-text">
|
||||
Bucket names must be unique within a partition.
|
||||
</div>
|
||||
</Box>
|
||||
</Box>
|
||||
</Fragment>
|
||||
}
|
||||
/>
|
||||
@@ -306,7 +278,10 @@ const AddBucket = ({ classes }: IsetProps) => {
|
||||
>
|
||||
<Grid container marginTop={1} spacing={2}>
|
||||
<Grid item xs={12}>
|
||||
<AddBucketName />
|
||||
<AddBucketName hasErrors={hasErrors} />
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<BucketNamingRules errorList={validationResult} />
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<SectionTitle>Features</SectionTitle>
|
||||
@@ -330,8 +305,7 @@ const AddBucket = ({ classes }: IsetProps) => {
|
||||
</Fragment>
|
||||
)}
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12}>
|
||||
<Grid item xs={12} spacing={2}>
|
||||
{siteReplicationInfo.enabled && (
|
||||
<Fragment>
|
||||
<br />
|
||||
@@ -498,7 +472,7 @@ const AddBucket = ({ classes }: IsetProps) => {
|
||||
type="submit"
|
||||
variant="contained"
|
||||
color="primary"
|
||||
disabled={addLoading || invalidFields.length > 0}
|
||||
disabled={addLoading || invalidFields.length > 0 || hasErrors}
|
||||
>
|
||||
Create Bucket
|
||||
</Button>
|
||||
|
||||
@@ -20,7 +20,7 @@ import InputBoxWrapper from "../../../Common/FormComponents/InputBoxWrapper/Inpu
|
||||
import { useSelector } from "react-redux";
|
||||
import { AppState, useAppDispatch } from "../../../../../store";
|
||||
|
||||
const AddBucketName = () => {
|
||||
const AddBucketName = ({ hasErrors }: { hasErrors: boolean }) => {
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const bucketName = useSelector((state: AppState) => state.addBucket.name);
|
||||
@@ -28,12 +28,14 @@ const AddBucketName = () => {
|
||||
<InputBoxWrapper
|
||||
id="bucket-name"
|
||||
name="bucket-name"
|
||||
error={hasErrors ? "Invalid bucket Name" : ""}
|
||||
autoFocus={true}
|
||||
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
dispatch(setName(event.target.value));
|
||||
}}
|
||||
label="Bucket Name"
|
||||
value={bucketName}
|
||||
required
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
import React, { Fragment, useState } from "react";
|
||||
import Grid from "@mui/material/Grid";
|
||||
import { Button, LinearProgress } from "@mui/material";
|
||||
import { AppState } from "../../../../../store";
|
||||
import { useSelector } from "react-redux";
|
||||
import ShowTextIcon from "../../../../../icons/ShowTextIcon";
|
||||
import HideTextIcon from "../../../../../icons/HideTextIcon";
|
||||
|
||||
import ValidRule from "./ValidRule";
|
||||
import InvalidRule from "./InvalidRule";
|
||||
import NARule from "./NARule";
|
||||
|
||||
const BucketNamingRules = ({ errorList }: { errorList: boolean[] }) => {
|
||||
const lengthRuleText =
|
||||
"Bucket names must be between 3 (min) and 63 (max) characters long.";
|
||||
const characterRuleText =
|
||||
"Bucket names can consist only of lowercase letters, numbers, dots (.), and hyphens (-).";
|
||||
const periodRuleText =
|
||||
"Bucket names must not contain two adjacent periods, or a period adjacent to a hyphen.";
|
||||
const ipRuleText =
|
||||
"Bucket names must not be formatted as an IP address (for example, 192.168.5.4).";
|
||||
const prefixRuleText = "Bucket names must not start with the prefix xn--.";
|
||||
const suffixRuleText =
|
||||
"Bucket names must not end with the suffix -s3alias. This suffix is reserved for access point alias names.";
|
||||
const uniqueRuleText = "Bucket names must be unique within a partition.";
|
||||
|
||||
const bucketName = useSelector((state: AppState) => state.addBucket.name);
|
||||
|
||||
const [showNamingRules, setShowNamingRules] = useState<boolean>(false);
|
||||
|
||||
const addLoading = useSelector((state: AppState) => state.addBucket.loading);
|
||||
|
||||
const [
|
||||
lengthRule,
|
||||
validCharacters,
|
||||
noAdjacentPeriods,
|
||||
notIPFormat,
|
||||
noPrefix,
|
||||
noSuffix,
|
||||
uniqueName,
|
||||
] = errorList;
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Grid item xs={12}>
|
||||
{showNamingRules ? (
|
||||
<span style={{ color: "#0288D1", textDecoration: "underline" }}>
|
||||
{" "}
|
||||
Hide Bucket Naming Rules{" "}
|
||||
</span>
|
||||
) : (
|
||||
<span style={{ color: "#0288D1", textDecoration: "underline" }}>
|
||||
View Bucket Naming Rules
|
||||
</span>
|
||||
)}
|
||||
<Button
|
||||
variant="text"
|
||||
size="small"
|
||||
onClick={() => {
|
||||
setShowNamingRules(!showNamingRules);
|
||||
}}
|
||||
>
|
||||
{showNamingRules ? <ShowTextIcon /> : <HideTextIcon />}
|
||||
</Button>
|
||||
{showNamingRules && (
|
||||
<Grid container>
|
||||
<Grid item xs={6}>
|
||||
{bucketName.length === 0 ? (
|
||||
<NARule ruleText={lengthRuleText} />
|
||||
) : lengthRule ? (
|
||||
<ValidRule ruleText={lengthRuleText} />
|
||||
) : (
|
||||
<InvalidRule ruleText={lengthRuleText} />
|
||||
)}
|
||||
{bucketName.length === 0 ? (
|
||||
<NARule ruleText={characterRuleText} />
|
||||
) : validCharacters ? (
|
||||
<ValidRule ruleText={characterRuleText} />
|
||||
) : (
|
||||
<InvalidRule ruleText={characterRuleText} />
|
||||
)}
|
||||
{bucketName.length === 0 ? (
|
||||
<NARule ruleText={periodRuleText} />
|
||||
) : noAdjacentPeriods ? (
|
||||
<ValidRule ruleText={periodRuleText} />
|
||||
) : (
|
||||
<InvalidRule ruleText={periodRuleText} />
|
||||
)}
|
||||
{bucketName.length === 0 ? (
|
||||
<NARule ruleText={ipRuleText} />
|
||||
) : notIPFormat ? (
|
||||
<ValidRule ruleText={ipRuleText} />
|
||||
) : (
|
||||
<InvalidRule ruleText={ipRuleText} />
|
||||
)}
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
{bucketName.length === 0 ? (
|
||||
<NARule ruleText={prefixRuleText} />
|
||||
) : noPrefix ? (
|
||||
<ValidRule ruleText={prefixRuleText} />
|
||||
) : (
|
||||
<InvalidRule ruleText={prefixRuleText} />
|
||||
)}
|
||||
|
||||
{bucketName.length === 0 ? (
|
||||
<NARule ruleText={suffixRuleText} />
|
||||
) : noSuffix ? (
|
||||
<ValidRule ruleText={suffixRuleText} />
|
||||
) : (
|
||||
<InvalidRule ruleText={suffixRuleText} />
|
||||
)}
|
||||
|
||||
{bucketName.length === 0 ? (
|
||||
<NARule ruleText={uniqueRuleText} />
|
||||
) : uniqueName ? (
|
||||
<ValidRule ruleText={uniqueRuleText} />
|
||||
) : (
|
||||
<InvalidRule ruleText={uniqueRuleText} />
|
||||
)}
|
||||
</Grid>
|
||||
</Grid>
|
||||
)}
|
||||
</Grid>
|
||||
{addLoading && (
|
||||
<Grid item xs={12}>
|
||||
<LinearProgress />
|
||||
</Grid>
|
||||
)}
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
export default BucketNamingRules;
|
||||
@@ -0,0 +1,56 @@
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
import React, { Fragment } from "react";
|
||||
import Grid from "@mui/material/Grid";
|
||||
import { ConfirmDeleteIcon } from "../../../../../icons";
|
||||
|
||||
interface IInvalidRule {
|
||||
ruleText: string;
|
||||
}
|
||||
|
||||
const InvalidRule = ({ ruleText }: IInvalidRule) => {
|
||||
return (
|
||||
<Fragment>
|
||||
<Grid
|
||||
container
|
||||
style={{
|
||||
color: "#C83B51",
|
||||
display: "flex",
|
||||
justifyContent: "flex-start",
|
||||
}}
|
||||
>
|
||||
<Grid item xs={1} paddingRight={1}>
|
||||
<ConfirmDeleteIcon width={"16px"} height={"16px"} />
|
||||
</Grid>
|
||||
<Grid
|
||||
item
|
||||
xs={9}
|
||||
paddingLeft={1}
|
||||
style={{
|
||||
color: "#C83B51",
|
||||
display: "flex",
|
||||
justifyContent: "flex-start",
|
||||
}}
|
||||
>
|
||||
{ruleText}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
export default InvalidRule;
|
||||
@@ -0,0 +1,53 @@
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
import React, { Fragment } from "react";
|
||||
import Grid from "@mui/material/Grid";
|
||||
import { CircleIcon } from "../../../../../icons";
|
||||
|
||||
interface INARule {
|
||||
ruleText: string;
|
||||
}
|
||||
|
||||
const NARule = ({ ruleText }: INARule) => {
|
||||
return (
|
||||
<Fragment>
|
||||
<Grid container style={{ display: "flex", justifyContent: "flex-start" }}>
|
||||
<Grid item xs={1} paddingRight={1}>
|
||||
<CircleIcon
|
||||
width={"12px"}
|
||||
height={"12px"}
|
||||
style={{ color: "#8f949c" }}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid
|
||||
item
|
||||
xs={9}
|
||||
paddingLeft={1}
|
||||
style={{
|
||||
color: "#8f949c",
|
||||
display: "flex",
|
||||
justifyContent: "flex-start",
|
||||
}}
|
||||
>
|
||||
{ruleText}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
export default NARule;
|
||||
@@ -0,0 +1,53 @@
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
import React, { Fragment } from "react";
|
||||
import Grid from "@mui/material/Grid";
|
||||
import { ConfirmModalIcon } from "../../../../../icons";
|
||||
|
||||
interface IValidRule {
|
||||
ruleText: string;
|
||||
}
|
||||
|
||||
const ValidRule = ({ ruleText }: IValidRule) => {
|
||||
return (
|
||||
<Fragment>
|
||||
<Grid container style={{ display: "flex", justifyContent: "flex-start" }}>
|
||||
<Grid item xs={1} paddingRight={1}>
|
||||
<ConfirmModalIcon
|
||||
width={"16px"}
|
||||
height={"16px"}
|
||||
style={{ color: "#18BF42" }}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid
|
||||
item
|
||||
xs={9}
|
||||
paddingLeft={1}
|
||||
style={{
|
||||
color: "#8f949c",
|
||||
display: "flex",
|
||||
justifyContent: "flex-start",
|
||||
}}
|
||||
>
|
||||
{ruleText}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
export default ValidRule;
|
||||
Reference in New Issue
Block a user