From 7a450ae5f0f41f81b517a95ba19695579ba6e4e1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?L=C3=A9o=20Banno-Cloutier?=
 <leo.banno-cloutier@savoirfairelinux.com>
Date: Wed, 14 Jun 2023 15:14:39 -0400
Subject: [PATCH] jams-react-client: add blueprint snackbar

Change-Id: Idda18d7eafd41dbc80492acad81fe36a3bb7f978
---
 .../components/Snackbar/BlueprintSnackbar.js  | 44 +++++++++
 .../src/views/Blueprint/Blueprint.js          | 32 +++----
 .../Blueprint/EditBlueprintConfiguration.js   | 53 +++--------
 .../Blueprint/EditBlueprintPermissions.js     | 89 ++++++-------------
 .../src/views/Blueprint/EditBlueprintUi.js    | 52 +++--------
 .../src/views/Blueprints/Blueprints.js        |  2 +-
 6 files changed, 115 insertions(+), 157 deletions(-)
 create mode 100644 jams-react-client/src/components/Snackbar/BlueprintSnackbar.js

diff --git a/jams-react-client/src/components/Snackbar/BlueprintSnackbar.js b/jams-react-client/src/components/Snackbar/BlueprintSnackbar.js
new file mode 100644
index 00000000..d52ac284
--- /dev/null
+++ b/jams-react-client/src/components/Snackbar/BlueprintSnackbar.js
@@ -0,0 +1,44 @@
+import React from "react";
+import PropTypes from "prop-types";
+
+import MuiAlert from "@material-ui/lab/Alert";
+import Snackbar from "@material-ui/core/Snackbar";
+import Slide from "@material-ui/core/Slide";
+
+// https://stackoverflow.com/a/67961603
+const Alert = React.forwardRef(function Alert(props, ref) {
+  return <MuiAlert elevation={6} ref={ref} variant="filled" {...props} />;
+});
+
+const SlideTransition = React.forwardRef(function SlideTransition(props, ref) {
+  return <Slide ref={ref} {...props} direction="left" />;
+});
+
+export default function BlueprintSnackbar({ snackbar, setSnackbar }) {
+  const snackbarRef = React.createRef(null);
+
+  const handleClose = () => {
+    setSnackbar((state) => ({ ...state, open: false }));
+  };
+
+  return (
+    <Snackbar
+      ref={snackbarRef}
+      TransitionComponent={SlideTransition}
+      anchorOrigin={{ vertical: "bottom", horizontal: "right" }}
+      open={snackbar.open}
+      onClose={handleClose}
+      message={snackbar.message}
+      key={"bottomright"}
+    >
+      <Alert onClose={handleClose} severity={snackbar.severity}>
+        {snackbar.message}
+      </Alert>
+    </Snackbar>
+  );
+}
+
+BlueprintSnackbar.propTypes = {
+  snackbar: PropTypes.object,
+  setSnackbar: PropTypes.func,
+};
diff --git a/jams-react-client/src/views/Blueprint/Blueprint.js b/jams-react-client/src/views/Blueprint/Blueprint.js
index 94cbc250..72283bca 100644
--- a/jams-react-client/src/views/Blueprint/Blueprint.js
+++ b/jams-react-client/src/views/Blueprint/Blueprint.js
@@ -41,24 +41,25 @@ TabPanel.propTypes = {
   value: PropTypes.any.isRequired,
 };
 
-function a11yProps(index) {
+const a11yProps = (index) => {
   return {
     id: `simple-tab-${index}`,
     "aria-controls": `simple-tabpanel-${index}`,
   };
-}
+};
 
