Updated styling methods to remove mui and replace it with mds (#3085)

Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
This commit is contained in:
Alex
2023-10-13 12:02:29 -05:00
committed by GitHub
parent 88bf40f9a6
commit 0ecd1c73c1
32 changed files with 1032 additions and 1842 deletions

View File

@@ -15,18 +15,14 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import React from "react";
import Typography from "@mui/material/Typography";
import Link from "@mui/material/Link";
import { Box } from "mds";
export default function Copyright() {
return (
<Typography variant="body2" color="textSecondary" align="center">
<Box className={"muted"} sx={{ textAlign: "center" }}>
{"Copyright © "}
<Link color="inherit" href="https://min.io/?ref=con">
MinIO
</Link>{" "}
{new Date().getFullYear()}
<a href="https://min.io/?ref=con">MinIO</a> {new Date().getFullYear()}
{"."}
</Typography>
</Box>
);
}

View File

@@ -15,18 +15,17 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import React, { Fragment, Suspense } from "react";
import ObjectBrowser from "../Console/ObjectBrowser/ObjectBrowser";
import LoadingComponent from "../../common/LoadingComponent";
import ObjectManager from "../Console/Common/ObjectManager/ObjectManager";
import { ApplicationLogo } from "mds";
import { ApplicationLogo, Button } from "mds";
import { Route, Routes } from "react-router-dom";
import { IAM_PAGES } from "../../common/SecureComponent/permissions";
import { resetSession } from "../Console/consoleSlice";
import { useAppDispatch } from "../../store";
import { resetSystem } from "../../systemSlice";
import { getLogoVar } from "../../config";
import ObjectBrowser from "../Console/ObjectBrowser/ObjectBrowser";
import LoadingComponent from "../../common/LoadingComponent";
import ObjectManager from "../Console/Common/ObjectManager/ObjectManager";
import ObjectManagerButton from "../Console/Common/ObjectManager/ObjectManagerButton";
import { Button } from "@mui/material";
const AnonymousAccess = () => {
const dispatch = useAppDispatch();
@@ -61,7 +60,7 @@ const AnonymousAccess = () => {
dispatch(resetSession());
dispatch(resetSystem());
}}
style={{ color: "white" }}
sx={{ color: "white", textTransform: "initial" }}
>
Login
</Button>

View File

@@ -16,14 +16,7 @@
import React, { useState } from "react";
import { AddNewTagIcon, Box, Button, FormLayout, Grid, InputBox } from "mds";
import { Theme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles";
import withStyles from "@mui/styles/withStyles";
import {
formFieldStyles,
modalStyleUtils,
spacingUtils,
} from "../../Common/FormComponents/common/styleLibrary";
import { modalStyleUtils } from "../../Common/FormComponents/common/styleLibrary";
import ModalWrapper from "../../Common/ModalWrapper/ModalWrapper";
import { setModalErrorSnackMessage } from "../../../../systemSlice";
import { useAppDispatch } from "../../../../store";
@@ -35,24 +28,13 @@ interface IBucketTagModal {
currentTags: any;
bucketName: string;
onCloseAndUpdate: (refresh: boolean) => void;
classes: any;
}
const styles = (theme: Theme) =>
createStyles({
...formFieldStyles,
...modalStyleUtils,
...spacingUtils,
});
const AddBucketTagModal = ({
modalOpen,
currentTags,
onCloseAndUpdate,
bucketName,
classes,
}: IBucketTagModal) => {
const dispatch = useAppDispatch();
const [newKey, setNewKey] = useState<string>("");
@@ -143,4 +125,4 @@ const AddBucketTagModal = ({
);
};
export default withStyles(styles)(AddBucketTagModal);
export default AddBucketTagModal;

View File

@@ -36,13 +36,6 @@ import {
TrashIcon,
} from "mds";
import { useSelector } from "react-redux";
import { Theme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles";
import withStyles from "@mui/styles/withStyles";
import {
containerForHeader,
searchField,
} from "../../Common/FormComponents/common/styleLibrary";
import {
browseBucketPermissions,
deleteBucketPermissions,
@@ -99,24 +92,7 @@ const BucketLifecyclePanel = withSuspense(
React.lazy(() => import("./BucketLifecyclePanel")),
);
const styles = (theme: Theme) =>
createStyles({
pageContainer: {
height: "100%",
},
...searchField,
capitalize: {
textTransform: "capitalize",
},
...containerForHeader,
});
interface IBucketDetailsProps {
classes: any;
}
const BucketDetails = ({ classes }: IBucketDetailsProps) => {
const BucketDetails = () => {
const dispatch = useAppDispatch();
const navigate = useNavigate();
const params = useParams();
@@ -255,8 +231,11 @@ const BucketDetails = ({ classes }: IBucketDetailsProps) => {
>
<span style={{ fontSize: 15 }}>Access: </span>
<span
className={classes.capitalize}
style={{ fontWeight: 600, fontSize: 15 }}
style={{
fontWeight: 600,
fontSize: 15,
textTransform: "capitalize",
}}
>
{bucketInfo?.access?.toLowerCase()}
</span>
@@ -421,4 +400,4 @@ const BucketDetails = ({ classes }: IBucketDetailsProps) => {
);
};
export default withStyles(styles)(BucketDetails);
export default BucketDetails;

View File

@@ -15,7 +15,6 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import React, { useEffect, useState } from "react";
import { Theme } from "@mui/material/styles";
import {
BucketReplicationIcon,
Button,
@@ -25,16 +24,9 @@ import {
Switch,
Grid,
} from "mds";
import createStyles from "@mui/styles/createStyles";
import withStyles from "@mui/styles/withStyles";
import ModalWrapper from "../../Common/ModalWrapper/ModalWrapper";
import QueryMultiSelector from "../../Common/FormComponents/QueryMultiSelector/QueryMultiSelector";
import {
createTenantCommon,
formFieldStyles,
modalStyleUtils,
spacingUtils,
} from "../../Common/FormComponents/common/styleLibrary";
import { modalStyleUtils } from "../../Common/FormComponents/common/styleLibrary";
import { setModalErrorSnackMessage } from "../../../../systemSlice";
import { useAppDispatch } from "../../../../store";
import { api } from "api";
@@ -43,27 +35,13 @@ import { errorToHandler } from "api/errors";
interface IEditReplicationModal {
closeModalAndRefresh: (refresh: boolean) => void;
open: boolean;
classes: any;
bucketName: string;
ruleID: string;
}
const styles = (theme: Theme) =>
createStyles({
...spacingUtils,
...createTenantCommon,
...formFieldStyles,
...modalStyleUtils,
modalFormScrollable: {
...modalStyleUtils.modalFormScrollable,
paddingRight: 10,
},
});
const EditReplicationModal = ({
closeModalAndRefresh,
open,
classes,
bucketName,
ruleID,
}: IEditReplicationModal) => {
@@ -302,4 +280,4 @@ const EditReplicationModal = ({
);
};
export default withStyles(styles)(EditReplicationModal);
export default EditReplicationModal;

View File

@@ -16,6 +16,7 @@
import React, { Fragment, useEffect, useState } from "react";
import {
Box,
FormLayout,
Grid,
InputBox,
@@ -25,18 +26,9 @@ import {
Switch,
Tooltip,
} from "mds";
import { Theme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles";
import withStyles from "@mui/styles/withStyles";
import get from "lodash/get";
import ErrorOutlineIcon from "@mui/icons-material/ErrorOutline";
import CheckCircleOutlineIcon from "@mui/icons-material/CheckCircleOutline";
import {
createTenantCommon,
formFieldStyles,
modalStyleUtils,
spacingUtils,
} from "../../Common/FormComponents/common/styleLibrary";
import ModalWrapper from "../../Common/ModalWrapper/ModalWrapper";
import GenericWizard from "../../Common/GenericWizard/GenericWizard";
import QueryMultiSelector from "../../Common/FormComponents/QueryMultiSelector/QueryMultiSelector";
@@ -50,36 +42,12 @@ import { errorToHandler } from "api/errors";
interface IBulkReplicationModal {
open: boolean;
closeModalAndRefresh: (clearSelection: boolean) => any;
classes: any;
buckets: string[];
}
const styles = (theme: Theme) =>
createStyles({
resultGrid: {
display: "grid",
gridTemplateColumns: "45px auto",
alignItems: "center",
justifyContent: "stretch",
},
errorIcon: {
paddingTop: 5,
color: "#C72C48",
},
successIcon: {
paddingTop: 5,
color: "#42C91A",
},
...spacingUtils,
...modalStyleUtils,
...formFieldStyles,
...createTenantCommon,
});
const AddBulkReplicationModal = ({
open,
closeModalAndRefresh,
classes,
buckets,
}: IBulkReplicationModal) => {
const dispatch = useAppDispatch();
@@ -143,20 +111,30 @@ const AddBulkReplicationModal = ({
switch (errString) {
case "":
return (
<div className={classes.successIcon}>
<Box
sx={{
paddingTop: 5,
color: "#42C91A",
}}
>
<CheckCircleOutlineIcon />
</div>
</Box>
);
case "n/a":
return null;
default:
if (errString) {
return (
<div className={classes.errorIcon}>
<Box
sx={{
paddingTop: 5,
color: "#C72C48",
}}
>
<Tooltip tooltip={errString} placement="top">
<ErrorOutlineIcon />
</Tooltip>
</div>
</Box>
);
}
}
@@ -382,14 +360,21 @@ const AddBulkReplicationModal = ({
<Fragment>
<h3>Multi Bucket lifecycle Assignments Results</h3>
<Grid container>
<Grid item xs={12} className={classes.formScrollable}>
<Grid item xs={12}>
<h4>Buckets Results</h4>
{results?.results?.map((resultItem) => {
return (
<div className={classes.resultGrid}>
<Box
sx={{
display: "grid",
gridTemplateColumns: "45px auto",
alignItems: "center",
justifyContent: "stretch",
}}
>
{LogoToShow({ errString: resultItem.error || "" })}
<span>{resultItem.bucketName}</span>
</div>
</Box>
);
})}
</Grid>
@@ -412,4 +397,4 @@ const AddBulkReplicationModal = ({
);
};
export default withStyles(styles)(AddBulkReplicationModal);
export default AddBulkReplicationModal;

View File

@@ -16,6 +16,7 @@
import React, { Fragment, useEffect, useState } from "react";
import {
Box,
FormLayout,
Grid,
InputBox,
@@ -24,16 +25,9 @@ import {
Switch,
Tooltip,
} from "mds";
import { Theme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles";
import withStyles from "@mui/styles/withStyles";
import get from "lodash/get";
import ErrorOutlineIcon from "@mui/icons-material/ErrorOutline";
import CheckCircleOutlineIcon from "@mui/icons-material/CheckCircleOutline";
import {
modalBasic,
wizardCommon,
} from "../../Common/FormComponents/common/styleLibrary";
import ModalWrapper from "../../Common/ModalWrapper/ModalWrapper";
import GenericWizard from "../../Common/GenericWizard/GenericWizard";
import { getBytes, k8sScalarUnitsExcluding } from "../../../../common/utils";
@@ -48,36 +42,12 @@ import { SelectorTypes } from "../../../../common/types";
interface IBulkReplicationModal {
open: boolean;
closeModalAndRefresh: (clearSelection: boolean) => any;
classes: any;
buckets: string[];
}
const styles = (theme: Theme) =>
createStyles({
remoteBucketList: {
display: "grid",
gridTemplateColumns: "auto auto 45px",
alignItems: "center",
justifyContent: "stretch",
},
errorIcon: {
color: "#C72C48",
},
successIcon: {
color: "#42C91A",
},
hide: {
opacity: 0,
transitionDuration: "0.3s",
},
...modalBasic,
...wizardCommon,
});
const AddBulkReplicationModal = ({
open,
closeModalAndRefresh,
classes,
buckets,
}: IBulkReplicationModal) => {
const dispatch = useAppDispatch();
@@ -233,20 +203,28 @@ const AddBulkReplicationModal = ({
switch (errString) {
case "":
return (
<div className={classes.successIcon}>
<Box
sx={{
color: "#42C91A",
}}
>
<CheckCircleOutlineIcon />
</div>
</Box>
);
case "n/a":
return null;
default:
if (errString) {
return (
<div className={classes.errorIcon}>
<Box
sx={{
color: "#C72C48",
}}
>
<Tooltip tooltip={errString} placement="top">
<ErrorOutlineIcon />
</Tooltip>
</div>
</Box>
);
}
}
@@ -340,7 +318,7 @@ const AddBulkReplicationModal = ({
</ReadBox>
</Grid>
<h4>Remote Endpoint Configuration</h4>
<span className={classes.descriptionText}>
<span style={{ fontSize: 14 }}>
Please avoid the use of root credentials for this feature
</span>
<br />
@@ -459,24 +437,35 @@ const AddBulkReplicationModal = ({
componentRender: (
<Fragment>
<h3>Remote Bucket Assignments</h3>
<span className={classes.descriptionText}>
<span style={{ fontSize: 14 }}>
Please select / type the desired remote bucket were you want
the local data to be replicated.
</span>
<div className={classes.remoteBucketList}>
<Box
sx={{
display: "grid",
gridTemplateColumns: "auto auto 45px",
alignItems: "center",
justifyContent: "stretch",
"& .hide": {
opacity: 0,
transitionDuration: "0.3s",
},
}}
>
{bucketsToAlter.map((bucketName: string, index: number) => {
const errorItem = stateOfItem(bucketName);
return (
<Fragment
key={`buckets-assignation-${index.toString()}-${bucketName}`}
>
<div className={errorItem === "" ? classes.hide : ""}>
<div className={errorItem === "" ? "hide" : ""}>
{bucketName}
</div>
<div className={errorItem === "" ? classes.hide : ""}>
<div className={errorItem === "" ? "hide" : ""}>
{itemDisplayBulk(index)}
</div>
<div className={errorItem === "" ? classes.hide : ""}>
<div className={errorItem === "" ? "hide" : ""}>
{responseItem && responseItem.length > 0 && (
<LogoToShow errString={errorItem} />
)}
@@ -484,7 +473,7 @@ const AddBulkReplicationModal = ({
</Fragment>
);
})}
</div>
</Box>
</Fragment>
),
buttons: [
@@ -508,4 +497,4 @@ const AddBulkReplicationModal = ({
);
};
export default withStyles(styles)(AddBulkReplicationModal);
export default AddBulkReplicationModal;

View File

@@ -16,21 +16,21 @@
import React, { useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";
import { Button, CreateNewPathIcon, InputBox, Grid } from "mds";
import ModalWrapper from "../../../../Common/ModalWrapper/ModalWrapper";
import { Theme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles";
import {
formFieldStyles,
modalStyleUtils,
} from "../../../../Common/FormComponents/common/styleLibrary";
import { connect, useSelector } from "react-redux";
import {
Button,
CreateNewPathIcon,
InputBox,
Grid,
FormLayout,
Box,
} from "mds";
import ModalWrapper from "../../../../Common/ModalWrapper/ModalWrapper";
import { modalStyleUtils } from "../../../../Common/FormComponents/common/styleLibrary";
import { encodeURLString } from "../../../../../../common/utils";
import { BucketObjectItem } from "./types";
import { AppState, useAppDispatch } from "../../../../../../store";
import { setModalErrorSnackMessage } from "../../../../../../systemSlice";
import makeStyles from "@mui/styles/makeStyles";
interface ICreatePath {
modalOpen: boolean;
@@ -40,13 +40,6 @@ interface ICreatePath {
simplePath: string | null;
}
const useStyles = makeStyles((theme: Theme) =>
createStyles({
...modalStyleUtils,
...formFieldStyles,
}),
);
const CreatePathModal = ({
modalOpen,
folderName,
@@ -56,7 +49,6 @@ const CreatePathModal = ({
}: ICreatePath) => {
const dispatch = useAppDispatch();
const navigate = useNavigate();
const classes = useStyles();
const [pathUrl, setPathUrl] = useState("");
const [isFormValid, setIsFormValid] = useState<boolean>(false);
@@ -141,11 +133,11 @@ const CreatePathModal = ({
onClose={onClose}
titleIcon={<CreateNewPathIcon />}
>
<Grid container>
<Grid item xs={12} className={classes.formFieldRow}>
<FormLayout withBorders={false} containerPadding={false}>
<Box className={"inputItem"} sx={{ display: "flex", gap: 8 }}>
<strong>Current Path:</strong> <br />
<div
style={{
<Box
sx={{
textOverflow: "ellipsis",
whiteSpace: "nowrap",
overflow: "hidden",
@@ -155,21 +147,19 @@ const CreatePathModal = ({
dir={"rtl"}
>
{currentPath}
</div>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBox
value={pathUrl}
label={"New Folder Path"}
id={"folderPath"}
name={"folderPath"}
placeholder={"Enter the new Folder Path"}
onChange={inputChange}
onKeyPress={keyPressed}
required
/>
</Grid>
<Grid item xs={12} className={classes.modalButtonBar}>
</Box>
</Box>
<InputBox
value={pathUrl}
label={"New Folder Path"}
id={"folderPath"}
name={"folderPath"}
placeholder={"Enter the new Folder Path"}
onChange={inputChange}
onKeyPress={keyPressed}
required
/>
<Grid item xs={12} sx={modalStyleUtils.modalButtonBar}>
<Button
id={"clear"}
type="button"
@@ -187,7 +177,7 @@ const CreatePathModal = ({
label={"Create"}
/>
</Grid>
</Grid>
</FormLayout>
</ModalWrapper>
</React.Fragment>
);

View File

@@ -1,44 +1,56 @@
// 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 <http://www.gnu.org/licenses/>.
// This object contains variables that will be used across form components.
import React from "react";
import createStyles from "@mui/styles/createStyles";
import withStyles from "@mui/styles/withStyles";
import { Theme } from "@mui/material/styles";
import { Box } from "mds";
import { replaceUnicodeChar } from "../../../../../../common/utils";
interface IIconWithLabel {
classes: any;
icon: JSX.Element;
icon: React.ReactNode;
strings: string[];
}
const styles = (theme: Theme) =>
createStyles({
fileName: {
display: "flex",
alignItems: "center",
"& .min-icon": {
width: 16,
height: 16,
marginRight: 4,
minWidth: 16,
minHeight: 16,
},
},
fileNameText: {
whiteSpace: "pre",
overflow: "hidden",
textOverflow: "ellipsis",
},
});
const IconWithLabel = ({ classes, icon, strings }: IIconWithLabel) => {
const IconWithLabel = ({ icon, strings }: IIconWithLabel) => {
return (
<div className={classes.fileName}>
<Box
sx={{
display: "flex",
alignItems: "center",
"& .min-icon": {
width: 16,
height: 16,
marginRight: 4,
minWidth: 16,
minHeight: 16,
},
"& .fileNameText": {
whiteSpace: "pre",
overflow: "hidden",
textOverflow: "ellipsis",
},
}}
>
{icon}
<span className={classes.fileNameText}>
<span className={"fileNameText"}>
{replaceUnicodeChar(strings[strings.length - 1])}
</span>
</div>
</Box>
);
};
export default withStyles(styles)(IconWithLabel);
export default IconWithLabel;

View File

@@ -23,7 +23,6 @@ import {
Grid,
Box,
} from "mds";
import withStyles from "@mui/styles/withStyles";
import {
decodeURLString,
deleteCookie,
@@ -32,27 +31,12 @@ import {
performDownload,
} from "../../../../../../common/utils";
import ModalWrapper from "../../../../Common/ModalWrapper/ModalWrapper";
import { Theme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles";
import {
formFieldStyles,
modalStyleUtils,
spacingUtils,
} from "../../../../Common/FormComponents/common/styleLibrary";
import { DialogContentText } from "@mui/material";
import { modalStyleUtils } from "../../../../Common/FormComponents/common/styleLibrary";
import KeyRevealer from "../../../../Tools/KeyRevealer";
import { setErrorSnackMessage } from "../../../../../../systemSlice";
import { useAppDispatch } from "../../../../../../store";
const styles = (theme: Theme) =>
createStyles({
...formFieldStyles,
...modalStyleUtils,
...spacingUtils,
});
interface IInspectObjectProps {
classes: any;
closeInspectModalAndRefresh: (refresh: boolean) => void;
inspectOpen: boolean;
inspectPath: string;
@@ -60,7 +44,6 @@ interface IInspectObjectProps {
}
const InspectObject = ({
classes,
closeInspectModalAndRefresh,
inspectOpen,
inspectPath,
@@ -156,7 +139,7 @@ const InspectObject = ({
}}
description=""
/>
<Grid item xs={12} className={classes.modalButtonBar}>
<Grid item xs={12} sx={modalStyleUtils.modalButtonBar}>
<Button
id={"inspect"}
type="submit"
@@ -176,20 +159,18 @@ const InspectObject = ({
onClose={onCloseDecKeyModal}
titleIcon={<PasswordKeyIcon />}
>
<DialogContentText>
<Box>
This will be displayed only once. It cannot be recovered.
<br />
Use secure medium to share this key.
</Box>
<Box>
<KeyRevealer value={decryptionKey} />
</Box>
</DialogContentText>
<Box>
This will be displayed only once. It cannot be recovered.
<br />
Use secure medium to share this key.
</Box>
<Box>
<KeyRevealer value={decryptionKey} />
</Box>
</ModalWrapper>
) : null}
</React.Fragment>
);
};
export default withStyles(styles)(InspectObject);
export default InspectObject;

View File

@@ -16,9 +16,6 @@
import React, { useState } from "react";
import { listModeColumns, rewindModeColumns } from "./ListObjectsHelpers";
import makeStyles from "@mui/styles/makeStyles";
import { Theme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles";
import { useSelector } from "react-redux";
import { AppState, useAppDispatch } from "../../../../../../store";
import { selFeatures } from "../../../../consoleSlice";
@@ -43,37 +40,7 @@ import { downloadObject } from "../../../../ObjectBrowser/utils";
import { DataTable, ItemActions } from "mds";
import { BucketObject } from "api/consoleApi";
const useStyles = makeStyles((theme: Theme) =>
createStyles({
browsePaper: {
border: 0,
"@media (max-width: 800px)": {
width: 800,
},
},
parentWrapper: {
position: "relative",
height: "calc(100% - 60px)",
"@media (max-width: 800px)": {
overflowX: "auto",
},
"@media (max-width: 1060px)": {
height: "calc(100% - 115px)",
},
},
"@global": {
".rowLine:hover .iconFileElm": {
backgroundImage: "url(/images/ob_file_filled.svg)",
},
".rowLine:hover .iconFolderElm": {
backgroundImage: "url(/images/ob_folder_filled.svg)",
},
},
}),
);
const ListObjectsTable = () => {
const classes = useStyles();
const dispatch = useAppDispatch();
const params = useParams();
const navigate = useNavigate();
@@ -266,7 +233,6 @@ const ListObjectsTable = () => {
return "";
}}
parentClassName={classes.parentWrapper}
sx={{
minHeight: detailsOpen ? "100%" : "initial",
}}

View File

@@ -798,7 +798,7 @@ const ObjectDetailPanel = ({
<SimpleHeader label={"Metadata"} icon={<MetadataIcon />} />
<Box className={"detailContainer"}>
{actualInfo && metaData ? (
<ObjectMetaData metaData={metaData} linear />
<ObjectMetaData metaData={metaData} />
) : null}
</Box>
</Fragment>

View File

@@ -15,108 +15,44 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import React, { Fragment } from "react";
import { withStyles } from "@mui/styles";
import Grid from "@mui/material/Grid";
import { Box, Table, TableBody, TableCell, TableRow } from "@mui/material";
import { Theme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles";
import {
detailsPanel,
spacingUtils,
} from "../../../../Common/FormComponents/common/styleLibrary";
import { Box } from "mds";
import { safeDecodeURIComponent } from "../../../../../../common/utils";
interface IObjectMetadata {
metaData: any;
classes?: any;
linear?: boolean;
}
const styles = (theme: Theme) =>
createStyles({
titleItem: {
width: "35%",
},
...spacingUtils,
...detailsPanel,
});
const itemRendererFn = (element: any) => {
return Array.isArray(element)
? element.map(safeDecodeURIComponent).join(", ")
: safeDecodeURIComponent(element);
};
const ObjectMetaData = ({
metaData,
classes,
linear = false,
}: IObjectMetadata) => {
const ObjectMetaData = ({ metaData }: IObjectMetadata) => {
const metaKeys = Object.keys(metaData);
if (linear) {
return (
<Fragment>
{metaKeys.map((element: string, index: number) => {
const renderItem = itemRendererFn(metaData[element]);
return (
<Box
className={classes.metadataLinear}
key={`box-meta-${element}-${index.toString()}`}
>
<strong>{element}</strong>
<br />
{renderItem}
</Box>
);
})}
</Fragment>
);
}
return (
<Grid container>
<Grid
item
xs={12}
sx={{
marginTop: "25px",
marginBottom: "5px",
}}
>
<h3
style={{
marginTop: "0",
marginBottom: "0",
}}
>
Object Metadata
</h3>
</Grid>
<Grid item xs={12}>
<Table className={classes.table} aria-label="simple table">
<TableBody>
{metaKeys.map((element: string, index: number) => {
const renderItem = itemRendererFn(metaData[element]);
return (
<TableRow key={`tRow-${index.toString()}`}>
<TableCell
component="th"
scope="row"
className={classes.titleItem}
>
{element}
</TableCell>
<TableCell align="right">{renderItem}</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
</Grid>
</Grid>
<Fragment>
{metaKeys.map((element: string, index: number) => {
const renderItem = itemRendererFn(metaData[element]);
return (
<Box
sx={{
marginBottom: 15,
fontSize: 14,
maxHeight: 180,
overflowY: "auto",
}}
key={`box-meta-${element}-${index.toString()}`}
>
<strong>{element}</strong>
<br />
{renderItem}
</Box>
);
})}
</Fragment>
);
};
export default withStyles(styles)(ObjectMetaData);
export default ObjectMetaData;

View File

@@ -15,22 +15,17 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
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 { encodeURLString } from "../../../../../../common/utils";
import ConfirmDialog from "../../../../Common/ModalWrapper/ConfirmDialog";
import { Box, RecoverIcon } from "mds";
import { setErrorSnackMessage } from "../../../../../../systemSlice";
import { useAppDispatch } from "../../../../../../store";
import { restoreLocalObjectList } from "../../../../ObjectBrowser/objectBrowserSlice";
import { BucketObject } from "api/consoleApi";
import { api } from "api";
import { errorToHandler } from "api/errors";
import { encodeURLString } from "../../../../../../common/utils";
import ConfirmDialog from "../../../../Common/ModalWrapper/ConfirmDialog";
import { setErrorSnackMessage } from "../../../../../../systemSlice";
import { useAppDispatch } from "../../../../../../store";
import { restoreLocalObjectList } from "../../../../ObjectBrowser/objectBrowserSlice";
interface IRestoreFileVersion {
classes: any;
restoreOpen: boolean;
bucketName: string;
versionToRestore: BucketObject;
@@ -38,13 +33,7 @@ interface IRestoreFileVersion {
onCloseAndUpdate: (refresh: boolean) => void;
}
const styles = (theme: Theme) =>
createStyles({
...modalBasic,
});
const RestoreFileVersion = ({
classes,
versionToRestore,
bucketName,
objectPath,
@@ -98,11 +87,11 @@ const RestoreFileVersion = ({
Are you sure you want to restore <br />
<b>{objectPath}</b> <br /> with Version ID:
<br />
<b className={classes.wrapText}>{versionToRestore.version_id}</b>?
<b>{versionToRestore.version_id}</b>?
</Box>
}
/>
);
};
export default withStyles(styles)(RestoreFileVersion);
export default RestoreFileVersion;

View File

@@ -15,35 +15,18 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import React, { useEffect, useState } from "react";
import { Theme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles";
import withStyles from "@mui/styles/withStyles";
import get from "lodash/get";
import { Button, Grid, Switch } from "mds";
import {
formFieldStyles,
modalStyleUtils,
spacingUtils,
} from "../../../../Common/FormComponents/common/styleLibrary";
import ModalWrapper from "../../../../Common/ModalWrapper/ModalWrapper";
import { encodeURLString } from "../../../../../../common/utils";
import { setModalErrorSnackMessage } from "../../../../../../systemSlice";
import { useAppDispatch } from "../../../../../../store";
import { Box, Button, FormLayout, Grid, Switch } from "mds";
import { BucketObject, ObjectLegalHoldStatus } from "api/consoleApi";
import { api } from "api";
import { errorToHandler } from "api/errors";
const styles = (theme: Theme) =>
createStyles({
...formFieldStyles,
...modalStyleUtils,
...spacingUtils,
});
import { modalStyleUtils } from "../../../../Common/FormComponents/common/styleLibrary";
import { encodeURLString } from "../../../../../../common/utils";
import { setModalErrorSnackMessage } from "../../../../../../systemSlice";
import { useAppDispatch } from "../../../../../../store";
import ModalWrapper from "../../../../Common/ModalWrapper/ModalWrapper";
interface ISetRetentionProps {
classes: any;
open: boolean;
closeModalAndRefresh: (reload: boolean) => void;
objectName: string;
@@ -52,7 +35,6 @@ interface ISetRetentionProps {
}
const SetLegalHoldModal = ({
classes,
open,
closeModalAndRefresh,
objectName,
@@ -109,10 +91,6 @@ const SetLegalHoldModal = ({
closeModalAndRefresh(false);
}}
>
<Grid item xs={12} className={classes.spacerBottom}>
Object: {bucketName}
</Grid>
<form
noValidate
autoComplete="off"
@@ -120,7 +98,10 @@ const SetLegalHoldModal = ({
onSubmit(e);
}}
>
<Grid item xs={12} className={classes.formFieldRow}>
<FormLayout withBorders={false} containerPadding={false}>
<Box className={"inputItem"}>
<strong>Object</strong>: {bucketName}
</Box>
<Switch
value="legalhold"
id="legalhold"
@@ -135,26 +116,26 @@ const SetLegalHoldModal = ({
"To enable this feature you need to enable versioning on the bucket before creation"
}
/>
</Grid>
<Grid item xs={12} className={classes.modalButtonBar}>
<Button
id={"clear"}
type="button"
variant="regular"
onClick={resetForm}
label={"Clear"}
/>
<Button
id={"save"}
type="submit"
variant="callAction"
disabled={isSaving}
label={" Save"}
/>
</Grid>
<Grid item xs={12} sx={modalStyleUtils.modalButtonBar}>
<Button
id={"clear"}
type="button"
variant="regular"
onClick={resetForm}
label={"Clear"}
/>
<Button
id={"save"}
type="submit"
variant="callAction"
disabled={isSaving}
label={" Save"}
/>
</Grid>
</FormLayout>
</form>
</ModalWrapper>
);
};
export default withStyles(styles)(SetLegalHoldModal);
export default SetLegalHoldModal;

View File

@@ -15,37 +15,20 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import React, { useEffect, useRef, useState } from "react";
import { Theme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles";
import withStyles from "@mui/styles/withStyles";
import { Button, Grid, RadioGroup, Switch } from "mds";
import {
formFieldStyles,
modalStyleUtils,
spacingUtils,
} from "../../../../Common/FormComponents/common/styleLibrary";
import { twoDigitDate } from "../../../../Common/FormComponents/DateSelector/utils";
import ModalWrapper from "../../../../Common/ModalWrapper/ModalWrapper";
import DateSelector from "../../../../Common/FormComponents/DateSelector/DateSelector";
import { setModalErrorSnackMessage } from "../../../../../../systemSlice";
import { AppState, useAppDispatch } from "../../../../../../store";
import { Box, Button, FormLayout, Grid, RadioGroup, Switch } from "mds";
import { useSelector } from "react-redux";
import { BucketObject, ObjectRetentionMode } from "api/consoleApi";
import { api } from "api";
import { errorToHandler } from "api/errors";
import { encodeURLString } from "common/utils";
const styles = (theme: Theme) =>
createStyles({
...formFieldStyles,
...modalStyleUtils,
...spacingUtils,
});
import { modalStyleUtils } from "../../../../Common/FormComponents/common/styleLibrary";
import { twoDigitDate } from "../../../../Common/FormComponents/DateSelector/utils";
import { setModalErrorSnackMessage } from "../../../../../../systemSlice";
import { AppState, useAppDispatch } from "../../../../../../store";
import ModalWrapper from "../../../../Common/ModalWrapper/ModalWrapper";
import DateSelector from "../../../../Common/FormComponents/DateSelector/DateSelector";
interface ISetRetentionProps {
classes: any;
open: boolean;
closeModalAndRefresh: (updateInfo: boolean) => void;
objectName: string;
@@ -58,7 +41,6 @@ interface IRefObject {
}
const SetRetention = ({
classes,
open,
closeModalAndRefresh,
objectName,
@@ -190,9 +172,6 @@ const SetRetention = ({
closeModalAndRefresh(false);
}}
>
<div className={classes.spacerBottom}>
<strong>Selected Object</strong>: {objectName}
</div>
<form
noValidate
autoComplete="off"
@@ -200,8 +179,11 @@ const SetRetention = ({
onSubmit(e);
}}
>
{showSwitcher && (
<Grid item xs={12} className={classes.formFieldRow}>
<FormLayout>
<Box className={"inputItem"}>
<strong>Selected Object</strong>: {objectName}
</Box>
{showSwitcher && (
<Switch
value="status"
id="status"
@@ -213,9 +195,7 @@ const SetRetention = ({
label={"Status"}
indicatorLabels={["Enabled", "Disabled"]}
/>
</Grid>
)}
<Grid item xs={12} className={classes.formFieldRow}>
)}
<RadioGroup
currentValue={type}
id="type"
@@ -232,47 +212,47 @@ const SetRetention = ({
{ label: "Compliance", value: ObjectRetentionMode.Compliance },
]}
/>
</Grid>
<Grid item xs={12} className={`${classes.dateSelector} `}>
<DateSelector
id="date"
label="Date"
disableOptions={dateFieldDisabled()}
ref={dateElement}
value={date}
borderBottom={true}
onDateChange={(date: string, isValid: boolean) => {
setIsDateValid(isValid);
if (isValid) {
setDate(date);
<Box className={"inputItem"}>
<DateSelector
id="date"
label="Date"
disableOptions={dateFieldDisabled()}
ref={dateElement}
value={date}
borderBottom={true}
onDateChange={(date: string, isValid: boolean) => {
setIsDateValid(isValid);
if (isValid) {
setDate(date);
}
}}
/>
</Box>
<Grid item xs={12} sx={modalStyleUtils.modalButtonBar}>
<Button
id={"reset"}
type="button"
variant="regular"
onClick={resetForm}
label={"Reset"}
/>
<Button
id={"save"}
type="submit"
variant="callAction"
disabled={
(statusEnabled && type === "") ||
(statusEnabled && !isDateValid) ||
isSaving
}
}}
/>
</Grid>
<Grid item xs={12} className={classes.modalButtonBar}>
<Button
id={"reset"}
type="button"
variant="regular"
onClick={resetForm}
label={"Reset"}
/>
<Button
id={"save"}
type="submit"
variant="callAction"
disabled={
(statusEnabled && type === "") ||
(statusEnabled && !isDateValid) ||
isSaving
}
onClick={saveNewRetentionPolicy}
label={"Save"}
/>
</Grid>
onClick={saveNewRetentionPolicy}
label={"Save"}
/>
</Grid>
</FormLayout>
</form>
</ModalWrapper>
);
};
export default withStyles(styles)(SetRetention);
export default SetRetention;

View File

@@ -16,7 +16,7 @@
import React, { Fragment, useState } from "react";
import get from "lodash/get";
import { Box, Grid } from "@mui/material";
import styled from "styled-components";
import {
AddNewTagIcon,
Button,
@@ -24,83 +24,43 @@ import {
EditTagIcon,
InputBox,
SectionTitle,
Box,
Grid,
Tag,
FormLayout,
} from "mds";
import { Theme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles";
import withStyles from "@mui/styles/withStyles";
import ModalWrapper from "../../../../Common/ModalWrapper/ModalWrapper";
import {
formFieldStyles,
modalStyleUtils,
spacingUtils,
} from "../../../../Common/FormComponents/common/styleLibrary";
import { IAM_SCOPES } from "../../../../../../common/SecureComponent/permissions";
import { SecureComponent } from "../../../../../../common/SecureComponent";
import Chip from "@mui/material/Chip";
import CloseIcon from "@mui/icons-material/Close";
import {
selDistSet,
setModalErrorSnackMessage,
} from "../../../../../../systemSlice";
import { useAppDispatch } from "../../../../../../store";
import { BucketObject } from "api/consoleApi";
import { api } from "api";
import { errorToHandler } from "api/errors";
import { encodeURLString } from "common/utils";
import { useSelector } from "react-redux";
import ModalWrapper from "../../../../Common/ModalWrapper/ModalWrapper";
import { modalStyleUtils } from "../../../../Common/FormComponents/common/styleLibrary";
import { IAM_SCOPES } from "../../../../../../common/SecureComponent/permissions";
import { SecureComponent } from "../../../../../../common/SecureComponent";
import {
selDistSet,
setModalErrorSnackMessage,
} from "../../../../../../systemSlice";
import { useAppDispatch } from "../../../../../../store";
interface ITagModal {
modalOpen: boolean;
bucketName: string;
actualInfo: BucketObject;
onCloseAndUpdate: (refresh: boolean) => void;
classes: any;
}
const styles = (theme: Theme) =>
createStyles({
newTileHeader: {
fontSize: 18,
fontWeight: "bold",
color: "#000",
margin: "35px 0",
paddingBottom: 15,
display: "flex",
alignItems: "center",
"& > svg": {
marginRight: 10,
},
},
tagsForLabel: {
fontSize: 16,
margin: "20px 0 30px",
whiteSpace: "nowrap",
overflow: "hidden",
textOverflow: "ellipsis",
width: "100%",
},
currentTagsContainer: {
fontSize: 14,
fontWeight: "normal",
},
noTagsForObject: {
color: "#858585",
},
deleteTag: {
color: "#C83B51",
marginLeft: 5,
},
...formFieldStyles,
...modalStyleUtils,
...spacingUtils,
});
const DeleteTag = styled.b(({ theme }) => ({
color: get(theme, "signalColors.danger", "#C83B51"),
marginLeft: 5,
}));
const AddTagModal = ({
modalOpen,
onCloseAndUpdate,
bucketName,
actualInfo,
classes,
}: ITagModal) => {
const dispatch = useAppDispatch();
const distributedSetup = useSelector(selDistSet);
@@ -184,9 +144,18 @@ const AddTagModal = ({
};
const tagsFor = (plural: boolean) => (
<div className={classes.tagsForLabel}>
<Box
sx={{
fontSize: 16,
margin: "20px 0 30px",
whiteSpace: "nowrap",
overflow: "hidden",
textOverflow: "ellipsis",
width: "100%",
}}
>
Tag{plural ? "s" : ""} for: <strong>{currentItem}</strong>
</div>
</Box>
);
return (
@@ -197,24 +166,19 @@ const AddTagModal = ({
onClose={() => {
onCloseAndUpdate(true);
}}
titleIcon={
deleteEnabled ? (
<DisabledIcon style={{ fill: "#C83B51" }} />
) : (
<EditTagIcon />
)
}
iconColor={deleteEnabled ? "delete" : "default"}
titleIcon={deleteEnabled ? <DisabledIcon /> : <EditTagIcon />}
>
{deleteEnabled ? (
<Fragment>
<Grid container>
{tagsFor(false)}
Are you sure you want to delete the tag{" "}
<b className={classes.deleteTag}>
<DeleteTag>
{deleteKey} : {deleteLabel}
</b>{" "}
</DeleteTag>{" "}
?
<Grid item xs={12} className={classes.modalButtonBar}>
<Grid item xs={12} sx={modalStyleUtils.modalButtonBar}>
<Button
id={"cancel"}
type="button"
@@ -233,7 +197,7 @@ const AddTagModal = ({
</Grid>
</Fragment>
) : (
<Grid container>
<Box>
<SecureComponent
scopes={[
IAM_SCOPES.S3_GET_OBJECT_TAGGING,
@@ -249,11 +213,16 @@ const AddTagModal = ({
}}
>
{tagsFor(true)}
<div className={classes.currentTagsContainer}>
<Box
sx={{
fontSize: 14,
fontWeight: "normal",
}}
>
Current Tags:
<br />
{currTagKeys.length === 0 ? (
<span className={classes.noTagsForObject}>
<span className={"muted"}>
There are no tags for this object
</span>
) : (
@@ -273,16 +242,11 @@ const AddTagModal = ({
onDelete: null,
}}
>
<Chip
style={{
textTransform: "none",
marginRight: "5px",
marginBottom: "5px",
}}
size="small"
<Tag
id={`${tagKey} : ${tag}`}
label={`${tagKey} : ${tag}`}
color="primary"
deleteIcon={<CloseIcon />}
variant={"regular"}
color={"default"}
onDelete={() => {
onDeleteTag(tagKey, tag);
}}
@@ -293,7 +257,7 @@ const AddTagModal = ({
return null;
})}
</Box>
</div>
</Box>
</Box>
</SecureComponent>
<SecureComponent
@@ -304,11 +268,11 @@ const AddTagModal = ({
resource={bucketName}
errorProps={{ disabled: true, onClick: null }}
>
<Grid container>
<Box>
<SectionTitle icon={<AddNewTagIcon />} separator={false}>
Add New Tag
</SectionTitle>
<Grid item xs={12} className={classes.formFieldRow}>
<FormLayout containerPadding={false} withBorders={false}>
<InputBox
value={newKey}
label={"Tag Key"}
@@ -319,8 +283,6 @@ const AddTagModal = ({
setNewKey(e.target.value);
}}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBox
value={newLabel}
label={"Tag Label"}
@@ -331,36 +293,36 @@ const AddTagModal = ({
setNewLabel(e.target.value);
}}
/>
</Grid>
<Grid item xs={12} className={classes.modalButtonBar}>
<Button
id={"clear"}
type="button"
variant="regular"
color="primary"
onClick={resetForm}
label={"Clear"}
/>
<Button
type="submit"
variant="callAction"
disabled={
newLabel.trim() === "" ||
newKey.trim() === "" ||
isSending
}
onClick={addTagProcess}
id="saveTag"
label={"Save"}
/>
</Grid>
</Grid>
<Grid item xs={12} sx={modalStyleUtils.modalButtonBar}>
<Button
id={"clear"}
type="button"
variant="regular"
color="primary"
onClick={resetForm}
label={"Clear"}
/>
<Button
type="submit"
variant="callAction"
disabled={
newLabel.trim() === "" ||
newKey.trim() === "" ||
isSending
}
onClick={addTagProcess}
id="saveTag"
label={"Save"}
/>
</Grid>
</FormLayout>
</Box>
</SecureComponent>
</Grid>
</Box>
)}
</ModalWrapper>
</Fragment>
);
};
export default withStyles(styles)(AddTagModal);
export default AddTagModal;

View File

@@ -17,36 +17,24 @@
import React, { Fragment, useEffect, useState } from "react";
import get from "lodash/get";
import { useSelector } from "react-redux";
import { withStyles } from "@mui/styles";
import { Theme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles";
import Grid from "@mui/material/Grid";
import ShareFile from "./ShareFile";
import {
actionsTray,
containerForHeader,
objectBrowserCommon,
objectBrowserExtras,
spacingUtils,
tableStyles,
textStyleUtils,
} from "../../../../Common/FormComponents/common/styleLibrary";
breakPoints,
Button,
DeleteIcon,
DeleteNonCurrentIcon,
Grid,
ProgressBar,
ScreenTitle,
Select,
SelectMultipleIcon,
VersionsIcon,
} from "mds";
import ShareFile from "./ShareFile";
import { decodeURLString, niceBytesInt } from "../../../../../../common/utils";
import RestoreFileVersion from "./RestoreFileVersion";
import { AppState, useAppDispatch } from "../../../../../../store";
import {
Button,
DeleteIcon,
DeleteNonCurrentIcon,
Select,
SelectMultipleIcon,
VersionsIcon,
ScreenTitle,
ProgressBar,
} from "mds";
import FileVersionItem from "./FileVersionItem";
import PreviewFileModal from "../Preview/PreviewFileModal";
import DeleteNonCurrent from "../ListObjects/DeleteNonCurrent";
@@ -68,54 +56,7 @@ import { BucketObject } from "api/consoleApi";
import { api } from "api";
import { errorToHandler } from "api/errors";
const styles = (theme: Theme) =>
createStyles({
versionsContainer: {
padding: 10,
"@media (max-width: 799px)": {
minHeight: 800,
},
},
noBottomBorder: {
borderBottom: 0,
},
versionsVirtualPanel: {
flexGrow: 1,
height: "calc(100% - 120px)",
overflow: "auto",
"@media (max-width: 799px)": {
height: 600,
},
},
screenTitleContainer: {
position: "relative",
"@media (max-width: 799px)": {
"&::before": {
display: "none",
},
},
},
sortByLabel: {
color: "#838383",
fontWeight: "bold",
whiteSpace: "nowrap",
marginRight: 12,
fontSize: 14,
"@media (max-width: 600px)": {
display: "none",
},
},
...actionsTray,
...tableStyles,
...spacingUtils,
...textStyleUtils,
...objectBrowserCommon,
...objectBrowserExtras,
...containerForHeader,
});
interface IVersionsNavigatorProps {
classes: any;
internalPaths: string;
bucketName: string;
}
@@ -133,7 +74,6 @@ const emptyFile: BucketObject = {
};
const VersionsNavigator = ({
classes,
internalPaths,
bucketName,
}: IVersionsNavigatorProps) => {
@@ -422,7 +362,16 @@ const VersionsNavigator = ({
closeDeleteModalAndRefresh={closeSelectedVersions}
/>
)}
<Grid container className={classes.versionsContainer}>
<Grid
container
sx={{
width: "100%",
padding: 10,
"@media (max-width: 799px)": {
minHeight: 800,
},
}}
>
{!actualInfo && (
<Grid item xs={12}>
<ProgressBar />
@@ -438,11 +387,33 @@ const VersionsNavigator = ({
hidePathButton={true}
/>
</Grid>
<Grid item xs={12} className={classes.screenTitleContainer}>
<Grid
item
xs={12}
sx={{
position: "relative",
"& .detailsSpacer": {
marginRight: 18,
"@media (max-width: 600px)": {
marginRight: 0,
},
},
[`@media (max-width: ${breakPoints.md}px)`]: {
"&::before": {
display: "none",
},
},
}}
>
<ScreenTitle
icon={
<span className={classes.listIcon}>
<VersionsIcon />
<span
style={{
display: "block",
marginTop: "-10px",
}}
>
<VersionsIcon style={{ width: 20, height: 20 }} />
</span>
}
title={`${
@@ -452,13 +423,13 @@ const VersionsNavigator = ({
} Versions`}
subTitle={
<Fragment>
<span className={classes.detailsSpacer}>
<span className={"detailsSpacer"}>
<strong>
{versions.length} Version
{versions.length === 1 ? "" : "s"}&nbsp;&nbsp;&nbsp;
</strong>
</span>
<span className={classes.detailsSpacer}>
<span className={"detailsSpacer"}>
<strong>{niceBytesInt(totalSpace)}</strong>
</span>
</Fragment>
@@ -523,7 +494,18 @@ const VersionsNavigator = ({
bottomBorder={false}
/>
</Grid>
<Grid item xs={12} className={classes.versionsVirtualPanel}>
<Grid
item
xs={12}
sx={{
flexGrow: 1,
height: "calc(100% - 120px)",
overflow: "auto",
[`@media (max-width: ${breakPoints.md}px)`]: {
height: 600,
},
}}
>
{actualInfo.version_id && actualInfo.version_id !== "null" && (
// @ts-ignore
<List
@@ -549,4 +531,4 @@ const VersionsNavigator = ({
);
};
export default withStyles(styles)(VersionsNavigator);
export default VersionsNavigator;

View File

@@ -30,8 +30,6 @@ import {
useRegisterActions,
} from "kbar";
import { Action } from "kbar/lib/types";
import { Theme } from "@mui/material/styles";
import makeStyles from "@mui/styles/makeStyles";
import { routesAsKbarActions } from "./kbar-actions";
import { Box, MenuExpandedIcon } from "mds";
@@ -40,21 +38,6 @@ import { selFeatures } from "./consoleSlice";
import { Bucket } from "../../api/consoleApi";
import { api } from "../../api";
const useStyles = makeStyles((theme: Theme) => ({
resultItem: {
display: "flex",
gap: "8px",
alignItems: "center",
fontSize: 14,
flex: 1,
justifyContent: "space-between",
"& .min-icon": {
width: "17px",
height: "17px",
},
},
}));
const searchStyle = {
padding: "12px 16px",
width: "100%",
@@ -212,7 +195,6 @@ const ResultItem = React.forwardRef(
},
ref: React.Ref<HTMLDivElement>,
) => {
const classes = useStyles();
const ancestors = React.useMemo(() => {
if (!currentRootActionId) return action.ancestors;
const index = action.ancestors.findIndex(
@@ -238,7 +220,20 @@ const ResultItem = React.forwardRef(
cursor: "pointer",
}}
>
<div className={classes.resultItem}>
<Box
sx={{
display: "flex",
gap: "8px",
alignItems: "center",
fontSize: 14,
flex: 1,
justifyContent: "space-between",
"& .min-icon": {
width: "17px",
height: "17px",
},
}}
>
<Box sx={{ height: "15px", width: "15px", marginRight: "36px" }}>
{action.icon && action.icon}
</Box>
@@ -292,7 +287,7 @@ const ResultItem = React.forwardRef(
>
<MenuExpandedIcon />
</Box>
</div>
</Box>
{action.shortcut?.length ? (
<div
aria-hidden

View File

@@ -153,181 +153,6 @@ export const actionsTray = {
},
};
export const searchField = {
searchField: {},
};
export const predefinedList = {
prefinedContainer: {
display: "flex",
width: "100%",
alignItems: "center" as const,
margin: "15px 0 0",
},
predefinedTitle: {
color: "rgba(0, 0, 0, 0.87)",
display: "flex" as const,
overflow: "hidden" as const,
fontSize: 14,
maxWidth: 160,
textAlign: "left" as const,
marginRight: 10,
flexGrow: 0,
fontWeight: "normal" as const,
},
predefinedList: {
backgroundColor: "#fbfafa",
border: "#e5e5e5 1px solid",
padding: "12px 10px",
color: "#696969",
fontSize: 12,
fontWeight: 600,
minHeight: 41,
borderRadius: 4,
},
innerContent: {
width: "100%",
overflowX: "auto" as const,
whiteSpace: "nowrap" as const,
scrollbarWidth: "none" as const,
"&::-webkit-scrollbar": {
display: "none",
},
},
innerContentMultiline: {
width: "100%",
maxHeight: 100,
overflowY: "auto" as const,
scrollbarWidth: "none" as const,
"&::-webkit-scrollbar": {
display: "none",
},
},
includesActionButton: {
paddingRight: 45,
position: "relative" as const,
},
overlayShareOption: {
position: "absolute" as const,
width: 45,
right: 0,
top: "50%",
transform: "translate(0, -50%)",
},
};
export const objectBrowserCommon = {
breadcrumbsMain: {
display: "flex",
},
breadcrumbs: {
fontSize: 12,
color: "#969FA8",
fontWeight: "bold",
border: "#EAEDEE 1px solid",
height: 38,
display: "flex",
alignItems: "center",
backgroundColor: "#FCFCFD",
marginRight: 10,
"& a": {
textDecoration: "none",
color: "#969FA8",
"&:hover": {
textDecoration: "underline",
},
},
"& .min-icon": {
width: 16,
minWidth: 16,
},
},
additionalOptions: {
paddingRight: "10px",
display: "flex",
alignItems: "center",
"@media (max-width: 1060px)": {
display: "none",
},
},
bucketDetails: {
marginLeft: 10,
fontSize: 14,
color: "#969FA8",
"@media (max-width: 600px)": {
marginLeft: 0,
"& span": {
marginBottom: 10,
display: "flex",
flexDirection: "column",
},
},
},
detailsSpacer: {
marginRight: 18,
"@media (max-width: 600px)": {
marginRight: 0,
},
},
breadcrumbsList: {
textOverflow: "ellipsis" as const,
overflow: "hidden" as const,
whiteSpace: "nowrap" as const,
display: "inline-block" as const,
flexGrow: 1,
textAlign: "left" as const,
marginLeft: 15,
marginRight: 10,
width: 0, // WA to avoid overflow if child elements in flexbox list.**
},
breadcrumbsSecond: {
display: "none" as const,
marginTop: 15,
marginBottom: 5,
justifyContent: "flex-start" as const,
"& > div": {
fontSize: 12,
fontWeight: "normal",
flexDirection: "row" as const,
flexWrap: "nowrap" as const,
},
"@media (max-width: 1060px)": {
display: "flex" as const,
},
},
overrideShowDeleted: {
"@media (max-width: 600px)": {
flexDirection: "row" as const,
},
},
};
// ** According to W3 spec, default minimum values for flex width flex-grow is "auto" (https://drafts.csswg.org/css-flexbox/#min-size-auto). So in this case we need to enforce the use of an absolute width.
// "The preferred width of a box element child containing text content is currently the text without line breaks, leading to very unintuitive width and flex calculations → declare a width on a box element child with more than a few words (ever wonder why flexbox demos are all “1,2,3”?)"
export const settingsCommon: any = {
settingsFormContainer: {
padding: 38,
overflowY: "auto" as const,
scrollbarWidth: "none" as const,
"&::-webkit-scrollbar": {
display: "none",
},
},
settingsButtonContainer: {
padding: "15px 38px",
display: "flex",
justifyContent: "flex-end",
},
settingsOptionsContainer: {
height: "calc(100vh - 244px)",
backgroundColor: "#fff",
border: "#EAEDEE 1px solid",
borderRadius: 3,
marginTop: 15,
},
};
export const typesSelection = {
iconContainer: {
display: "flex" as const,
@@ -517,55 +342,6 @@ export const snackBarCommon = {
},
};
export const wizardCommon = {
multiContainer: {
display: "flex" as const,
alignItems: "center" as const,
justifyContent: "flex-start" as const,
},
multiContainerStackNarrow: {
display: "flex",
alignItems: "center",
justifyContent: "flex-start",
gap: "8px",
"@media (max-width: 750px)": {
flexFlow: "column",
flexDirection: "column",
},
},
headerElement: {
position: "sticky" as const,
top: 0,
paddingTop: 5,
marginBottom: 10,
zIndex: 500,
backgroundColor: "#fff",
},
error: {
color: "#dc1f2e",
fontSize: "0.75rem",
},
descriptionText: {
fontSize: 14,
},
container: {
padding: "77px 0 0 0",
"& h6": {
color: "#777777",
fontSize: 14,
},
"& p": {
"& span:not(*[class*='smallUnit'])": {
fontSize: 16,
},
},
},
paperWrapper: {
padding: 12,
border: 0,
},
};
export const inputFieldStyles = {
root: {
borderRadius: 3,
@@ -610,43 +386,6 @@ export const inputFieldStyles = {
},
};
export const tableStyles: any = {
tableBlock: {
display: "flex",
flexDirection: "row",
"& .optionsAlignment ": {
textAlign: "right",
"& .MuiButtonBase-root": {
backgroundColor: "#F8F8F8",
},
"&:hover": {
backgroundColor: "#E2E2E2",
},
"& .min-icon": {
width: 13,
margin: 3,
},
},
},
};
export const spacingUtils: any = {
spacerRight: {
marginRight: ".9rem",
},
spacerLeft: {
marginLeft: ".9rem",
},
spacerBottom: {
marginBottom: ".9rem",
},
spacerTop: {
marginTop: ".9rem",
},
};
export const formFieldStyles: any = {
formFieldRow: {
marginBottom: ".8rem",
@@ -695,16 +434,6 @@ export const deleteDialogStyles: any = {
},
};
export const createTenantCommon: any = {
fieldGroup: {
border: "1px solid #EAEAEA",
paddingTop: 15,
},
descriptionText: {
fontSize: 14,
},
};
export const modalStyleUtils: any = {
modalButtonBar: {
marginTop: 15,
@@ -720,79 +449,6 @@ export const modalStyleUtils: any = {
},
};
export const textStyleUtils: any = {
textMuted: {
color: "#8399AB",
},
};
export const detailsPanel: any = {
metadataLinear: {
marginBottom: 15,
fontSize: 14,
maxHeight: 180,
overflowY: "auto",
},
detailContainer: {
padding: "0 22px",
marginBottom: 20,
fontSize: 14,
},
titleLabel: {
fontSize: 14,
fontWeight: "700",
color: "#000",
padding: "12px 30px 8px 22px",
whiteSpace: "nowrap",
textOverflow: "ellipsis",
overflow: "hidden",
alignItems: "center",
},
objectActions: {
backgroundColor: "#F8F8F8",
border: "#F1F1F1 1px solid",
borderRadius: 3,
margin: "8px 22px",
padding: 0,
color: "#696969",
"& li": {
listStyle: "none",
padding: 6,
margin: 0,
borderBottom: "#E5E5E5 1px solid",
fontSize: 14,
"&:first-of-type": {
padding: 10,
fontWeight: "bold",
color: "#000",
},
"&:last-of-type": {
borderBottom: 0,
},
"&::before": {
content: "' '!important",
},
},
},
};
export const objectBrowserExtras = {
listIcon: {
display: "block",
marginTop: "-10px",
"& .min-icon": {
width: 20,
height: 20,
},
},
titleSpacer: {
marginLeft: 10,
"@media (max-width: 600px)": {
marginLeft: 0,
},
},
};
export const twoColCssGridLayoutConfig = {
display: "grid",
gridTemplateColumns: "2fr 1fr",

View File

@@ -15,11 +15,8 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import React from "react";
import { Button, ModalBox, Box } from "mds";
import { Theme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles";
import withStyles from "@mui/styles/withStyles";
import { deleteDialogStyles } from "../FormComponents/common/styleLibrary";
import { Box, Button, ModalBox } from "mds";
interface ButtonProps {
label?: string;
variant?: "regular" | "callAction" | "secondary";
@@ -30,17 +27,11 @@ interface ButtonProps {
onClick?: React.MouseEventHandler<HTMLButtonElement>;
}
const styles = (theme: Theme) =>
createStyles({
...deleteDialogStyles,
});
type ConfirmDialogProps = {
isOpen?: boolean;
onClose: () => void;
onCancel?: () => void;
onConfirm: () => void;
classes?: any;
title: string;
isLoading?: boolean;
confirmationContent: React.ReactNode | React.ReactNode[];
@@ -59,7 +50,6 @@ const ConfirmDialog = ({
onClose,
onCancel,
onConfirm,
classes = {},
title = "",
isLoading,
confirmationContent,
@@ -78,7 +68,7 @@ const ConfirmDialog = ({
open={isOpen}
customMaxWidth={510}
>
<Box className={classes.content}>{confirmationContent}</Box>
<Box>{confirmationContent}</Box>
<Box
sx={{
display: "flex",
@@ -110,4 +100,4 @@ const ConfirmDialog = ({
);
};
export default withStyles(styles)(ConfirmDialog);
export default ConfirmDialog;

View File

@@ -37,6 +37,7 @@ interface IModalProps {
children: any;
wideLimit?: boolean;
titleIcon?: React.ReactNode;
iconColor?: "default" | "delete" | "accept";
sx?: CSSObject;
}
@@ -54,6 +55,7 @@ const ModalWrapper = ({
classes,
wideLimit = true,
titleIcon = null,
iconColor = "default",
sx,
}: IModalProps) => {
const dispatch = useAppDispatch();
@@ -105,6 +107,7 @@ const ModalWrapper = ({
titleIcon={titleIcon}
widthLimit={wideLimit}
sx={sx}
iconColor={iconColor}
>
<MainError isModal={true} />
<Snackbar

View File

@@ -15,43 +15,41 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import React, { Fragment, useEffect, useState } from "react";
import styled from "styled-components";
import get from "lodash/get";
import { Button, CircleIcon, ObjectManagerIcon } from "mds";
import { useSelector } from "react-redux";
import { toggleList } from "../../ObjectBrowser/objectBrowserSlice";
import { AppState, useAppDispatch } from "../../../../store";
import { useSelector } from "react-redux";
import makeStyles from "@mui/styles/makeStyles";
const useStyles = makeStyles((theme) => ({
indicator: {
position: "absolute",
display: "block",
width: 15,
height: 15,
top: 0,
right: 4,
marginTop: 4,
const IndicatorContainer = styled.div(({ theme }) => ({
position: "absolute",
display: "block",
width: 15,
height: 15,
top: 0,
right: 4,
marginTop: 4,
transitionDuration: "0.2s",
color: get(theme, "signalColors.good", "#32C787"),
"& svg": {
width: 10,
height: 10,
top: "50%",
left: "50%",
transitionDuration: "0.2s",
color: "#32C787",
},
"&.newItem": {
color: get(theme, "signalColors.info", "#2781B0"),
"& svg": {
width: 10,
height: 10,
top: "50%",
left: "50%",
transitionDuration: "0.2s",
},
"&.newItem": {
color: "#2781B0",
"& svg": {
width: 15,
height: 15,
},
width: 15,
height: 15,
},
},
}));
const ObjectManagerButton = () => {
const dispatch = useAppDispatch();
const classes = useStyles();
const managerObjects = useSelector(
(state: AppState) => state.objectBrowser.objectManager.objectsToManage,
);
@@ -83,14 +81,14 @@ const ObjectManagerButton = () => {
}}
icon={
<Fragment>
<div
className={`${classes.indicator} ${newObject ? "newItem" : ""}`}
<IndicatorContainer
className={newObject ? "newItem" : ""}
style={{
opacity: managerObjects.length > 0 && newItems ? 1 : 0,
}}
>
<CircleIcon />
</div>
</IndicatorContainer>
<ObjectManagerIcon
style={{ width: 20, height: 20, marginTop: -2 }}
/>

View File

@@ -15,27 +15,20 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import React from "react";
import { Theme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles";
import withStyles from "@mui/styles/withStyles";
import { IconButtonProps } from "@mui/material";
import styled from "styled-components";
const styles = (theme: Theme) =>
createStyles({
root: {
padding: 0,
margin: 0,
fontSize: ".9rem",
},
});
const PanelTitleContainer = styled.h1(() => ({
padding: 0,
margin: 0,
fontSize: ".9rem",
}));
interface IPanelTitle extends IconButtonProps {
classes: any;
children: any;
interface IPanelTitle {
children: React.ReactNode;
}
const PanelTitle = ({ classes, children }: IPanelTitle) => {
return <h1 className={classes.root}>{children}</h1>;
const PanelTitle = ({ children }: IPanelTitle) => {
return <PanelTitleContainer>{children}</PanelTitleContainer>;
};
export default withStyles(styles)(PanelTitle);
export default PanelTitle;

View File

@@ -15,13 +15,11 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import React, { Fragment, useCallback, useEffect, useState } 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 { BackLink, Button, FormLayout, Grid, InputBox, PageLayout } from "mds";
import { useNavigate, useParams } from "react-router-dom";
import { api } from "api";
import { errorToHandler } from "api/errors";
import {
destinationList,
notificationEndpointsFields,
@@ -29,29 +27,19 @@ import {
notifyPostgres,
removeEmptyFields,
} from "./utils";
import {
modalBasic,
settingsCommon,
} from "../Common/FormComponents/common/styleLibrary";
import { IElementValue } from "../Configurations/types";
import withSuspense from "../Common/Components/withSuspense";
import { IAM_PAGES } from "../../../common/SecureComponent/permissions";
import {
setErrorSnackMessage,
setHelpName,
setServerNeedsRestart,
} from "../../../systemSlice";
import { useNavigate, useParams } from "react-router-dom";
import { useAppDispatch } from "../../../store";
import { setDestinationLoading } from "./destinationsSlice";
import withSuspense from "../Common/Components/withSuspense";
import PageHeaderWrapper from "../Common/PageHeaderWrapper/PageHeaderWrapper";
import TargetTitle from "./TargetTitle";
import { setDestinationLoading } from "./destinationsSlice";
import HelpMenu from "../HelpMenu";
import { api } from "api";
import { errorToHandler } from "api/errors";
const ConfMySql = withSuspense(
React.lazy(() => import("./CustomForms/ConfMySql")),
@@ -65,20 +53,12 @@ const ConfPostgres = withSuspense(
React.lazy(() => import("./CustomForms/ConfPostgres")),
);
const styles = (theme: Theme) =>
createStyles({
...modalBasic,
...settingsCommon,
});
interface IAddNotificationEndpointProps {
saveAndRefresh: any;
classes: any;
}
const AddEventDestination = ({
saveAndRefresh,
classes,
}: IAddNotificationEndpointProps) => {
const dispatch = useAppDispatch();
const navigate = useNavigate();
@@ -187,23 +167,16 @@ const AddEventDestination = ({
)}
</Grid>
<FormLayout>
<Grid
item
xs={12}
className={classes.formFieldRow}
sx={{ marginBottom: "12px" }}
>
<InputBox
id={"identifier-field"}
name={"identifier-field"}
label={"Identifier"}
value={identifier}
onChange={(e) => setIdentifier(e.target.value)}
tooltip={"Unique descriptive string for this destination"}
placeholder="Enter Destination Identifier"
required
/>
</Grid>
<InputBox
id={"identifier-field"}
name={"identifier-field"}
label={"Identifier"}
value={identifier}
onChange={(e) => setIdentifier(e.target.value)}
tooltip={"Unique descriptive string for this destination"}
placeholder="Enter Destination Identifier"
required
/>
<Grid item xs={12}>
{srvComponent}
</Grid>
@@ -233,4 +206,4 @@ const AddEventDestination = ({
);
};
export default withStyles(styles)(AddEventDestination);
export default AddEventDestination;

View File

@@ -15,36 +15,23 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import React, { useCallback, useEffect, useState } from "react";
import { Theme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles";
import withStyles from "@mui/styles/withStyles";
import { IElementValue } from "../../Configurations/types";
import {
formFieldStyles,
modalBasic,
} from "../../Common/FormComponents/common/styleLibrary";
import {
Switch,
InputBox,
Grid,
Box,
ReadBox,
RadioGroup,
CommentBox,
FormLayout,
Grid,
InputBox,
RadioGroup,
ReadBox,
Switch,
} from "mds";
interface IConfMySqlProps {
onChange: (newValue: IElementValue[]) => void;
classes: any;
}
const styles = (theme: Theme) =>
createStyles({
...modalBasic,
...formFieldStyles,
});
const ConfMySql = ({ onChange, classes }: IConfMySqlProps) => {
const ConfMySql = ({ onChange }: IConfMySqlProps) => {
//Local States
const [useDsnString, setUseDsnString] = useState<boolean>(false);
const [dsnString, setDsnString] = useState<string>("");
@@ -140,20 +127,18 @@ const ConfMySql = ({ onChange, classes }: IConfMySqlProps) => {
};
return (
<Grid container>
<Grid item xs={12} className={classes.formFieldRow}>
<Switch
label={"Enter DNS String"}
checked={useDsnString}
id="checkedB"
name="checkedB"
onChange={switcherChangeEvt}
value={"dnsString"}
/>
</Grid>
<FormLayout withBorders={false} containerPadding={false}>
<Switch
label={"Enter DNS String"}
checked={useDsnString}
id="checkedB"
name="checkedB"
onChange={switcherChangeEvt}
value={"dnsString"}
/>
{useDsnString ? (
<React.Fragment>
<Grid item xs={12} className={classes.formFieldRow}>
<Box className={"inputItem"}>
<InputBox
id="dsn-string"
name="dsn_string"
@@ -163,11 +148,11 @@ const ConfMySql = ({ onChange, classes }: IConfMySqlProps) => {
setDsnString(e.target.value);
}}
/>
</Grid>
</Box>
</React.Fragment>
) : (
<React.Fragment>
<Grid item xs={12}>
<Box>
<Box
withBorders
useBackground
@@ -177,70 +162,59 @@ const ConfMySql = ({ onChange, classes }: IConfMySqlProps) => {
marginBottom: 12,
}}
>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBox
id="host"
name="host"
label=""
placeholder="Enter Host"
value={host}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setHostname(e.target.value);
}}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBox
id="db-name"
name="db-name"
label=""
placeholder="Enter DB Name"
value={dbName}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setDbName(e.target.value);
}}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBox
id="port"
name="port"
label=""
placeholder="Enter Port"
value={port}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setPort(e.target.value);
}}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBox
id="user"
name="user"
label=""
placeholder="Enter User"
value={user}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setUser(e.target.value);
}}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBox
id="password"
name="password"
label=""
placeholder="Enter Password"
type="password"
value={password}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setPassword(e.target.value);
}}
/>
</Grid>
<InputBox
id="host"
name="host"
label=""
placeholder="Enter Host"
value={host}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setHostname(e.target.value);
}}
/>
<InputBox
id="db-name"
name="db-name"
label=""
placeholder="Enter DB Name"
value={dbName}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setDbName(e.target.value);
}}
/>
<InputBox
id="port"
name="port"
label=""
placeholder="Enter Port"
value={port}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setPort(e.target.value);
}}
/>
<InputBox
id="user"
name="user"
label=""
placeholder="Enter User"
value={user}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setUser(e.target.value);
}}
/>
<InputBox
id="password"
name="password"
label=""
placeholder="Enter Password"
type="password"
value={password}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setPassword(e.target.value);
}}
/>
</Box>
</Grid>
</Box>
<Grid item xs={12} sx={{ margin: "12px 0" }}>
<ReadBox label={"Connection String"} multiLine>
{dsnString}
@@ -248,76 +222,66 @@ const ConfMySql = ({ onChange, classes }: IConfMySqlProps) => {
</Grid>
</React.Fragment>
)}
<Grid item xs={12} className={classes.formFieldRow}>
<InputBox
id="table"
name="table"
label="Table"
placeholder="Enter Table Name"
value={table}
tooltip="DB table name to store/update events, table is auto-created"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setTable(e.target.value);
}}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<RadioGroup
currentValue={format}
id="format"
name="format"
label="Format"
onChange={(e) => {
setFormat(e.target.value);
}}
tooltip="'namespace' reflects current bucket/object list and 'access' reflects a journal of object operations, defaults to 'namespace'"
selectorOptions={[
{ label: "Namespace", value: "namespace" },
{ label: "Access", value: "access" },
]}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBox
id="queue-dir"
name="queue_dir"
label="Queue Dir"
placeholder="Enter Queue Dir"
value={queueDir}
tooltip="Staging directory for undelivered messages e.g. '/home/events'"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setQueueDir(e.target.value);
}}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBox
id="queue-limit"
name="queue_limit"
label="Queue Limit"
placeholder="Enter Queue Limit"
type="number"
value={queueLimit}
tooltip="Maximum limit for undelivered messages, defaults to '10000'"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setQueueLimit(e.target.value);
}}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<CommentBox
id="comment"
name="comment"
label="Comment"
placeholder="Enter custom notes if any"
value={comment}
onChange={(e) => {
setComment(e.target.value);
}}
/>
</Grid>
</Grid>
<InputBox
id="table"
name="table"
label="Table"
placeholder="Enter Table Name"
value={table}
tooltip="DB table name to store/update events, table is auto-created"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setTable(e.target.value);
}}
/>
<RadioGroup
currentValue={format}
id="format"
name="format"
label="Format"
onChange={(e) => {
setFormat(e.target.value);
}}
tooltip="'namespace' reflects current bucket/object list and 'access' reflects a journal of object operations, defaults to 'namespace'"
selectorOptions={[
{ label: "Namespace", value: "namespace" },
{ label: "Access", value: "access" },
]}
/>
<InputBox
id="queue-dir"
name="queue_dir"
label="Queue Dir"
placeholder="Enter Queue Dir"
value={queueDir}
tooltip="Staging directory for undelivered messages e.g. '/home/events'"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setQueueDir(e.target.value);
}}
/>
<InputBox
id="queue-limit"
name="queue_limit"
label="Queue Limit"
placeholder="Enter Queue Limit"
type="number"
value={queueLimit}
tooltip="Maximum limit for undelivered messages, defaults to '10000'"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setQueueLimit(e.target.value);
}}
/>
<CommentBox
id="comment"
name="comment"
label="Comment"
placeholder="Enter custom notes if any"
value={comment}
onChange={(e) => {
setComment(e.target.value);
}}
/>
</FormLayout>
);
};
export default withStyles(styles)(ConfMySql);
export default ConfMySql;

View File

@@ -14,13 +14,11 @@
// 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, { useCallback, useEffect, useState } from "react";
import { Theme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles";
import withStyles from "@mui/styles/withStyles";
import React, { Fragment, useCallback, useEffect, useState } from "react";
import {
Box,
CommentBox,
FormLayout,
Grid,
InputBox,
RadioGroup,
@@ -29,23 +27,12 @@ import {
Switch,
} from "mds";
import { IElementValue } from "../../Configurations/types";
import {
formFieldStyles,
modalBasic,
} from "../../Common/FormComponents/common/styleLibrary";
interface IConfPostgresProps {
onChange: (newValue: IElementValue[]) => void;
classes: any;
}
const styles = (theme: Theme) =>
createStyles({
...modalBasic,
...formFieldStyles,
});
const ConfPostgres = ({ onChange, classes }: IConfPostgresProps) => {
const ConfPostgres = ({ onChange }: IConfPostgresProps) => {
//Local States
const [useConnectionString, setUseConnectionString] =
useState<boolean>(false);
@@ -207,35 +194,31 @@ const ConfPostgres = ({ onChange, classes }: IConfPostgresProps) => {
}, [useConnectionString]);
return (
<Grid container>
<Grid item xs={12} className={classes.formFieldRow}>
<Switch
label={"Manually Configure String"}
checked={useConnectionString}
id="manualString"
name="manualString"
onChange={(e) => {
setUseConnectionString(e.target.checked);
}}
value={"manualString"}
/>
</Grid>
<FormLayout containerPadding={false} withBorders={false}>
<Switch
label={"Manually Configure String"}
checked={useConnectionString}
id="manualString"
name="manualString"
onChange={(e) => {
setUseConnectionString(e.target.checked);
}}
value={"manualString"}
/>
{useConnectionString ? (
<React.Fragment>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBox
id="connection-string"
name="connection_string"
label="Connection String"
value={connectionString}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setConnectionString(e.target.value);
}}
/>
</Grid>
</React.Fragment>
<Fragment>
<InputBox
id="connection-string"
name="connection_string"
label="Connection String"
value={connectionString}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setConnectionString(e.target.value);
}}
/>
</Fragment>
) : (
<React.Fragment>
<Fragment>
<Grid item xs={12}>
<Box
withBorders
@@ -246,166 +229,142 @@ const ConfPostgres = ({ onChange, classes }: IConfPostgresProps) => {
marginBottom: 12,
}}
>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBox
id="host"
name="host"
label=""
placeholder="Enter Host"
value={host}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setHostname(e.target.value);
}}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBox
id="db-name"
name="db-name"
label=""
placeholder="Enter DB Name"
value={dbName}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setDbName(e.target.value);
}}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBox
id="port"
name="port"
label=""
placeholder="Enter Port"
value={port}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setPort(e.target.value);
}}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<Select
value={sslMode}
label=""
id="sslmode"
name="sslmode"
onChange={(value): void => {
if (value) {
setSslMode(value + "");
}
}}
options={[
{ label: "Enter SSL Mode", value: " " },
{ label: "Require", value: "require" },
{ label: "Disable", value: "disable" },
{ label: "Verify CA", value: "verify-ca" },
{ label: "Verify Full", value: "verify-full" },
]}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBox
id="user"
name="user"
label=""
placeholder="Enter User"
value={user}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setUser(e.target.value);
}}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBox
id="password"
name="password"
label=""
type="password"
placeholder="Enter Password"
value={password}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setPassword(e.target.value);
}}
/>
</Grid>
<InputBox
id="host"
name="host"
label=""
placeholder="Enter Host"
value={host}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setHostname(e.target.value);
}}
/>
<InputBox
id="db-name"
name="db-name"
label=""
placeholder="Enter DB Name"
value={dbName}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setDbName(e.target.value);
}}
/>
<InputBox
id="port"
name="port"
label=""
placeholder="Enter Port"
value={port}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setPort(e.target.value);
}}
/>
<Select
value={sslMode}
label=""
id="sslmode"
name="sslmode"
onChange={(value): void => {
if (value) {
setSslMode(value + "");
}
}}
options={[
{ label: "Enter SSL Mode", value: " " },
{ label: "Require", value: "require" },
{ label: "Disable", value: "disable" },
{ label: "Verify CA", value: "verify-ca" },
{ label: "Verify Full", value: "verify-full" },
]}
/>
<InputBox
id="user"
name="user"
label=""
placeholder="Enter User"
value={user}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setUser(e.target.value);
}}
/>
<InputBox
id="password"
name="password"
label=""
type="password"
placeholder="Enter Password"
value={password}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setPassword(e.target.value);
}}
/>
</Box>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<ReadBox label={"Connection String"} multiLine>
{connectionString}
</ReadBox>
</Grid>
</React.Fragment>
<ReadBox label={"Connection String"} multiLine>
{connectionString}
</ReadBox>
</Fragment>
)}
<Grid item xs={12} className={classes.formFieldRow}>
<InputBox
id="table"
name="table"
label="Table"
placeholder={"Enter Table Name"}
value={table}
tooltip="DB table name to store/update events, table is auto-created"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setTable(e.target.value);
}}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<RadioGroup
currentValue={format}
id="format"
name="format"
label="Format"
onChange={(e) => {
setFormat(e.target.value);
}}
tooltip="'namespace' reflects current bucket/object list and 'access' reflects a journal of object operations, defaults to 'namespace'"
selectorOptions={[
{ label: "Namespace", value: "namespace" },
{ label: "Access", value: "access" },
]}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBox
id="queue-dir"
name="queue_dir"
label="Queue Dir"
placeholder="Enter Queue Directory"
value={queueDir}
tooltip="Staging directory for undelivered messages e.g. '/home/events'"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setQueueDir(e.target.value);
}}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<InputBox
id="queue-limit"
name="queue_limit"
label="Queue Limit"
placeholder="Enter Queue Limit"
type="number"
value={queueLimit}
tooltip="Maximum limit for undelivered messages, defaults to '10000'"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setQueueLimit(e.target.value);
}}
/>
</Grid>
<Grid item xs={12} className={classes.formFieldRow}>
<CommentBox
id="comment"
name="comment"
label="Comment"
placeholder="Enter custom notes if any"
value={comment}
onChange={(e) => {
setComment(e.target.value);
}}
/>
</Grid>
</Grid>
<InputBox
id="table"
name="table"
label="Table"
placeholder={"Enter Table Name"}
value={table}
tooltip="DB table name to store/update events, table is auto-created"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setTable(e.target.value);
}}
/>
<RadioGroup
currentValue={format}
id="format"
name="format"
label="Format"
onChange={(e) => {
setFormat(e.target.value);
}}
tooltip="'namespace' reflects current bucket/object list and 'access' reflects a journal of object operations, defaults to 'namespace'"
selectorOptions={[
{ label: "Namespace", value: "namespace" },
{ label: "Access", value: "access" },
]}
/>
<InputBox
id="queue-dir"
name="queue_dir"
label="Queue Dir"
placeholder="Enter Queue Directory"
value={queueDir}
tooltip="Staging directory for undelivered messages e.g. '/home/events'"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setQueueDir(e.target.value);
}}
/>
<InputBox
id="queue-limit"
name="queue_limit"
label="Queue Limit"
placeholder="Enter Queue Limit"
type="number"
value={queueLimit}
tooltip="Maximum limit for undelivered messages, defaults to '10000'"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setQueueLimit(e.target.value);
}}
/>
<CommentBox
id="comment"
name="comment"
label="Comment"
placeholder="Enter custom notes if any"
value={comment}
onChange={(e) => {
setComment(e.target.value);
}}
/>
</FormLayout>
);
};
export default withStyles(styles)(ConfPostgres);
export default ConfPostgres;

View File

@@ -20,6 +20,7 @@ import {
AddIcon,
Box,
Button,
CircleIcon,
DataTable,
Grid,
HelpBox,
@@ -28,65 +29,41 @@ import {
ProgressBar,
RefreshIcon,
} from "mds";
import { useSelector } from "react-redux";
import { useNavigate } from "react-router-dom";
import { Theme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles";
import withStyles from "@mui/styles/withStyles";
import { red } from "@mui/material/colors";
import FiberManualRecordIcon from "@mui/icons-material/FiberManualRecord";
import { api } from "api";
import { NotificationEndpointItem } from "api/consoleApi";
import { errorToHandler } from "api/errors";
import styled from "styled-components";
import get from "lodash/get";
import { TransformedEndpointItem } from "./types";
import { getNotificationConfigKey, notificationTransform } from "./utils";
import {
actionsTray,
containerForHeader,
searchField,
settingsCommon,
tableStyles,
} from "../Common/FormComponents/common/styleLibrary";
import SearchBox from "../Common/SearchBox";
import { actionsTray } from "../Common/FormComponents/common/styleLibrary";
import { IAM_PAGES } from "../../../common/SecureComponent/permissions";
import {
setErrorSnackMessage,
setServerNeedsRestart,
} from "../../../systemSlice";
import { AppState, useAppDispatch } from "../../../store";
import { setDestinationLoading } from "./destinationsSlice";
import SearchBox from "../Common/SearchBox";
import ConfirmDeleteDestinationModal from "./ConfirmDeleteDestinationModal";
import TooltipWrapper from "../Common/TooltipWrapper/TooltipWrapper";
import { useSelector } from "react-redux";
import { setDestinationLoading } from "./destinationsSlice";
import { api } from "api";
import { NotificationEndpointItem } from "api/consoleApi";
import { errorToHandler } from "api/errors";
interface IListNotificationEndpoints {
classes: any;
}
const StatusDisplay = styled.div(({ theme }) => ({
display: "flex",
alignItems: "center",
"& svg": {
width: 16,
marginRight: 5,
fill: get(theme, "signalColors.good", "#4CCB92"),
},
"& svg.offline": {
fill: get(theme, "signalColors.danger", "#C51B3F"),
},
}));
const styles = (theme: Theme) =>
createStyles({
...actionsTray,
...settingsCommon,
...containerForHeader,
tableBlock: {
...tableStyles.tableBlock,
},
rightActionItems: {
display: "flex",
alignItems: "center",
"& button": {
whiteSpace: "nowrap",
},
},
searchField: {
...searchField.searchField,
maxWidth: 380,
},
});
const ListEventDestinations = ({ classes }: IListNotificationEndpoints) => {
const ListEventDestinations = () => {
const dispatch = useAppDispatch();
const navigate = useNavigate();
// Reducer States
@@ -171,166 +148,162 @@ const ListEventDestinations = ({ classes }: IListNotificationEndpoints) => {
const statusDisplay = (status: string) => {
return (
<div
style={{
display: "flex",
alignItems: "center",
}}
>
<FiberManualRecordIcon
style={status === "Offline" ? { color: red[500] } : {}}
/>
<StatusDisplay>
<CircleIcon className={status === "Offline" ? "offline" : ""} />
{status}
</div>
</StatusDisplay>
);
};
return (
<Fragment>
<PageLayout>
<Grid container sx={{ width: "100%" }}>
<Grid item xs={12} className={classes.actionsTray}>
<SearchBox
placeholder="Search target"
onChange={setFilter}
overrideClass={classes.searchField}
value={filter}
/>
<div className={classes.rightActionItems}>
<TooltipWrapper tooltip={"Refresh List"}>
<Button
id={"reload-event-destinations"}
label={"Refresh"}
variant="regular"
icon={<RefreshIcon />}
onClick={() => {
dispatch(setDestinationLoading(true));
}}
/>
</TooltipWrapper>
<TooltipWrapper tooltip={"Add Event Destination"}>
<Button
id={"add-notification-target"}
label={"Add Event Destination"}
variant="callAction"
icon={<AddIcon />}
onClick={() => {
navigate(IAM_PAGES.EVENT_DESTINATIONS_ADD);
}}
/>
</TooltipWrapper>
</div>
</Grid>
{isLoading && <ProgressBar />}
{!isLoading && (
<Fragment>
{records.length > 0 && (
<Fragment>
<Grid item xs={12} className={classes.tableBlock}>
<Box sx={{ width: "100%" }}>
<DataTable
itemActions={tableActions}
columns={[
{
label: "Status",
elementKey: "status",
renderFunction: statusDisplay,
width: 150,
},
{ label: "Service", elementKey: "service_name" },
]}
isLoading={isLoading}
records={filteredRecords}
entityName="Event Destinations"
idField="service_name"
customPaperHeight={"400px"}
/>
</Box>
</Grid>
<Grid item xs={12} sx={{ marginTop: 15 }}>
<HelpBox
title={"Event Destinations"}
iconComponent={<LambdaIcon />}
help={
<Fragment>
MinIO bucket notifications allow administrators to
send notifications to supported external services on
certain object or bucket events. MinIO supports bucket
and object-level S3 events similar to the Amazon S3
Event Notifications.
<br />
<br />
You can learn more at our{" "}
<a
href="https://min.io/docs/minio/linux/administration/monitoring/bucket-notifications.html?ref=con"
target="_blank"
rel="noopener"
>
documentation
</a>
.
</Fragment>
}
/>
</Grid>
</Fragment>
)}
{records.length === 0 && (
<Grid
container
sx={{
justifyContent: "center",
alignContent: "center",
alignItems: "center",
}}
>
<Grid item xs={8}>
<HelpBox
title={"Event Destinations"}
iconComponent={<LambdaIcon />}
help={
<Fragment>
MinIO bucket notifications allow administrators to
send notifications to supported external services on
certain object or bucket events. MinIO supports bucket
and object-level S3 events similar to the Amazon S3
Event Notifications.
<br />
<br />
To get started,{" "}
<ActionLink
onClick={() => {
navigate(IAM_PAGES.EVENT_DESTINATIONS_ADD);
}}
>
Add an Event Destination
</ActionLink>
.
</Fragment>
}
/>
</Grid>
</Grid>
)}
</Fragment>
)}
{isDelConfirmOpen ? (
<ConfirmDeleteDestinationModal
onConfirm={() => {
resetNotificationConfig(selNotifyEndPoint);
}}
status={`${selNotifyEndPoint?.status}`}
serviceName={`${selNotifyEndPoint?.service_name}`}
onClose={() => {
setIsDelConfirmOpen(false);
}}
/>
) : null}
<Grid item xs={12} sx={actionsTray.actionsTray}>
<SearchBox
placeholder="Search target"
onChange={setFilter}
value={filter}
sx={{ maxWidth: 380 }}
/>
<Box
sx={{
display: "flex",
alignItems: "center",
justifyContent: "flex-end",
gap: 5,
}}
>
<TooltipWrapper tooltip={"Refresh List"}>
<Button
id={"reload-event-destinations"}
label={"Refresh"}
variant="regular"
icon={<RefreshIcon />}
onClick={() => {
dispatch(setDestinationLoading(true));
}}
/>
</TooltipWrapper>
<TooltipWrapper tooltip={"Add Event Destination"}>
<Button
id={"add-notification-target"}
label={"Add Event Destination"}
variant="callAction"
icon={<AddIcon />}
onClick={() => {
navigate(IAM_PAGES.EVENT_DESTINATIONS_ADD);
}}
/>
</TooltipWrapper>
</Box>
</Grid>
{isLoading && <ProgressBar />}
{!isLoading && (
<Fragment>
{records.length > 0 && (
<Fragment>
<Box sx={{ width: "100%" }}>
<DataTable
itemActions={tableActions}
columns={[
{
label: "Status",
elementKey: "status",
renderFunction: statusDisplay,
width: 150,
},
{ label: "Service", elementKey: "service_name" },
]}
isLoading={isLoading}
records={filteredRecords}
entityName="Event Destinations"
idField="service_name"
customPaperHeight={"400px"}
/>
</Box>
<Grid item xs={12} sx={{ marginTop: 15 }}>
<HelpBox
title={"Event Destinations"}
iconComponent={<LambdaIcon />}
help={
<Fragment>
MinIO bucket notifications allow administrators to send
notifications to supported external services on certain
object or bucket events. MinIO supports bucket and
object-level S3 events similar to the Amazon S3 Event
Notifications.
<br />
<br />
You can learn more at our{" "}
<a
href="https://min.io/docs/minio/linux/administration/monitoring/bucket-notifications.html?ref=con"
target="_blank"
rel="noopener"
>
documentation
</a>
.
</Fragment>
}
/>
</Grid>
</Fragment>
)}
{records.length === 0 && (
<Grid
container
sx={{
justifyContent: "center",
alignContent: "center",
alignItems: "center",
}}
>
<Grid item xs={8}>
<HelpBox
title={"Event Destinations"}
iconComponent={<LambdaIcon />}
help={
<Fragment>
MinIO bucket notifications allow administrators to send
notifications to supported external services on certain
object or bucket events. MinIO supports bucket and
object-level S3 events similar to the Amazon S3 Event
Notifications.
<br />
<br />
To get started,{" "}
<ActionLink
onClick={() => {
navigate(IAM_PAGES.EVENT_DESTINATIONS_ADD);
}}
>
Add an Event Destination
</ActionLink>
.
</Fragment>
}
/>
</Grid>
</Grid>
)}
</Fragment>
)}
{isDelConfirmOpen ? (
<ConfirmDeleteDestinationModal
onConfirm={() => {
resetNotificationConfig(selNotifyEndPoint);
}}
status={`${selNotifyEndPoint?.status}`}
serviceName={`${selNotifyEndPoint?.service_name}`}
onClose={() => {
setIsDelConfirmOpen(false);
}}
/>
) : null}
</PageLayout>
</Fragment>
);
};
export default withStyles(styles)(ListEventDestinations);
export default ListEventDestinations;

View File

@@ -15,25 +15,23 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import React, { Fragment } from "react";
import makeStyles from "@mui/styles/makeStyles";
import styled from "styled-components";
import get from "lodash/get";
const useStyles = makeStyles((theme) => ({
linkText: {
color: "#2781B0",
fontWeight: 600,
},
const LinkElement = styled.a(({ theme }) => ({
color: get(theme, "signalColors.info", "#2781B0"),
fontWeight: 600,
}));
const makeLink = (text: string, link: string, className: string) => {
const makeLink = (text: string, link: string) => {
return (
<a href={link} target={"_blank"} className={className}>
<LinkElement href={link} target={"_blank"}>
{text}
</a>
</LinkElement>
);
};
const LicenseFAQ = () => {
const classes = useStyles();
return (
<Fragment>
<h2>What is the GNU AGPL v3?</h2>
@@ -43,20 +41,14 @@ const LicenseFAQ = () => {
{makeLink(
"FOSS",
"https://en.wikipedia.org/wiki/Free_and_open-source_software",
classes.linkText,
)}{" "}
license certified by the{" "}
{makeLink(
"Free Software Foundation",
"https://www.fsf.org/",
classes.linkText,
)}{" "}
and the Open Source Initiative. You can get a copy of the GNU AGPL v3
license with MinIO source code or at{" "}
{makeLink("Free Software Foundation", "https://www.fsf.org/")} and the
Open Source Initiative. You can get a copy of the GNU AGPL v3 license
with MinIO source code or at{" "}
{makeLink(
"https://www.gnu.org/licenses/agpl-3.0.en.html",
"https://min.io/compliance?ref=con",
classes.linkText,
)}
.
</p>
@@ -74,7 +66,6 @@ const LicenseFAQ = () => {
{makeLink(
"Free Software Foundations interpretation",
"https://www.gnu.org/licenses/agpl-3.0.en.html",
classes.linkText,
)}{" "}
of the GNU AGPL v3 license.
</p>
@@ -105,7 +96,6 @@ const LicenseFAQ = () => {
{makeLink(
"GPL FAQ",
"https://www.gnu.org/licenses/gpl-faq.en.html#MereAggregation",
classes.linkText,
)}
.
</p>

View File

@@ -17,13 +17,18 @@
import React, { Fragment, useState } from "react";
import { useSelector } from "react-redux";
import CopyToClipboard from "react-copy-to-clipboard";
import createStyles from "@mui/styles/createStyles";
import makeStyles from "@mui/styles/makeStyles";
import { Theme } from "@mui/material/styles";
import styled from "styled-components";
import { Link, useNavigate } from "react-router-dom";
import { objectBrowserCommon } from "../Common/FormComponents/common/styleLibrary";
import { encodeURLString, safeDecodeURIComponent } from "../../../common/utils";
import { Button, CopyIcon, NewPathIcon, Tooltip, Breadcrumbs } from "mds";
import {
Button,
CopyIcon,
NewPathIcon,
Tooltip,
Breadcrumbs,
breakPoints,
Box,
} from "mds";
import { hasPermission } from "../../../common/SecureComponent";
import {
IAM_SCOPES,
@@ -41,14 +46,20 @@ const CreatePathModal = withSuspense(
),
);
const useStyles = makeStyles((theme: Theme) =>
createStyles({
...objectBrowserCommon,
slashSpacingStyle: {
margin: "0 5px",
const BreadcrumbsMain = styled.div(() => ({
display: "flex",
"& .additionalOptions": {
paddingRight: "10px",
display: "flex",
alignItems: "center",
[`@media (max-width: ${breakPoints.lg}px)`]: {
display: "none",
},
}),
);
},
"& .slashSpacingStyle": {
margin: "0 5px",
},
}));
interface IObjectBrowser {
bucketName: string;
@@ -65,7 +76,6 @@ const BrowserBreadcrumbs = ({
}: IObjectBrowser) => {
const dispatch = useAppDispatch();
const navigate = useNavigate();
const classes = useStyles();
const rewindEnabled = useSelector(
(state: AppState) => state.objectBrowser.rewind.rewindEnabled,
@@ -125,7 +135,7 @@ const BrowserBreadcrumbs = ({
return (
<Fragment key={`breadcrumbs-${index.toString()}`}>
<span className={classes.slashSpacingStyle}>/</span>
<span className={"slashSpacingStyle"}>/</span>
{index === lastBreadcrumbsIndex ? (
<span style={{ cursor: "default", whiteSpace: "pre" }}>
{safeDecodeURIComponent(objectItem) /*Only for display*/}
@@ -159,7 +169,7 @@ const BrowserBreadcrumbs = ({
versionsItem = [
<Fragment key={`breadcrumbs-versionedItem`}>
<span>
<span className={classes.slashSpacingStyle}>/</span>
<span className={"slashSpacingStyle"}>/</span>
{versionedFile} - Versions
</span>
</Fragment>,
@@ -209,7 +219,7 @@ const BrowserBreadcrumbs = ({
return (
<Fragment>
<div className={classes.breadcrumbsMain}>
<BreadcrumbsMain>
{createFolderOpen && (
<CreatePathModal
modalOpen={createFolderOpen}
@@ -251,9 +261,7 @@ const BrowserBreadcrumbs = ({
}}
/>
</CopyToClipboard>
<div className={classes.additionalOptions}>
{additionalOptions}
</div>
<Box className={"additionalOptions"}>{additionalOptions}</Box>
</Fragment>
}
>
@@ -285,8 +293,26 @@ const BrowserBreadcrumbs = ({
/>
</Tooltip>
)}
</div>
<div className={classes.breadcrumbsSecond}>{additionalOptions}</div>
</BreadcrumbsMain>
<Box
sx={{
display: "none",
marginTop: 15,
marginBottom: 5,
justifyContent: "flex-start",
"& > div": {
fontSize: 12,
fontWeight: "normal",
flexDirection: "row",
flexWrap: "nowrap",
},
[`@media (max-width: ${breakPoints.lg}px)`]: {
display: "flex",
},
}}
>
{additionalOptions}
</Box>
</Fragment>
);
};

View File

@@ -17,7 +17,6 @@
import React, { Fragment, useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";
import { Theme } from "@mui/material/styles";
import {
ActionLink,
BucketsIcon,
@@ -27,16 +26,9 @@ import {
PageLayout,
ProgressBar,
RefreshIcon,
Grid,
} from "mds";
import createStyles from "@mui/styles/createStyles";
import Grid from "@mui/material/Grid";
import {
actionsTray,
containerForHeader,
searchField,
} from "../Common/FormComponents/common/styleLibrary";
import { actionsTray } from "../Common/FormComponents/common/styleLibrary";
import { SecureComponent } from "../../../common/SecureComponent";
import {
CONSOLE_UI_RESOURCE,
@@ -52,7 +44,6 @@ import { useSelector } from "react-redux";
import { selFeatures } from "../consoleSlice";
import AutoColorIcon from "../Common/Components/AutoColorIcon";
import TooltipWrapper from "../Common/TooltipWrapper/TooltipWrapper";
import makeStyles from "@mui/styles/makeStyles";
import { niceBytesInt } from "../../../common/utils";
import PageHeaderWrapper from "../Common/PageHeaderWrapper/PageHeaderWrapper";
import { Bucket } from "../../../api/consoleApi";
@@ -60,31 +51,9 @@ import { api } from "../../../api";
import { errorToHandler } from "../../../api/errors";
import HelpMenu from "../HelpMenu";
const useStyles = makeStyles((theme: Theme) =>
createStyles({
bucketList: {
marginTop: 25,
height: "calc(100vh - 211px)",
"&.isEmbedded": {
height: "calc(100vh - 128px)",
},
},
searchField: {
...searchField.searchField,
minWidth: 380,
"@media (max-width: 900px)": {
minWidth: 220,
},
},
...actionsTray,
...containerForHeader,
}),
);
const OBListBuckets = () => {
const dispatch = useAppDispatch();
const navigate = useNavigate();
const classes = useStyles();
const [records, setRecords] = useState<Bucket[]>([]);
const [loading, setLoading] = useState<boolean>(true);
@@ -149,7 +118,7 @@ const OBListBuckets = () => {
)}
<PageLayout>
<Grid item xs={12} className={classes.actionsTray} display="flex">
<Grid item xs={12} sx={{ ...actionsTray.actionsTray, display: "flex" }}>
{obOnly && (
<Grid item xs>
<AutoColorIcon marginRight={15} marginTop={10} />
@@ -159,21 +128,24 @@ const OBListBuckets = () => {
<SearchBox
onChange={setFilterBuckets}
placeholder="Filter Buckets"
overrideClass={classes.searchField}
value={filterBuckets}
sx={{
minWidth: 380,
"@media (max-width: 900px)": {
minWidth: 220,
},
}}
/>
)}
<Grid
item
xs={12}
display={"flex"}
alignItems={"center"}
justifyContent={"flex-end"}
sx={{
"& button": {
marginLeft: "8px",
},
display: "flex",
alignItems: "center",
justifyContent: "flex-end",
gap: 8,
}}
>
<TooltipWrapper tooltip={"Refresh"}>
@@ -194,7 +166,14 @@ const OBListBuckets = () => {
<Grid
item
xs={12}
className={`${classes.bucketList} ${obOnly ? "isEmbedded" : ""}`}
sx={{
marginTop: 25,
height: "calc(100vh - 211px)",
"&.isEmbedded": {
height: "calc(100vh - 128px)",
},
}}
className={obOnly ? "isEmbedded" : ""}
>
{filteredRecords.length !== 0 && (
<DataTable
@@ -258,9 +237,11 @@ const OBListBuckets = () => {
{filteredRecords.length === 0 && filterBuckets !== "" && (
<Grid
container
justifyContent={"center"}
alignContent={"center"}
alignItems={"center"}
sx={{
justifyContent: "center",
alignContent: "center",
alignItems: "center",
}}
>
<Grid item xs={8}>
<HelpBox
@@ -278,9 +259,11 @@ const OBListBuckets = () => {
{!hasBuckets && (
<Grid
container
justifyContent={"center"}
alignContent={"center"}
alignItems={"center"}
sx={{
justifyContent: "center",
alignContent: "center",
alignItems: "center",
}}
>
<Grid item xs={8}>
<HelpBox

View File

@@ -49,12 +49,12 @@ test
.typeText("#newTagLabel", "test")
.click(Selector("#saveTag:enabled"))
.click(Selector("button").withText("Tags"), { offsetX: -1, offsetY: -1 })
.expect(Selector(".MuiChip-label").withText("tag1 : test").exists)
.expect(Selector("span").withText("tag1 : test").exists)
.ok()
.click(Selector(".MuiChip-deleteIcon"))
.click(Selector(".deleteTagButton"))
.click(Selector("#deleteTag"))
.click(Selector("button").withText("Tags"))
.expect(Selector(".MuiChip-label").withText("tag1 : test").exists)
.expect(Selector("span").withText("tag1 : test").exists)
.notOk();
})
.after(async (t) => {