-export default function Blueprint(props) {
-  const [value, setValue] = useState(0);
+export default function Blueprint({ blueprintName }) {
+  const [openedTab, setOpenedTab] = useState(0);
 
   const handleChange = (event, newValue) => {
-    setValue(newValue);
+    setOpenedTab(newValue);
   };
+
   return (
     <div>
       <AppBar position="static" style={{ background: infoColor[0] }}>
         <Tabs
-          value={value}
+          value={openedTab}
           onChange={handleChange}
           aria-label="simple tabs example"
         >
@@ -76,15 +77,16 @@ export default function Blueprint(props) {
           />
         </Tabs>
       </AppBar>
-      <TabPanel value={value} index={0}>
-        <EditBlueprintPermissions blueprintName={props.blueprintName} />
-      </TabPanel>
-      <TabPanel value={value} index={1}>
-        <EditBlueprintConfiguration blueprintName={props.blueprintName} />
-      </TabPanel>
-      <TabPanel value={value} index={2}>
-        <EditBlueprintUi blueprintName={props.blueprintName} />
-      </TabPanel>
+
+        <TabPanel value={openedTab} index={0}>
+          <EditBlueprintPermissions blueprintName={blueprintName} />
+        </TabPanel>
+        <TabPanel value={openedTab} index={1}>
+          <EditBlueprintConfiguration blueprintName={blueprintName} />
+        </TabPanel>
+        <TabPanel value={openedTab} index={2}>
+          <EditBlueprintUi blueprintName={blueprintName} />
+        </TabPanel>
     </div>
   );
 }
diff --git a/jams-react-client/src/views/Blueprint/EditBlueprintConfiguration.js b/jams-react-client/src/views/Blueprint/EditBlueprintConfiguration.js
index c0300566..4192bcfd 100644
--- a/jams-react-client/src/views/Blueprint/EditBlueprintConfiguration.js
+++ b/jams-react-client/src/views/Blueprint/EditBlueprintConfiguration.js
@@ -4,6 +4,7 @@ import clsx from "clsx";
 // @material-ui/core components
 import { makeStyles } from "@material-ui/core/styles";
 import InputLabel from "@material-ui/core/InputLabel";
+
 // core components
 import Grid from "@material-ui/core/Grid";
 import GridItem from "components/Grid/GridItem.js";
@@ -21,7 +22,9 @@ import InputAdornment from "@material-ui/core/InputAdornment";
 
 import Radio from "@material-ui/core/Radio";
 import RadioGroup from "@material-ui/core/RadioGroup";
+import Switch from "@material-ui/core/Switch";
 
+import BuildOutlinedIcon from "@material-ui/icons/BuildOutlined";
 import IconButton from "@material-ui/core/IconButton";
 import VisibilityIcon from "@material-ui/icons/Visibility";
 import VisibilityOffIcon from "@material-ui/icons/VisibilityOff";
@@ -30,24 +33,14 @@ import AccountCircleIcon from "@material-ui/icons/AccountCircle";
 import VpnKeyOutlinedIcon from "@material-ui/icons/VpnKeyOutlined";
 import LanguageOutlinedIcon from "@material-ui/icons/LanguageOutlined";
 
-import { hexToRgb, blackColor } from "assets/jss/material-dashboard-react.js";
-
-import BuildOutlinedIcon from "@material-ui/icons/BuildOutlined";
-
-import axios from "axios";
-import configApiCall from "../../api";
-import { api_path_blueprints } from "../../globalUrls";
-
-import Snackbar from "@material-ui/core/Snackbar";
-
-import MuiAlert from "@material-ui/lab/Alert";
+import i18next from "i18next";
 
 import dashboardStyle from "assets/jss/material-dashboard-react/views/dashboardStyle.js";
+import { hexToRgb, blackColor } from "assets/jss/material-dashboard-react.js";
 
-import Switch from "@material-ui/core/Switch";
-import CustomPopupState from "../../components/CustomPopupState/CustomPopupState";
+import BlueprintSnackbar from "components/Snackbar/BlueprintSnackbar";
+import CustomPopupState from "components/CustomPopupState/CustomPopupState";
 
-import i18next from "i18next";
 
 const styles = (theme) => ({
   ...dashboardStyle,
@@ -147,10 +140,6 @@ const styles = (theme) => ({
 
 const useStyles = makeStyles(styles);
 
-const Alert = (props) => {
-  return <MuiAlert elevation={6} variant="filled" {...props} />;
-};
-
 // Inspired by blueprintjs
 const StyledRadio = (props) => {
   const classes = useStyles();
@@ -345,10 +334,6 @@ export default function EditBlueprintConfiguration(props) {
       });
   };
 
-  const handleClose = () => {
-    setOpen(false);
-  };
-
   const handleTurnChangedOption = (event) => {
     setSelectedTurnOption(event.target.value);
     if (event.target.value === "customTurn") {
@@ -393,17 +378,7 @@ export default function EditBlueprintConfiguration(props) {
 
   return (
     <div>
-      <Snackbar
-        anchorOrigin={{ vertical: "bottom", horizontal: "right" }}
-        open={open}
-        onClose={handleClose}
-        message={message}
-        key={"bottomright"}
-      >
-        <Alert onClose={handleClose} severity={severity}>
-          {message}
-        </Alert>
-      </Snackbar>
+      <BlueprintSnackbar snackbar={snackbar} setSnackbar={setSnackbar} />
       <GridContainer>
         <GridItem xs={12} sm={12} md={6}>
           <Card profile>
@@ -462,7 +437,7 @@ export default function EditBlueprintConfiguration(props) {
                       </FormLabel>
                       <RadioGroup
                         value={selectedTurnOption}
-                        aria-label="gender"
+                        aria-label="turn option"
                         name="customized-radios"
                         onChange={handleTurnChangedOption}
                       >
@@ -491,7 +466,7 @@ export default function EditBlueprintConfiguration(props) {
                                 : "none",
                           }}
                         >
-                          <FormControl className={classes.margin} size="large">
+                          <FormControl className={classes.margin}>
                             <InputLabel htmlFor="turnServer">
                               {i18next.t(
                                 "turn_server_address",
@@ -526,7 +501,7 @@ export default function EditBlueprintConfiguration(props) {
                                 : "none",
                           }}
                         >
-                          <FormControl className={classes.margin} size="large">
+                          <FormControl className={classes.margin}>
                             <InputLabel htmlFor="turnServerUserName">
                               {i18next.t(
                                 "turn_server_username",
@@ -561,7 +536,7 @@ export default function EditBlueprintConfiguration(props) {
                                 : "none",
                           }}
                         >
-                          <FormControl className={classes.margin} size="large">
+                          <FormControl className={classes.margin}>
                             <InputLabel htmlFor="turnServerPassword">
                               {i18next.t(
                                 "turn_server_password",
@@ -627,7 +602,7 @@ export default function EditBlueprintConfiguration(props) {
                       </FormLabel>
                       <RadioGroup
                         value={selectedDHTProxyOption}
-                        aria-label="gender"
+                        aria-label="dht proxy option"
                         name="customized-radios"
                         onChange={handleDHTProxyChangedOption}
                       >
@@ -650,7 +625,6 @@ export default function EditBlueprintConfiguration(props) {
                         <FormGroup row>
                           <FormControl
                             className={classes.margin}
-                            size="large"
                             style={{
                               display:
                                 selectedDHTProxyOption === "customDHTProxy"
@@ -686,7 +660,6 @@ export default function EditBlueprintConfiguration(props) {
                         <FormGroup row>
                           <FormControl
                             className={classes.margin}
-                            size="large"
                             style={{
                               display:
                                 selectedDHTProxyOption === "customDHTProxy"
diff --git a/jams-react-client/src/views/Blueprint/EditBlueprintPermissions.js b/jams-react-client/src/views/Blueprint/EditBlueprintPermissions.js
index 2adc2a3e..4d2b9c12 100644
--- a/jams-react-client/src/views/Blueprint/EditBlueprintPermissions.js
+++ b/jams-react-client/src/views/Blueprint/EditBlueprintPermissions.js
@@ -1,65 +1,52 @@
 import React, { useEffect, useState } from "react";
 import { Link, useHistory } from "react-router-dom";
+import axios from "axios";
+import i18next from "i18next";
+
 // @material-ui/core components
 import { makeStyles } from "@material-ui/core/styles";
 import Checkbox from "@material-ui/core/Checkbox";
-import classnames from "classnames";
 
-// core components
-import Grid from "@material-ui/core/Grid";
-import GridItem from "components/Grid/GridItem.js";
-import GridContainer from "components/Grid/GridContainer.js";
-import Card from "components/Card/Card.js";
-import CardHeader from "components/Card/CardHeader.js";
-import CardIcon from "components/Card/CardIcon.js";
-import CardBody from "components/Card/CardBody.js";
-import FormGroup from "@material-ui/core/FormGroup";
+import Avatar from "@material-ui/core/Avatar";
 import FormControlLabel from "@material-ui/core/FormControlLabel";
+import FormGroup from "@material-ui/core/FormGroup";
 import FormLabel from "@material-ui/core/FormLabel";
-import Button from "components/CustomButtons/Button.js";
-
-import AddCircleOutlineIcon from "@material-ui/icons/AddCircleOutline";
-
-import Avatar from "@material-ui/core/Avatar";
-
+import Grid from "@material-ui/core/Grid";
+import Switch from "@material-ui/core/Switch";
 import Table from "@material-ui/core/Table";
 import TableHead from "@material-ui/core/TableHead";
 import TableRow from "@material-ui/core/TableRow";
 import TableBody from "@material-ui/core/TableBody";
 import TableCell from "@material-ui/core/TableCell";
 
-import Snackbar from "@material-ui/core/Snackbar";
-
-import { hexToRgb, blackColor } from "assets/jss/material-dashboard-react.js";
-
+import AddCircleOutlineIcon from "@material-ui/icons/AddCircleOutline";
 import PriorityHighOutlinedIcon from "@material-ui/icons/PriorityHighOutlined";
 
+import BlueprintSnackbar from "components/Snackbar/BlueprintSnackbar";
+import Button from "components/CustomButtons/Button.js";
+import Card from "components/Card/Card.js";
+import CardBody from "components/Card/CardBody.js";
+import CardHeader from "components/Card/CardHeader.js";
+import CardIcon from "components/Card/CardIcon.js";
+import CustomPopupState from "components/CustomPopupState/CustomPopupState";
+import GridItem from "components/Grid/GridItem.js";
+import GridContainer from "components/Grid/GridContainer.js";
+import TemporaryDrawer from "components/Drawer/Drawer";
+
+import { hexToRgb, blackColor } from "assets/jss/material-dashboard-react.js";
 import noProfilePicture from "assets/img/faces/no-profile-picture.png";
+import dashboardStyle from "assets/jss/material-dashboard-react/views/dashboardStyle.js";
 
-import axios from "axios";
+import auth from "../../auth";
 import configApiCall from "../../api";
 import {
-  api_path_blueprints,
   api_path_get_user_directory_search,
   api_path_get_ns_name_from_addr,
   api_path_get_user_profile,
 } from "../../globalUrls";
 
-import TemporaryDrawer from "components/Drawer/Drawer";
 
-import dashboardStyle from "assets/jss/material-dashboard-react/views/dashboardStyle.js";
-
-import MuiAlert from "@material-ui/lab/Alert";
-
-import i18next from "i18next";
-
-import auth from "auth.js";
-
-import CustomPopupState from "../../components/CustomPopupState/CustomPopupState";
-
-import Switch from "@material-ui/core/Switch";
-
-const styles = (theme) => ({
+const styles = {
   ...dashboardStyle,
   root: {
     flexGrow: 1,
@@ -112,19 +99,15 @@ const styles = (theme) => ({
     minWidth: "80vh",
     maxWidth: "80vh",
   },
-});
+};
 
 const useStyles = makeStyles(styles);
 
-function Alert(props) {
-  return <MuiAlert elevation={6} variant="filled" {...props} />;
-}
 
 export default function EditBlueprintPermissions(props) {
   const classes = useStyles();
   const history = useHistory();
 
-  const tableCellClasses = classnames(classes.tableCell);
 
   const [openDrawer, setOpenDrawer] = useState(false);
   const [users, setUsers] = useState([]);
@@ -329,10 +312,6 @@ export default function EditBlueprintPermissions(props) {
       });
   };
 
-  const handleClose = () => {
-    setOpen(false);
-  };
-
   const addModeratorToBlueprint = (user) => {
     handleUpdatePermissions(
       "defaultModerators",
@@ -355,17 +334,7 @@ export default function EditBlueprintPermissions(props) {
 
   return (
     <div>
-      <Snackbar
-        anchorOrigin={{ vertical: "bottom", horizontal: "right" }}
-        open={open}
-        onClose={handleClose}
-        message={message}
-        key={"bottomright"}
-      >
-        <Alert onClose={handleClose} severity={severity}>
-          {message}
-        </Alert>
-      </Snackbar>
+      <BlueprintSnackbar snackbar={snackbar} setSnackbar={setSnackbar} />
       <TemporaryDrawer
         openDrawer={openDrawer}
         setOpenDrawer={setOpenDrawer}
@@ -630,7 +599,7 @@ export default function EditBlueprintPermissions(props) {
             <TableBody>
               {blueprintModerators.map((user) => (
                 <TableRow key={user.username} className={classes.tableRow}>
-                  <TableCell className={tableCellClasses}>
+                  <TableCell className={classes.tableCell}>
                     <Link to={`/user/${user.username}`}>
                       <Avatar
                         style={{ marginRight: "10px" }}
@@ -643,13 +612,13 @@ export default function EditBlueprintPermissions(props) {
                       />
                     </Link>
                   </TableCell>
-                  <TableCell className={tableCellClasses}>
+                  <TableCell className={classes.tableCell}>
                     <Link to={`/user/${user.username}`}>{user.username}</Link>
                   </TableCell>
-                  <TableCell className={tableCellClasses}>
+                  <TableCell className={classes.tableCell}>
                     <Link to={`/user/${user.username}`}>{user.firstName}</Link>
                   </TableCell>
-                  <TableCell className={tableCellClasses}>
+                  <TableCell className={classes.tableCell}>
                     <Link to={`/user/${user.username}`}>{user.lastName}</Link>
                   </TableCell>
                   <TableCell align="right" className={classes.tableActions}>
diff --git a/jams-react-client/src/views/Blueprint/EditBlueprintUi.js b/jams-react-client/src/views/Blueprint/EditBlueprintUi.js
index 79064858..2822a1ea 100644
--- a/jams-react-client/src/views/Blueprint/EditBlueprintUi.js
+++ b/jams-react-client/src/views/Blueprint/EditBlueprintUi.js
@@ -1,36 +1,28 @@
 import React, { useEffect, useState } from "react";
-// @material-ui/core components
-import { makeStyles } from "@material-ui/core/styles";
 
-// core components
+import { makeStyles } from "@material-ui/core/styles";
 import Grid from "@material-ui/core/Grid";
-import GridItem from "components/Grid/GridItem.js";
-import GridContainer from "components/Grid/GridContainer.js";
+import SettingsIcon from "@material-ui/icons/Settings";
+
+import BlueprintSnackbar from "components/Snackbar/BlueprintSnackbar";
 import Card from "components/Card/Card.js";
 import CardHeader from "components/Card/CardHeader.js";
 import CardIcon from "components/Card/CardIcon.js";
 import CardBody from "components/Card/CardBody.js";
-
-import SettingsIcon from "@material-ui/icons/Settings";
+import GridItem from "components/Grid/GridItem.js";
+import GridContainer from "components/Grid/GridContainer.js";
 
 import { hexToRgb, blackColor } from "assets/jss/material-dashboard-react.js";
 
-import axios from "axios";
-import configApiCall from "../../api";
-import {
-  api_path_blueprints,
-  api_path_get_image,
-  api_path_post_image,
-} from "../../globalUrls";
+import { api_path_blueprints, api_path_get_image, api_path_post_image } from "../../globalUrls";
 
 import dashboardStyle from "assets/jss/material-dashboard-react/views/dashboardStyle.js";
 
-import Snackbar from "@material-ui/core/Snackbar";
-import MuiAlert from "@material-ui/lab/Alert";
-
 import i18next from "i18next";
 import CustomUiPreview from "components/CustomUiPreview/CustomUiPreview";
 import EditBlueprintUiForm from "./EditBlueprintUiForm";
+import configApiCall from "api";
+import axios from "axios";
 
 const DEFAULT_UI_CUSTOMIZATION = {
   hasTitle: true,
@@ -110,10 +102,6 @@ const styles = {
 
 const useStyles = makeStyles(styles);
 
-function Alert(props) {
-  return <MuiAlert elevation={6} variant="filled" {...props} />;
-}
-
 export default function EditBlueprintUi({ blueprintName }) {
   const classes = useStyles();
 
@@ -126,9 +114,7 @@ export default function EditBlueprintUi({ blueprintName }) {
     setPolicyData({ ...policyData, uiCustomization: ui });
   };
 
-  const [oldUiCustomization, setOldUiCustomization] = useState({
-    ...uiCustomization,
-  });
+  const [oldUiCustomization, setOldUiCustomization] = useState(uiCustomization);
   const [opacity, setOpacity] = useState(0);
 
   const [open, setOpen] = useState(false);
@@ -324,24 +310,9 @@ export default function EditBlueprintUi({ blueprintName }) {
     setBgFile(null);
   };
 
-  const handleClose = () => {
-    setOpen(false);
-  };
-
   return (
     <div>
-      <Snackbar
-        anchorOrigin={{ vertical: "bottom", horizontal: "right" }}
-        open={open}
-        onClose={handleClose}
-        message={message}
-        key={"bottomright"}
-      >
-        <Alert onClose={handleClose} severity={severity}>
-          {message}
-        </Alert>
-      </Snackbar>
-
+      <BlueprintSnackbar snackbar={snackbar} setSnackbar={setSnackbar} />
       <GridContainer>
         <GridItem xs={12} sm={12} md={6}>
           <Card profile className={classes.card}>
@@ -382,7 +353,6 @@ export default function EditBlueprintUi({ blueprintName }) {
                           setUiCustomization={setUiCustomization}
                           handleUpdateUi={handleUpdateUi}
                           handleImgDrop={handleImgDrop}
-                          logoFile={logoFile}
                           setLogoFile={setLogoFile}
                           handleDeleteLogo={handleDeleteLogo}
                           bgFile={bgFile}
diff --git a/jams-react-client/src/views/Blueprints/Blueprints.js b/jams-react-client/src/views/Blueprints/Blueprints.js
index 8e944601..4643d58b 100644
--- a/jams-react-client/src/views/Blueprints/Blueprints.js
+++ b/jams-react-client/src/views/Blueprints/Blueprints.js
@@ -203,7 +203,7 @@ export default function Blueprints() {
         setDisableCreate(true);
         setSelectedBlueprintName(blueprintName);
         setSelectedBlueprint(true);
-        console.log("Successfully created" + blueprintName);
+        console.log("Successfully created " + blueprintName);
       })
       .catch((error) => {
         setOpen(false);
-- 
GitLab