From 1be057655036d32b2904f7226c1570d0b1f8d366 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Banno-Cloutier?= <leo.banno-cloutier@savoirfairelinux.com> Date: Thu, 8 Jun 2023 11:39:17 -0400 Subject: [PATCH] jams-react-client: format all files using prettier Also added `npm run format` in the package.json Change-Id: Ic738fa042e28fc8572a8ba4a71827d82b0f92a64 --- jams-react-client/.babelrc | 15 +- jams-react-client/.eslintrc.js | 10 +- jams-react-client/README.md | 2 +- jams-react-client/bower.json | 4 +- jams-react-client/gulpfile.js | 2 +- jams-react-client/package.json | 1 + .../assets/jss/material-dashboard-react.js | 60 +- .../cardImagesStyles.js | 10 +- .../checkboxAdnRadioStyle.js | 22 +- .../components/buttonStyle.js | 106 +-- .../components/cardBodyStyle.js | 8 +- .../components/cardFooterStyle.js | 18 +- .../components/cardHeaderStyle.js | 58 +- .../components/cardIconStyle.js | 8 +- .../components/cardStyle.js | 24 +- .../components/customTabsStyle.js | 22 +- .../components/devicesStyle.js | 22 +- .../components/footerStyle.js | 18 +- .../components/headerLinksStyle.js | 48 +- .../components/rtlHeaderLinksStyle.js | 48 +- .../components/sidebarStyle.js | 82 +- .../components/snackbarContentStyle.js | 46 +- .../components/tableStyle.js | 34 +- .../components/tasksStyle.js | 22 +- .../components/typographyStyle.js | 26 +- .../material-dashboard-react/dropdownStyle.js | 38 +- .../layouts/adminStyle.js | 16 +- .../layouts/rtlStyle.js | 16 +- .../material-dashboard-react/tooltipStyle.js | 4 +- .../views/dashboardStyle.js | 26 +- .../views/iconsStyle.js | 18 +- .../views/rtlStyle.js | 28 +- .../src/components/CaSetup/CaSetup.js | 742 ++++++++------- jams-react-client/src/components/Card/Card.js | 4 +- .../src/components/Card/CardAvatar.js | 14 +- .../src/components/Card/CardBody.js | 4 +- .../src/components/Card/CardFooter.js | 4 +- .../src/components/Card/CardHeader.js | 6 +- .../src/components/Card/CardIcon.js | 6 +- .../components/CountrySelect/CountrySelect.js | 605 ++++++------ .../src/components/CreateAdmin/CreateAdmin.js | 50 +- .../src/components/CustomButtons/Button.js | 6 +- .../src/components/CustomInput/CustomInput.js | 12 +- .../CustomPopupState/CustomPopupState.js | 75 +- .../src/components/CustomTabs/CustomTabs.js | 14 +- .../CustomizedSteppers/CustomizedSteppers.js | 71 +- .../src/components/Devices/Devices.js | 621 +++++++------ .../src/components/Drawer/Drawer.js | 109 ++- .../src/components/FixedPlugin/FixedPlugin.js | 4 +- .../src/components/Footer/Footer.js | 6 +- .../src/components/Grid/GridContainer.js | 4 +- .../src/components/Grid/GridItem.js | 4 +- .../IdentityManagement/AdStorageForm.js | 7 +- .../IdentityManagement/IdentityManagement.js | 75 +- .../IdentityManagement/LdapStorageForm.js | 244 +++-- .../IdentityManagement/LocalStorageForm.js | 66 +- .../LanguagePicker/LanguagePicker.js | 54 +- .../components/Navbars/AdminNavbarLinks.js | 6 +- .../src/components/Navbars/Navbar.js | 11 +- .../src/components/Navbars/RTLNavbarLinks.js | 10 +- .../PasswordDialog/PasswordDialog.js | 2 +- .../ServerParameters/ServerParameters.js | 106 ++- .../src/components/Sidebar/Sidebar.js | 39 +- .../src/components/Snackbar/Snackbar.js | 12 +- .../components/Snackbar/SnackbarContent.js | 8 +- .../src/components/Table/Table.js | 6 +- .../src/components/Tasks/Tasks.js | 10 +- .../src/components/Typography/Danger.js | 2 +- .../src/components/Typography/Info.js | 2 +- .../src/components/Typography/Muted.js | 2 +- .../src/components/Typography/Primary.js | 2 +- .../src/components/Typography/Quote.js | 2 +- .../src/components/Typography/Success.js | 2 +- .../src/components/Typography/Warning.js | 2 +- jams-react-client/src/configured.route.js | 62 +- jams-react-client/src/globalUrls.js | 2 +- jams-react-client/src/i18n.js | 2 +- jams-react-client/src/index.js | 7 +- jams-react-client/src/layouts/BaseLayout.js | 58 +- jams-react-client/src/layouts/ListLayout.js | 66 +- jams-react-client/src/layouts/SignIn.js | 14 +- jams-react-client/src/layouts/SignUp.js | 2 +- jams-react-client/src/protected.route.js | 50 +- .../src/routes/BlueprintRoute.js | 12 +- .../src/routes/BlueprintsRoute.js | 8 +- .../src/routes/CreateUserRoute.js | 18 +- jams-react-client/src/routes/GroupRoute.js | 12 +- jams-react-client/src/routes/GroupsRoute.js | 8 +- jams-react-client/src/routes/SettingsRoute.js | 8 +- jams-react-client/src/routes/UserRoute.js | 12 +- jams-react-client/src/routes/UsersRoute.js | 8 +- jams-react-client/src/routes/routes.js | 3 +- jams-react-client/src/tools.js | 42 +- jams-react-client/src/variables/charts.js | 76 +- jams-react-client/src/variables/general.js | 8 +- .../src/views/Blueprint/Blueprint.js | 49 +- .../Blueprint/EditBlueprintConfiguration.js | 105 ++- .../Blueprint/EditBlueprintPermissions.js | 537 ++++++----- .../src/views/Blueprints/Blueprints.js | 97 +- .../src/views/Dashboard/Dashboard.js | 14 +- .../src/views/Groups/EditGroup.js | 859 ++++++++++-------- jams-react-client/src/views/Groups/Groups.js | 154 ++-- jams-react-client/src/views/Maps/Maps.js | 30 +- .../src/views/Notifications/Notifications.js | 26 +- .../src/views/RTLPage/RTLPage.js | 22 +- .../src/views/Settings/General.js | 357 ++++---- .../src/views/Settings/Settings.js | 11 +- .../src/views/Settings/Subscription.js | 295 +++--- .../src/views/TableList/TableList.js | 20 +- .../src/views/Typography/Typography.js | 10 +- .../src/views/UpgradeToPro/UpgradeToPro.js | 24 +- .../views/UserProfile/DisplayUserProfile.js | 631 +++++++------ .../UserProfile/EditCreateUserProfile.js | 808 ++++++++-------- .../src/views/UserProfile/UserProfile.js | 2 +- .../src/views/UserProfile/cropImage.js | 58 +- jams-react-client/src/views/Users/Users.js | 126 +-- 116 files changed, 4755 insertions(+), 3851 deletions(-) diff --git a/jams-react-client/.babelrc b/jams-react-client/.babelrc index ad0bfb71..d483719e 100644 --- a/jams-react-client/.babelrc +++ b/jams-react-client/.babelrc @@ -4,9 +4,12 @@ "transform-class-properties", "transform-react-jsx", "transform-object-rest-spread", - ["module-resolver", { - "root": ["./src"] - }], - ["import-rename", {"^(.*)\\.jsx$": "$1"}] - ] - } + [ + "module-resolver", + { + "root": ["./src"] + } + ], + ["import-rename", { "^(.*)\\.jsx$": "$1" }] + ] +} diff --git a/jams-react-client/.eslintrc.js b/jams-react-client/.eslintrc.js index 3b1e8415..e254df4e 100644 --- a/jams-react-client/.eslintrc.js +++ b/jams-react-client/.eslintrc.js @@ -3,19 +3,19 @@ module.exports = { env: { es6: true, node: true, - browser: true + browser: true, }, parserOptions: { ecmaVersion: 6, sourceType: "module", ecmaFeatures: { - jsx: true - } + jsx: true, + }, }, plugins: ["react"], extends: [ "eslint:recommended", "plugin:react/recommended", - "plugin:prettier/recommended" - ] + "plugin:prettier/recommended", + ], }; diff --git a/jams-react-client/README.md b/jams-react-client/README.md index bc9d6dc0..2e55daa9 100644 --- a/jams-react-client/README.md +++ b/jams-react-client/README.md @@ -1,3 +1,3 @@ # Jams Jami Client -Jams client for managing user's devices build with React using https://github.com/creativetimofficial/material-dashboard-react#demo \ No newline at end of file +Jams client for managing user's devices build with React using https://github.com/creativetimofficial/material-dashboard-react#demo diff --git a/jams-react-client/bower.json b/jams-react-client/bower.json index 45376a72..d7dab400 100644 --- a/jams-react-client/bower.json +++ b/jams-react-client/bower.json @@ -1,9 +1,7 @@ { "name": "material-dashboard-react", "homepage": "https://github.com/creativetimofficial/material-dashboard-react", - "authors": [ - "creative-tim" - ], + "authors": ["creative-tim"], "description": "A Badass Material-UI Kit based on Material Design", "main": "public/index.html", "keywords": [ diff --git a/jams-react-client/gulpfile.js b/jams-react-client/gulpfile.js index 8fc0f029..cbffafbf 100644 --- a/jams-react-client/gulpfile.js +++ b/jams-react-client/gulpfile.js @@ -1,7 +1,7 @@ const gulp = require("gulp"); const gap = require("gulp-append-prepend"); -gulp.task("licenses", async function() { +gulp.task("licenses", async function () { // this is to add Creative Tim licenses in the production mode for the minified js gulp .src("build/static/js/*chunk.js", { base: "./" }) diff --git a/jams-react-client/package.json b/jams-react-client/package.json index d3bf2f73..e7d90b82 100644 --- a/jams-react-client/package.json +++ b/jams-react-client/package.json @@ -48,6 +48,7 @@ "test": "react-scripts test --env=jsdom", "eject": "react-scripts eject", "install:clean": "rm -rf node_modules/ && rm -rf package-lock.json && npm install && npm start", + "format": "prettier --write \"src/**/*\"", "lint:check": "eslint . --ext=js,jsx; exit 0", "lint:fix": "eslint . --ext=js,jsx --fix; exit 0", "build-package-css": "cp src/assets/css/material-dashboard-react.css dist/material-dashboard-react.css", diff --git a/jams-react-client/src/assets/jss/material-dashboard-react.js b/jams-react-client/src/assets/jss/material-dashboard-react.js index d644b429..4b55358e 100644 --- a/jams-react-client/src/assets/jss/material-dashboard-react.js +++ b/jams-react-client/src/assets/jss/material-dashboard-react.js @@ -21,7 +21,7 @@ // // // Example: input = #999 => output = 153, 153, 153 // // // Example: input = 999 => output = 153, 153, 153 // ############################# -const hexToRgb = input => { +const hexToRgb = (input) => { input = input + ""; input = input.replace("#", ""); let hexRegex = /[0-9A-Fa-f]/g; @@ -54,20 +54,20 @@ const hexToRgb = input => { const drawerWidth = 260; const transition = { - transition: "all 0.33s cubic-bezier(0.685, 0.0473, 0.346, 1)" + transition: "all 0.33s cubic-bezier(0.685, 0.0473, 0.346, 1)", }; const container = { paddingRight: "15px", paddingLeft: "15px", marginRight: "auto", - marginLeft: "auto" + marginLeft: "auto", }; const defaultFont = { fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif', fontWeight: "300", - lineHeight: "1.5em" + lineHeight: "1.5em", }; const primaryColor = ["#ffffff", "#ab47bc", "#8e24aa", "#af2cc5"]; @@ -88,7 +88,7 @@ const grayColor = [ "#333", "#a9afbb", "#eee", - "#e7e7e7" + "#e7e7e7", ]; const blackColor = "#000"; const whiteColor = "#FFF"; @@ -101,7 +101,7 @@ const boxShadow = { hexToRgb(blackColor) + ", 0.12), 0 8px 10px -5px rgba(" + hexToRgb(blackColor) + - ", 0.2)" + ", 0.2)", }; const primaryBoxShadow = { @@ -110,7 +110,7 @@ const primaryBoxShadow = { hexToRgb(blackColor) + ",.14), 0 7px 10px -5px rgba(" + hexToRgb(primaryColor[0]) + - ",.4)" + ",.4)", }; const infoBoxShadow = { boxShadow: @@ -118,7 +118,7 @@ const infoBoxShadow = { hexToRgb(blackColor) + ",.14), 0 7px 10px -5px rgba(" + hexToRgb(infoColor[0]) + - ",.4)" + ",.4)", }; const successBoxShadow = { boxShadow: @@ -126,7 +126,7 @@ const successBoxShadow = { hexToRgb(blackColor) + ",.14), 0 7px 10px -5px rgba(" + hexToRgb(successColor[0]) + - ",.4)" + ",.4)", }; const warningBoxShadow = { boxShadow: @@ -134,7 +134,7 @@ const warningBoxShadow = { hexToRgb(blackColor) + ",.14), 0 7px 10px -5px rgba(" + hexToRgb(warningColor[0]) + - ",.4)" + ",.4)", }; const dangerBoxShadow = { boxShadow: @@ -142,7 +142,7 @@ const dangerBoxShadow = { hexToRgb(blackColor) + ",.14), 0 7px 10px -5px rgba(" + hexToRgb(dangerColor[0]) + - ",.4)" + ",.4)", }; const roseBoxShadow = { boxShadow: @@ -150,38 +150,38 @@ const roseBoxShadow = { hexToRgb(blackColor) + ",.14), 0 7px 10px -5px rgba(" + hexToRgb(roseColor[0]) + - ",.4)" + ",.4)", }; const warningCardHeader = { background: "linear-gradient(60deg, " + warningColor[1] + ", " + warningColor[2] + ")", - ...warningBoxShadow + ...warningBoxShadow, }; const successCardHeader = { background: "linear-gradient(60deg, " + successColor[1] + ", " + successColor[2] + ")", - ...successBoxShadow + ...successBoxShadow, }; const dangerCardHeader = { background: "linear-gradient(60deg, " + dangerColor[1] + ", " + dangerColor[2] + ")", - ...dangerBoxShadow + ...dangerBoxShadow, }; const infoCardHeader = { background: "linear-gradient(60deg, " + infoColor[1] + ", " + infoColor[2] + ")", - ...infoBoxShadow + ...infoBoxShadow, }; const primaryCardHeader = { background: "linear-gradient(60deg, " + primaryColor[1] + ", " + primaryColor[2] + ")", - ...primaryBoxShadow + ...primaryBoxShadow, }; const roseCardHeader = { background: "linear-gradient(60deg, " + roseColor[1] + ", " + roseColor[2] + ")", - ...roseBoxShadow + ...roseBoxShadow, }; const cardActions = { @@ -189,13 +189,13 @@ const cardActions = { paddingTop: "10px", borderTop: "1px solid " + grayColor[10], height: "auto", - ...defaultFont + ...defaultFont, }; const cardHeader = { margin: "-20px 15px 0", borderRadius: "3px", - padding: "15px" + padding: "15px", }; const card = { @@ -206,7 +206,7 @@ const card = { boxShadow: "0 1px 4px 0 rgba(" + hexToRgb(blackColor) + ", 0.14)", borderRadius: "3px", color: "rgba(" + hexToRgb(blackColor) + ", 0.87)", - background: whiteColor + background: whiteColor, }; const defaultBoxShadow = { @@ -221,7 +221,7 @@ const defaultBoxShadow = { hexToRgb(blackColor) + ", 0.2)", padding: "10px 0", - transition: "all 150ms ease 0s" + transition: "all 150ms ease 0s", }; const title = { @@ -235,8 +235,8 @@ const title = { "& small": { color: grayColor[1], fontWeight: "400", - lineHeight: "1" - } + lineHeight: "1", + }, }; const cardTitle = { @@ -248,18 +248,18 @@ const cardTitle = { ...title, marginTop: ".625rem", marginBottom: "0.75rem", - minHeight: "auto" - } + minHeight: "auto", + }, }; const cardSubtitle = { - marginTop: "-.375rem" + marginTop: "-.375rem", }; const cardLink = { "& + $cardLink": { - marginLeft: "1.25rem" - } + marginLeft: "1.25rem", + }, }; export { @@ -298,5 +298,5 @@ export { title, cardTitle, cardSubtitle, - cardLink + cardLink, }; diff --git a/jams-react-client/src/assets/jss/material-dashboard-react/cardImagesStyles.js b/jams-react-client/src/assets/jss/material-dashboard-react/cardImagesStyles.js index 39b34e21..1461bd56 100644 --- a/jams-react-client/src/assets/jss/material-dashboard-react/cardImagesStyles.js +++ b/jams-react-client/src/assets/jss/material-dashboard-react/cardImagesStyles.js @@ -2,12 +2,12 @@ const cardImagesStyles = { cardImgTop: { width: "100%", borderTopLeftRadius: "calc(.25rem - 1px)", - borderTopRightRadius: "calc(.25rem - 1px)" + borderTopRightRadius: "calc(.25rem - 1px)", }, cardImgBottom: { width: "100%", borderBottomRightRadius: "calc(.25rem - 1px)", - borderBottomLeftRadius: "calc(.25rem - 1px)" + borderBottomLeftRadius: "calc(.25rem - 1px)", }, cardImgOverlay: { position: "absolute", @@ -15,12 +15,12 @@ const cardImagesStyles = { right: "0", bottom: "0", left: "0", - padding: "1.25rem" + padding: "1.25rem", }, cardImg: { width: "100%", - borderRadius: "calc(.25rem - 1px)" - } + borderRadius: "calc(.25rem - 1px)", + }, }; export default cardImagesStyles; diff --git a/jams-react-client/src/assets/jss/material-dashboard-react/checkboxAdnRadioStyle.js b/jams-react-client/src/assets/jss/material-dashboard-react/checkboxAdnRadioStyle.js index 5c5ec510..c78ec472 100644 --- a/jams-react-client/src/assets/jss/material-dashboard-react/checkboxAdnRadioStyle.js +++ b/jams-react-client/src/assets/jss/material-dashboard-react/checkboxAdnRadioStyle.js @@ -1,51 +1,51 @@ import { primaryColor, blackColor, - hexToRgb + hexToRgb, } from "assets/jss/material-dashboard-react.js"; const checkboxAdnRadioStyle = { root: { padding: "13px", "&:hover": { - backgroundColor: "unset" - } + backgroundColor: "unset", + }, }, labelRoot: { - marginLeft: "-14px" + marginLeft: "-14px", }, checked: { - color: primaryColor[0] + "!important" + color: primaryColor[0] + "!important", }, checkedIcon: { width: "20px", height: "20px", border: "1px solid rgba(" + hexToRgb(blackColor) + ", .54)", - borderRadius: "3px" + borderRadius: "3px", }, uncheckedIcon: { width: "0px", height: "0px", padding: "10px", border: "1px solid rgba(" + hexToRgb(blackColor) + ", .54)", - borderRadius: "3px" + borderRadius: "3px", }, radio: { - color: primaryColor[0] + "!important" + color: primaryColor[0] + "!important", }, radioChecked: { width: "20px", height: "20px", border: "1px solid " + primaryColor[0], - borderRadius: "50%" + borderRadius: "50%", }, radioUnchecked: { width: "0px", height: "0px", padding: "10px", border: "1px solid rgba(" + hexToRgb(blackColor) + ", .54)", - borderRadius: "50%" - } + borderRadius: "50%", + }, }; export default checkboxAdnRadioStyle; diff --git a/jams-react-client/src/assets/jss/material-dashboard-react/components/buttonStyle.js b/jams-react-client/src/assets/jss/material-dashboard-react/components/buttonStyle.js index 3905a98b..634bcc35 100644 --- a/jams-react-client/src/assets/jss/material-dashboard-react/components/buttonStyle.js +++ b/jams-react-client/src/assets/jss/material-dashboard-react/components/buttonStyle.js @@ -8,7 +8,7 @@ import { roseColor, whiteColor, blackColor, - hexToRgb + hexToRgb, } from "assets/jss/material-dashboard-react.js"; const buttonStyle = { @@ -53,7 +53,7 @@ const buttonStyle = { hexToRgb(blackColor) + ", 0.12), 0 8px 10px -5px rgba(" + hexToRgb(grayColor[0]) + - ", 0.2)" + ", 0.2)", }, "& .fab,& .fas,& .far,& .fal, &.material-icons": { position: "relative", @@ -63,7 +63,7 @@ const buttonStyle = { marginBottom: "-1em", fontSize: "1.1rem", marginRight: "4px", - verticalAlign: "middle" + verticalAlign: "middle", }, "& svg": { position: "relative", @@ -72,7 +72,7 @@ const buttonStyle = { width: "18px", height: "18px", marginRight: "4px", - verticalAlign: "middle" + verticalAlign: "middle", }, "&$justIcon": { "& .fab,& .fas,& .far,& .fal,& .material-icons": { @@ -84,15 +84,15 @@ const buttonStyle = { top: "0px", height: "100%", lineHeight: "41px", - fontSize: "20px" - } - } + fontSize: "20px", + }, + }, }, white: { "&,&:focus,&:hover": { backgroundColor: whiteColor, - color: grayColor[0] - } + color: grayColor[0], + }, }, rose: { backgroundColor: roseColor[0], @@ -113,8 +113,8 @@ const buttonStyle = { hexToRgb(blackColor) + ", 0.12), 0 8px 10px -5px rgba(" + hexToRgb(roseColor[0]) + - ", 0.2)" - } + ", 0.2)", + }, }, primary: { backgroundColor: primaryColor[0], @@ -135,8 +135,8 @@ const buttonStyle = { hexToRgb(blackColor) + ", 0.12), 0 8px 10px -5px rgba(" + hexToRgb(primaryColor[0]) + - ", 0.2)" - } + ", 0.2)", + }, }, info: { backgroundColor: infoColor[0], @@ -157,8 +157,8 @@ const buttonStyle = { hexToRgb(blackColor) + ", 0.12), 0 8px 10px -5px rgba(" + hexToRgb(infoColor[0]) + - ", 0.2)" - } + ", 0.2)", + }, }, success: { backgroundColor: successColor[0], @@ -179,8 +179,8 @@ const buttonStyle = { hexToRgb(blackColor) + ", 0.12), 0 8px 10px -5px rgba(" + hexToRgb(successColor[0]) + - ", 0.2)" - } + ", 0.2)", + }, }, warning: { backgroundColor: warningColor[0], @@ -201,8 +201,8 @@ const buttonStyle = { hexToRgb(blackColor) + ", 0.12), 0 8px 10px -5px rgba(" + hexToRgb(warningColor[0]) + - ", 0.2)" - } + ", 0.2)", + }, }, danger: { backgroundColor: dangerColor[0], @@ -223,81 +223,81 @@ const buttonStyle = { hexToRgb(blackColor) + ", 0.12), 0 8px 10px -5px rgba(" + hexToRgb(dangerColor[0]) + - ", 0.2)" - } + ", 0.2)", + }, }, simple: { "&,&:focus,&:hover": { color: whiteColor, background: "transparent", - boxShadow: "none" + boxShadow: "none", }, "&$rose": { "&,&:focus,&:hover,&:visited": { - color: roseColor[0] - } + color: roseColor[0], + }, }, "&$primary": { "&,&:focus,&:hover,&:visited": { - color: primaryColor[0] - } + color: primaryColor[0], + }, }, "&$info": { "&,&:focus,&:hover,&:visited": { - color: infoColor[0] - } + color: infoColor[0], + }, }, "&$success": { "&,&:focus,&:hover,&:visited": { - color: successColor[0] - } + color: successColor[0], + }, }, "&$warning": { "&,&:focus,&:hover,&:visited": { - color: warningColor[0] - } + color: warningColor[0], + }, }, "&$danger": { "&,&:focus,&:hover,&:visited": { - color: dangerColor[0] - } - } + color: dangerColor[0], + }, + }, }, transparent: { "&,&:focus,&:hover": { color: "inherit", background: "transparent", - boxShadow: "none" - } + boxShadow: "none", + }, }, disabled: { opacity: "0.65", - pointerEvents: "none" + pointerEvents: "none", }, lg: { padding: "1.125rem 2.25rem", fontSize: "0.875rem", lineHeight: "1.333333", - borderRadius: "0.2rem" + borderRadius: "0.2rem", }, sm: { padding: "0.40625rem 1.25rem", fontSize: "0.6875rem", lineHeight: "1.5", - borderRadius: "0.2rem" + borderRadius: "0.2rem", }, round: { - borderRadius: "30px" + borderRadius: "30px", }, block: { - width: "100% !important" + width: "100% !important", }, link: { "&,&:hover,&:focus": { backgroundColor: "transparent", color: grayColor[0], - boxShadow: "none" - } + boxShadow: "none", + }, }, justIcon: { paddingLeft: "12px", @@ -307,7 +307,7 @@ const buttonStyle = { minWidth: "41px", width: "41px", "& .fab,& .fas,& .far,& .fal,& svg,& .material-icons": { - marginRight: "0px" + marginRight: "0px", }, "&$lg": { height: "57px", @@ -316,12 +316,12 @@ const buttonStyle = { lineHeight: "56px", "& .fab,& .fas,& .far,& .fal,& .material-icons": { fontSize: "32px", - lineHeight: "56px" + lineHeight: "56px", }, "& svg": { width: "32px", - height: "32px" - } + height: "32px", + }, }, "&$sm": { height: "30px", @@ -329,14 +329,14 @@ const buttonStyle = { width: "30px", "& .fab,& .fas,& .far,& .fal,& .material-icons": { fontSize: "17px", - lineHeight: "29px" + lineHeight: "29px", }, "& svg": { width: "17px", - height: "17px" - } - } - } + height: "17px", + }, + }, + }, }; export default buttonStyle; diff --git a/jams-react-client/src/assets/jss/material-dashboard-react/components/cardBodyStyle.js b/jams-react-client/src/assets/jss/material-dashboard-react/components/cardBodyStyle.js index cfc0005a..38f4856c 100644 --- a/jams-react-client/src/assets/jss/material-dashboard-react/components/cardBodyStyle.js +++ b/jams-react-client/src/assets/jss/material-dashboard-react/components/cardBodyStyle.js @@ -3,15 +3,15 @@ const cardBodyStyle = { padding: "0.9375rem 20px", flex: "1 1 auto", WebkitBoxFlex: "1", - position: "relative" + position: "relative", }, cardBodyPlain: { paddingLeft: "5px", - paddingRight: "5px" + paddingRight: "5px", }, cardBodyProfile: { - marginTop: "15px" - } + marginTop: "15px", + }, }; export default cardBodyStyle; diff --git a/jams-react-client/src/assets/jss/material-dashboard-react/components/cardFooterStyle.js b/jams-react-client/src/assets/jss/material-dashboard-react/components/cardFooterStyle.js index 94bbf650..3488ec30 100644 --- a/jams-react-client/src/assets/jss/material-dashboard-react/components/cardFooterStyle.js +++ b/jams-react-client/src/assets/jss/material-dashboard-react/components/cardFooterStyle.js @@ -1,6 +1,6 @@ import { grayColor } from "assets/jss/material-dashboard-react.js"; -const cardFooterStyle = theme => ({ +const cardFooterStyle = (theme) => ({ cardFooter: { padding: "0", paddingTop: "10px", @@ -18,18 +18,18 @@ const cardFooterStyle = theme => ({ display: "flex", flexDirection: "column", "& button": { - width: "100%" + width: "100%", }, }, }, }, cardFooterProfile: { - marginTop: "-15px" + marginTop: "-15px", }, cardFooterPlain: { paddingLeft: "5px", paddingRight: "5px", - backgroundColor: "transparent" + backgroundColor: "transparent", }, cardFooterStats: { borderTop: "1px solid " + grayColor[10], @@ -40,19 +40,19 @@ const cardFooterStyle = theme => ({ marginRight: "3px", marginLeft: "3px", width: "16px", - height: "16px" + height: "16px", }, "& .fab,& .fas,& .far,& .fal,& .material-icons": { fontSize: "16px", position: "relative", top: "4px", marginRight: "3px", - marginLeft: "3px" - } + marginLeft: "3px", + }, }, cardFooterChart: { - borderTop: "1px solid " + grayColor[10] - } + borderTop: "1px solid " + grayColor[10], + }, }); export default cardFooterStyle; diff --git a/jams-react-client/src/assets/jss/material-dashboard-react/components/cardHeaderStyle.js b/jams-react-client/src/assets/jss/material-dashboard-react/components/cardHeaderStyle.js index fe8312cb..7cb8f459 100644 --- a/jams-react-client/src/assets/jss/material-dashboard-react/components/cardHeaderStyle.js +++ b/jams-react-client/src/assets/jss/material-dashboard-react/components/cardHeaderStyle.js @@ -5,7 +5,7 @@ import { infoCardHeader, primaryCardHeader, roseCardHeader, - whiteColor + whiteColor, } from "assets/jss/material-dashboard-react.js"; const cardHeaderStyle = { @@ -19,17 +19,17 @@ const cardHeaderStyle = { margin: "0 15px", padding: "0", position: "relative", - color: whiteColor + color: whiteColor, }, "&:first-child": { - borderRadius: "calc(.25rem - 1px) calc(.25rem - 1px) 0 0" + borderRadius: "calc(.25rem - 1px) calc(.25rem - 1px) 0 0", }, "&$warningCardHeader,&$successCardHeader,&$dangerCardHeader,&$infoCardHeader,&$primaryCardHeader,&$roseCardHeader": { "&:not($cardHeaderIcon)": { borderRadius: "3px", marginTop: "-20px", - padding: "15px" - } + padding: "15px", + }, }, "&$cardHeaderStats svg": { fontSize: "36px", @@ -37,7 +37,7 @@ const cardHeaderStyle = { textAlign: "center", width: "36px", height: "36px", - margin: "10px 10px 4px" + margin: "10px 10px 4px", }, "&$cardHeaderStats i,&$cardHeaderStats .material-icons": { fontSize: "36px", @@ -46,79 +46,79 @@ const cardHeaderStyle = { height: "56px", textAlign: "center", overflow: "unset", - marginBottom: "1px" + marginBottom: "1px", }, "&$cardHeaderStats$cardHeaderIcon": { - textAlign: "right" + textAlign: "right", }, }, cardHeaderPlain: { marginLeft: "0px !important", - marginRight: "0px !important" + marginRight: "0px !important", }, cardHeaderStats: { "& $cardHeaderIcon": { - textAlign: "right" + textAlign: "right", }, "& h1,& h2,& h3,& h4,& h5,& h6": { - margin: "0 !important" - } + margin: "0 !important", + }, }, cardHeaderIcon: { "&$warningCardHeader,&$successCardHeader,&$dangerCardHeader,&$infoCardHeader,&$primaryCardHeader,&$roseCardHeader": { background: "transparent", - boxShadow: "none" + boxShadow: "none", }, "& i,& .material-icons": { width: "33px", height: "33px", textAlign: "center", - lineHeight: "33px" + lineHeight: "33px", }, "& svg": { width: "24px", height: "24px", textAlign: "center", lineHeight: "33px", - margin: "5px 4px 0px" - } + margin: "5px 4px 0px", + }, }, warningCardHeader: { color: whiteColor, "&:not($cardHeaderIcon)": { - ...warningCardHeader - } + ...warningCardHeader, + }, }, successCardHeader: { color: whiteColor, "&:not($cardHeaderIcon)": { - ...successCardHeader - } + ...successCardHeader, + }, }, dangerCardHeader: { color: whiteColor, "&:not($cardHeaderIcon)": { - ...dangerCardHeader - } + ...dangerCardHeader, + }, }, infoCardHeader: { color: whiteColor, "&:not($cardHeaderIcon)": { - ...infoCardHeader - } + ...infoCardHeader, + }, }, primaryCardHeader: { color: whiteColor, "&:not($cardHeaderIcon)": { - ...primaryCardHeader - } + ...primaryCardHeader, + }, }, roseCardHeader: { color: whiteColor, "&:not($cardHeaderIcon)": { - ...roseCardHeader - } - } + ...roseCardHeader, + }, + }, }; export default cardHeaderStyle; diff --git a/jams-react-client/src/assets/jss/material-dashboard-react/components/cardIconStyle.js b/jams-react-client/src/assets/jss/material-dashboard-react/components/cardIconStyle.js index 55715f1e..572ed2cb 100644 --- a/jams-react-client/src/assets/jss/material-dashboard-react/components/cardIconStyle.js +++ b/jams-react-client/src/assets/jss/material-dashboard-react/components/cardIconStyle.js @@ -5,7 +5,7 @@ import { infoCardHeader, primaryCardHeader, roseCardHeader, - grayColor + grayColor, } from "assets/jss/material-dashboard-react.js"; const cardIconStyle = { @@ -16,15 +16,15 @@ const cardIconStyle = { padding: "15px", marginTop: "-20px", marginRight: "15px", - float: "left" - } + float: "left", + }, }, warningCardHeader, successCardHeader, dangerCardHeader, infoCardHeader, primaryCardHeader, - roseCardHeader + roseCardHeader, }; export default cardIconStyle; diff --git a/jams-react-client/src/assets/jss/material-dashboard-react/components/cardStyle.js b/jams-react-client/src/assets/jss/material-dashboard-react/components/cardStyle.js index bbe39ea3..aa90d468 100644 --- a/jams-react-client/src/assets/jss/material-dashboard-react/components/cardStyle.js +++ b/jams-react-client/src/assets/jss/material-dashboard-react/components/cardStyle.js @@ -1,7 +1,7 @@ import { blackColor, whiteColor, - hexToRgb + hexToRgb, } from "assets/jss/material-dashboard-react.js"; import { grayColor } from "assets/jss/material-dashboard-react"; @@ -24,33 +24,33 @@ const cardStyle = { "& ul": { "list-style": "none", padding: 0, - "& li" :{ - display: 'flex', - alignItems: 'center', - } + "& li": { + display: "flex", + alignItems: "center", + }, }, "&:hover": { boxShadow: "0 1px 4px 0 rgba(" + hexToRgb(blackColor) + ", 0.54)", }, "& a": { - color: blackColor - } + color: blackColor, + }, }, cardPlain: { background: "transparent", - boxShadow: "none" + boxShadow: "none", }, cardProfile: { marginTop: "50px", textAlign: "left", - height: "calc(100% - 4em)" + height: "calc(100% - 4em)", }, cardChart: { "& p": { marginTop: "0px", - paddingTop: "0px" - } - } + paddingTop: "0px", + }, + }, }; export default cardStyle; diff --git a/jams-react-client/src/assets/jss/material-dashboard-react/components/customTabsStyle.js b/jams-react-client/src/assets/jss/material-dashboard-react/components/customTabsStyle.js index 472ccb1a..c436bf2d 100644 --- a/jams-react-client/src/assets/jss/material-dashboard-react/components/customTabsStyle.js +++ b/jams-react-client/src/assets/jss/material-dashboard-react/components/customTabsStyle.js @@ -4,21 +4,21 @@ const customTabsStyle = { cardTitle: { float: "left", padding: "10px 10px 10px 0px", - lineHeight: "24px" + lineHeight: "24px", }, cardTitleRTL: { float: "right", - padding: "10px 0px 10px 10px !important" + padding: "10px 0px 10px 10px !important", }, displayNone: { - display: "none !important" + display: "none !important", }, tabsRoot: { minHeight: "unset !important", overflowX: "visible", "& $tabRootButton": { - fontSize: "0.875rem" - } + fontSize: "0.875rem", + }, }, tabRootButton: { minHeight: "unset !important", @@ -34,12 +34,12 @@ const customTabsStyle = { color: whiteColor + " !important", marginLeft: "4px", "&:last-child": { - marginLeft: "0px" - } + marginLeft: "0px", + }, }, tabSelected: { backgroundColor: "rgba(" + hexToRgb(whiteColor) + ", 0.2)", - transition: "0.2s background-color 0.1s" + transition: "0.2s background-color 0.1s", }, tabWrapper: { display: "inline-block", @@ -54,9 +54,9 @@ const customTabsStyle = { marginTop: "1px", "& > svg,& > .material-icons": { verticalAlign: "middle", - margin: "-1px 5px 0 0 !important" - } - } + margin: "-1px 5px 0 0 !important", + }, + }, }; export default customTabsStyle; diff --git a/jams-react-client/src/assets/jss/material-dashboard-react/components/devicesStyle.js b/jams-react-client/src/assets/jss/material-dashboard-react/components/devicesStyle.js index e3505a06..710cc0fb 100644 --- a/jams-react-client/src/assets/jss/material-dashboard-react/components/devicesStyle.js +++ b/jams-react-client/src/assets/jss/material-dashboard-react/components/devicesStyle.js @@ -3,7 +3,7 @@ import { primaryColor, dangerColor, grayColor, - infoColor + infoColor, } from "assets/jss/material-dashboard-react.js"; import tooltipStyle from "assets/jss/material-dashboard-react/tooltipStyle.js"; import checkboxAdnRadioStyle from "assets/jss/material-dashboard-react/checkboxAdnRadioStyle.js"; @@ -12,17 +12,17 @@ const tasksStyle = { ...checkboxAdnRadioStyle, table: { marginBottom: "0", - overflow: "visible" + overflow: "visible", }, tableRow: { position: "relative", - borderBottom: "1px solid " + grayColor[5] + borderBottom: "1px solid " + grayColor[5], }, tableActions: { display: "flex", border: "none", padding: "12px 8px !important", - verticalAlign: "middle" + verticalAlign: "middle", }, tableCell: { ...defaultFont, @@ -30,29 +30,29 @@ const tasksStyle = { border: "none", lineHeight: "1.42857143", fontSize: "14px", - textAlign: "left" + textAlign: "left", }, tableCellRTL: { - textAlign: "right" + textAlign: "right", }, tableActionButton: { width: "27px", height: "27px", - padding: "0" + padding: "0", }, tableActionButtonIcon: { width: "17px", - height: "17px" + height: "17px", }, edit: { backgroundColor: "transparent", color: infoColor[0], - boxShadow: "none" + boxShadow: "none", }, close: { backgroundColor: "transparent", color: dangerColor[0], - boxShadow: "none" - } + boxShadow: "none", + }, }; export default tasksStyle; diff --git a/jams-react-client/src/assets/jss/material-dashboard-react/components/footerStyle.js b/jams-react-client/src/assets/jss/material-dashboard-react/components/footerStyle.js index 9d7aa9aa..a0613e45 100644 --- a/jams-react-client/src/assets/jss/material-dashboard-react/components/footerStyle.js +++ b/jams-react-client/src/assets/jss/material-dashboard-react/components/footerStyle.js @@ -2,7 +2,7 @@ import { defaultFont, container, primaryColor, - grayColor + grayColor, } from "assets/jss/material-dashboard-react.js"; const footerStyle = { @@ -16,39 +16,39 @@ const footerStyle = { display: "block", ...defaultFont, fontWeight: "500", - fontSize: "12px" + fontSize: "12px", }, left: { float: "left!important", - display: "block" + display: "block", }, right: { padding: "15px 0", margin: "0", fontSize: "14px", - float: "right!important" + float: "right!important", }, footer: { bottom: "0", borderTop: "1px solid " + grayColor[11], padding: "15px 0", - ...defaultFont + ...defaultFont, }, container, a: { color: primaryColor, textDecoration: "none", - backgroundColor: "transparent" + backgroundColor: "transparent", }, list: { marginBottom: "0", padding: "0", - marginTop: "0" + marginTop: "0", }, inlineBlock: { display: "inline-block", padding: "0px", - width: "auto" - } + width: "auto", + }, }; export default footerStyle; diff --git a/jams-react-client/src/assets/jss/material-dashboard-react/components/headerLinksStyle.js b/jams-react-client/src/assets/jss/material-dashboard-react/components/headerLinksStyle.js index fcd3da4f..818cb007 100644 --- a/jams-react-client/src/assets/jss/material-dashboard-react/components/headerLinksStyle.js +++ b/jams-react-client/src/assets/jss/material-dashboard-react/components/headerLinksStyle.js @@ -1,16 +1,16 @@ import { defaultFont, dangerColor, - whiteColor + whiteColor, } from "assets/jss/material-dashboard-react.js"; import dropdownStyle from "assets/jss/material-dashboard-react/dropdownStyle.js"; -const headerLinksStyle = theme => ({ +const headerLinksStyle = (theme) => ({ ...dropdownStyle(theme), search: { "& > div": { - marginTop: "0" + marginTop: "0", }, [theme.breakpoints.down("sm")]: { margin: "10px 15px !important", @@ -21,15 +21,15 @@ const headerLinksStyle = theme => ({ width: "60%", marginTop: "40px", "& input": { - color: whiteColor - } - } + color: whiteColor, + }, + }, }, linkText: { zIndex: "4", ...defaultFont, fontSize: "14px", - margin: "0px" + margin: "0px", }, buttonLink: { [theme.breakpoints.down("sm")]: { @@ -40,7 +40,7 @@ const headerLinksStyle = theme => ({ width: "24px", height: "30px", marginRight: "15px", - marginLeft: "-15px" + marginLeft: "-15px", }, "& .fab,& .fas,& .far,& .fal,& .material-icons": { fontSize: "24px", @@ -48,28 +48,28 @@ const headerLinksStyle = theme => ({ width: "24px", height: "30px", marginRight: "15px", - marginLeft: "-15px" + marginLeft: "-15px", }, "& > span": { justifyContent: "flex-start", - width: "100%" - } - } + width: "100%", + }, + }, }, searchButton: { [theme.breakpoints.down("sm")]: { top: "-50px !important", marginRight: "22px", - float: "right" - } + float: "right", + }, }, margin: { zIndex: "4", - margin: "0" + margin: "0", }, searchIcon: { width: "17px", - zIndex: "4" + zIndex: "4", }, notifications: { zIndex: "4", @@ -87,27 +87,27 @@ const headerLinksStyle = theme => ({ textAlign: "center", lineHeight: "16px", verticalAlign: "middle", - display: "block" + display: "block", }, [theme.breakpoints.down("sm")]: { ...defaultFont, fontSize: "14px", - marginRight: "8px" - } + marginRight: "8px", + }, }, manager: { [theme.breakpoints.down("sm")]: { - width: "100%" + width: "100%", }, - display: "inline-block" + display: "inline-block", }, searchWrapper: { [theme.breakpoints.down("sm")]: { width: "-webkit-fill-available", - margin: "10px 15px 0" + margin: "10px 15px 0", }, - display: "inline-block" - } + display: "inline-block", + }, }); export default headerLinksStyle; diff --git a/jams-react-client/src/assets/jss/material-dashboard-react/components/rtlHeaderLinksStyle.js b/jams-react-client/src/assets/jss/material-dashboard-react/components/rtlHeaderLinksStyle.js index fcd3da4f..818cb007 100644 --- a/jams-react-client/src/assets/jss/material-dashboard-react/components/rtlHeaderLinksStyle.js +++ b/jams-react-client/src/assets/jss/material-dashboard-react/components/rtlHeaderLinksStyle.js @@ -1,16 +1,16 @@ import { defaultFont, dangerColor, - whiteColor + whiteColor, } from "assets/jss/material-dashboard-react.js"; import dropdownStyle from "assets/jss/material-dashboard-react/dropdownStyle.js"; -const headerLinksStyle = theme => ({ +const headerLinksStyle = (theme) => ({ ...dropdownStyle(theme), search: { "& > div": { - marginTop: "0" + marginTop: "0", }, [theme.breakpoints.down("sm")]: { margin: "10px 15px !important", @@ -21,15 +21,15 @@ const headerLinksStyle = theme => ({ width: "60%", marginTop: "40px", "& input": { - color: whiteColor - } - } + color: whiteColor, + }, + }, }, linkText: { zIndex: "4", ...defaultFont, fontSize: "14px", - margin: "0px" + margin: "0px", }, buttonLink: { [theme.breakpoints.down("sm")]: { @@ -40,7 +40,7 @@ const headerLinksStyle = theme => ({ width: "24px", height: "30px", marginRight: "15px", - marginLeft: "-15px" + marginLeft: "-15px", }, "& .fab,& .fas,& .far,& .fal,& .material-icons": { fontSize: "24px", @@ -48,28 +48,28 @@ const headerLinksStyle = theme => ({ width: "24px", height: "30px", marginRight: "15px", - marginLeft: "-15px" + marginLeft: "-15px", }, "& > span": { justifyContent: "flex-start", - width: "100%" - } - } + width: "100%", + }, + }, }, searchButton: { [theme.breakpoints.down("sm")]: { top: "-50px !important", marginRight: "22px", - float: "right" - } + float: "right", + }, }, margin: { zIndex: "4", - margin: "0" + margin: "0", }, searchIcon: { width: "17px", - zIndex: "4" + zIndex: "4", }, notifications: { zIndex: "4", @@ -87,27 +87,27 @@ const headerLinksStyle = theme => ({ textAlign: "center", lineHeight: "16px", verticalAlign: "middle", - display: "block" + display: "block", }, [theme.breakpoints.down("sm")]: { ...defaultFont, fontSize: "14px", - marginRight: "8px" - } + marginRight: "8px", + }, }, manager: { [theme.breakpoints.down("sm")]: { - width: "100%" + width: "100%", }, - display: "inline-block" + display: "inline-block", }, searchWrapper: { [theme.breakpoints.down("sm")]: { width: "-webkit-fill-available", - margin: "10px 15px 0" + margin: "10px 15px 0", }, - display: "inline-block" - } + display: "inline-block", + }, }); export default headerLinksStyle; diff --git a/jams-react-client/src/assets/jss/material-dashboard-react/components/sidebarStyle.js b/jams-react-client/src/assets/jss/material-dashboard-react/components/sidebarStyle.js index 70e80544..227b7cfe 100644 --- a/jams-react-client/src/assets/jss/material-dashboard-react/components/sidebarStyle.js +++ b/jams-react-client/src/assets/jss/material-dashboard-react/components/sidebarStyle.js @@ -12,10 +12,10 @@ import { whiteColor, grayColor, blackColor, - hexToRgb + hexToRgb, } from "assets/jss/material-dashboard-react.js"; -const sidebarStyle = theme => ({ +const sidebarStyle = (theme) => ({ drawerPaper: { border: "none", position: "fixed", @@ -28,7 +28,7 @@ const sidebarStyle = theme => ({ [theme.breakpoints.up("md")]: { width: drawerWidth, position: "fixed", - height: "100%" + height: "100%", }, [theme.breakpoints.down("sm")]: { width: drawerWidth, @@ -47,18 +47,18 @@ const sidebarStyle = theme => ({ paddingRight: "0px", paddingLeft: "0", transform: `translate3d(${drawerWidth}px, 0, 0)`, - ...transition - } + ...transition, + }, }, drawerPaperRTL: { [theme.breakpoints.up("md")]: { left: "auto !important", - right: "0 !important" + right: "0 !important", }, [theme.breakpoints.down("sm")]: { left: "0 !important", - right: "auto !important" - } + right: "auto !important", + }, }, logo: { position: "relative", @@ -76,29 +76,29 @@ const sidebarStyle = theme => ({ textDecoration: "none", backgroundColor: "transparent", "&,&:hover": { - color: whiteColor - } + color: whiteColor, + }, }, logoLinkRTL: { - textAlign: "right" + textAlign: "right", }, logoImage: { width: "30px", display: "inline-block", maxHeight: "30px", marginLeft: "10px", - marginRight: "15px" + marginRight: "15px", }, img: { width: "100%", verticalAlign: "middle", - border: "0" + border: "0", }, itemLinkSeparator: { "& > hr": { width: "75%", - opacity: "50%" - } + opacity: "50%", + }, }, background: { position: "absolute", @@ -118,8 +118,8 @@ const sidebarStyle = theme => ({ content: '""', display: "block", background: blackColor, - opacity: ".8" - } + opacity: ".8", + }, }, list: { paddingLeft: "0", @@ -127,7 +127,7 @@ const sidebarStyle = theme => ({ paddingBottom: "0", marginBottom: "0", listStyle: "none", - position: "unset" + position: "unset", }, bottomlist: { marginTop: "20px", @@ -139,15 +139,15 @@ const sidebarStyle = theme => ({ position: "fixed", bottom: "0", left: "0", - width: drawerWidth + width: drawerWidth, }, item: { position: "relative", display: "block", textDecoration: "none", "&:hover,&:focus,&:visited,&": { - color: whiteColor - } + color: whiteColor, + }, }, itemLink: { width: "auto", @@ -158,7 +158,7 @@ const sidebarStyle = theme => ({ display: "block", padding: "10px 15px", backgroundColor: "transparent", - ...defaultFont + ...defaultFont, }, itemIcon: { width: "24px", @@ -169,33 +169,33 @@ const sidebarStyle = theme => ({ marginRight: "15px", textAlign: "center", verticalAlign: "middle", - color: "rgba(" + hexToRgb(whiteColor) + ", 0.8)" + color: "rgba(" + hexToRgb(whiteColor) + ", 0.8)", }, itemIconRTL: { marginRight: "3px", marginLeft: "15px", - float: "right" + float: "right", }, itemText: { ...defaultFont, margin: "0", lineHeight: "30px", fontSize: "14px", - color: whiteColor + color: whiteColor, }, itemTextRTL: { - textAlign: "right" + textAlign: "right", }, whiteFont: { - color: whiteColor + color: whiteColor, }, purple: { backgroundColor: primaryColor[0], ...primaryBoxShadow, "&:hover,&:focus": { backgroundColor: primaryColor[0], - ...primaryBoxShadow - } + ...primaryBoxShadow, + }, }, blue: { backgroundColor: infoColor[0], @@ -216,8 +216,8 @@ const sidebarStyle = theme => ({ hexToRgb(blackColor) + ",.12), 0 7px 8px -5px rgba(" + hexToRgb(infoColor[0]) + - ",.2)" - } + ",.2)", + }, }, green: { backgroundColor: successColor[0], @@ -238,8 +238,8 @@ const sidebarStyle = theme => ({ hexToRgb(blackColor) + ",.12), 0 7px 8px -5px rgba(" + hexToRgb(successColor[0]) + - ",.2)" - } + ",.2)", + }, }, orange: { backgroundColor: warningColor[0], @@ -260,8 +260,8 @@ const sidebarStyle = theme => ({ hexToRgb(blackColor) + ",.12), 0 7px 8px -5px rgba(" + hexToRgb(warningColor[0]) + - ",.2)" - } + ",.2)", + }, }, red: { backgroundColor: dangerColor[0], @@ -282,8 +282,8 @@ const sidebarStyle = theme => ({ hexToRgb(blackColor) + ",.12), 0 7px 8px -5px rgba(" + hexToRgb(dangerColor[0]) + - ",.2)" - } + ",.2)", + }, }, sidebarWrapper: { position: "relative", @@ -291,15 +291,15 @@ const sidebarStyle = theme => ({ overflow: "auto", width: "260px", zIndex: "4", - overflowScrolling: "touch" + overflowScrolling: "touch", }, activePro: { [theme.breakpoints.up("md")]: { position: "absolute", width: "100%", - bottom: "13px" - } - } + bottom: "13px", + }, + }, }); export default sidebarStyle; diff --git a/jams-react-client/src/assets/jss/material-dashboard-react/components/snackbarContentStyle.js b/jams-react-client/src/assets/jss/material-dashboard-react/components/snackbarContentStyle.js index d10fbc1e..82b68b19 100644 --- a/jams-react-client/src/assets/jss/material-dashboard-react/components/snackbarContentStyle.js +++ b/jams-react-client/src/assets/jss/material-dashboard-react/components/snackbarContentStyle.js @@ -15,7 +15,7 @@ import { roseColor, primaryColor, warningColor, - hexToRgb + hexToRgb, } from "assets/jss/material-dashboard-react.js"; const snackbarContentStyle = { @@ -39,57 +39,57 @@ const snackbarContentStyle = { hexToRgb(blackColor) + ", 0.12), 0 7px 8px -5px rgba(" + hexToRgb(whiteColor) + - ", 0.2)" + ", 0.2)", }, top20: { - top: "20px" + top: "20px", }, top40: { - top: "40px" + top: "40px", }, info: { backgroundColor: infoColor[3], color: whiteColor, - ...infoBoxShadow + ...infoBoxShadow, }, success: { backgroundColor: successColor[3], color: whiteColor, - ...successBoxShadow + ...successBoxShadow, }, warning: { backgroundColor: warningColor[3], color: whiteColor, - ...warningBoxShadow + ...warningBoxShadow, }, danger: { backgroundColor: dangerColor[3], color: whiteColor, - ...dangerBoxShadow + ...dangerBoxShadow, }, primary: { backgroundColor: primaryColor[3], color: whiteColor, - ...primaryBoxShadow + ...primaryBoxShadow, }, rose: { backgroundColor: roseColor[3], color: whiteColor, - ...roseBoxShadow + ...roseBoxShadow, }, message: { padding: "0", display: "block", - maxWidth: "89%" + maxWidth: "89%", }, close: { width: "11px", - height: "11px" + height: "11px", }, iconButton: { width: "24px", height: "24px", - padding: "0px" + padding: "0px", }, icon: { display: "block", @@ -98,34 +98,34 @@ const snackbarContentStyle = { top: "50%", marginTop: "-15px", width: "30px", - height: "30px" + height: "30px", }, infoIcon: { - color: infoColor[3] + color: infoColor[3], }, successIcon: { - color: successColor[3] + color: successColor[3], }, warningIcon: { - color: warningColor[3] + color: warningColor[3], }, dangerIcon: { - color: dangerColor[3] + color: dangerColor[3], }, primaryIcon: { - color: primaryColor[3] + color: primaryColor[3], }, roseIcon: { - color: roseColor[3] + color: roseColor[3], }, iconMessage: { paddingLeft: "50px", - display: "block" + display: "block", }, actionRTL: { marginLeft: "-8px", - marginRight: "auto" - } + marginRight: "auto", + }, }; export default snackbarContentStyle; diff --git a/jams-react-client/src/assets/jss/material-dashboard-react/components/tableStyle.js b/jams-react-client/src/assets/jss/material-dashboard-react/components/tableStyle.js index 8054225b..d9108706 100644 --- a/jams-react-client/src/assets/jss/material-dashboard-react/components/tableStyle.js +++ b/jams-react-client/src/assets/jss/material-dashboard-react/components/tableStyle.js @@ -6,30 +6,30 @@ import { infoColor, roseColor, grayColor, - defaultFont + defaultFont, } from "assets/jss/material-dashboard-react.js"; -const tableStyle = theme => ({ +const tableStyle = (theme) => ({ warningTableHeader: { - color: warningColor[0] + color: warningColor[0], }, primaryTableHeader: { - color: primaryColor[0] + color: primaryColor[0], }, dangerTableHeader: { - color: dangerColor[0] + color: dangerColor[0], }, successTableHeader: { - color: successColor[0] + color: successColor[0], }, infoTableHeader: { - color: infoColor[0] + color: infoColor[0], }, roseTableHeader: { - color: roseColor[0] + color: roseColor[0], }, grayTableHeader: { - color: grayColor[0] + color: grayColor[0], }, table: { marginBottom: "0", @@ -37,41 +37,41 @@ const tableStyle = theme => ({ maxWidth: "100%", backgroundColor: "transparent", borderSpacing: "0", - borderCollapse: "collapse" + borderCollapse: "collapse", }, tableHeadCell: { color: "inherit", ...defaultFont, "&, &$tableCell": { - fontSize: "1em" - } + fontSize: "1em", + }, }, tableCell: { ...defaultFont, lineHeight: "1.42857143", padding: "12px 8px", verticalAlign: "middle", - fontSize: "0.8125rem" + fontSize: "0.8125rem", }, tableResponsive: { width: "100%", marginTop: theme.spacing(3), - overflowX: "auto" + overflowX: "auto", }, tableHeadRow: { height: "56px", color: "inherit", display: "table-row", outline: "none", - verticalAlign: "middle" + verticalAlign: "middle", }, tableBodyRow: { height: "48px", color: "inherit", display: "table-row", outline: "none", - verticalAlign: "middle" - } + verticalAlign: "middle", + }, }); export default tableStyle; diff --git a/jams-react-client/src/assets/jss/material-dashboard-react/components/tasksStyle.js b/jams-react-client/src/assets/jss/material-dashboard-react/components/tasksStyle.js index 58a5e9c0..886494db 100644 --- a/jams-react-client/src/assets/jss/material-dashboard-react/components/tasksStyle.js +++ b/jams-react-client/src/assets/jss/material-dashboard-react/components/tasksStyle.js @@ -2,7 +2,7 @@ import { defaultFont, primaryColor, dangerColor, - grayColor + grayColor, } from "assets/jss/material-dashboard-react.js"; import tooltipStyle from "assets/jss/material-dashboard-react/tooltipStyle.js"; import checkboxAdnRadioStyle from "assets/jss/material-dashboard-react/checkboxAdnRadioStyle.js"; @@ -11,17 +11,17 @@ const tasksStyle = { ...checkboxAdnRadioStyle, table: { marginBottom: "0", - overflow: "visible" + overflow: "visible", }, tableRow: { position: "relative", - borderBottom: "1px solid " + grayColor[5] + borderBottom: "1px solid " + grayColor[5], }, tableActions: { display: "flex", border: "none", padding: "12px 8px !important", - verticalAlign: "middle" + verticalAlign: "middle", }, tableCell: { ...defaultFont, @@ -29,29 +29,29 @@ const tasksStyle = { verticalAlign: "middle", border: "none", lineHeight: "1.42857143", - fontSize: "14px" + fontSize: "14px", }, tableCellRTL: { - textAlign: "right" + textAlign: "right", }, tableActionButton: { width: "27px", height: "27px", - padding: "0" + padding: "0", }, tableActionButtonIcon: { width: "17px", - height: "17px" + height: "17px", }, edit: { backgroundColor: "transparent", color: primaryColor[0], - boxShadow: "none" + boxShadow: "none", }, close: { backgroundColor: "transparent", color: dangerColor[0], - boxShadow: "none" - } + boxShadow: "none", + }, }; export default tasksStyle; diff --git a/jams-react-client/src/assets/jss/material-dashboard-react/components/typographyStyle.js b/jams-react-client/src/assets/jss/material-dashboard-react/components/typographyStyle.js index 3894ecaf..8aff98a4 100644 --- a/jams-react-client/src/assets/jss/material-dashboard-react/components/typographyStyle.js +++ b/jams-react-client/src/assets/jss/material-dashboard-react/components/typographyStyle.js @@ -5,52 +5,52 @@ import { successColor, warningColor, dangerColor, - grayColor + grayColor, } from "assets/jss/material-dashboard-react.js"; const typographyStyle = { defaultFontStyle: { ...defaultFont, - fontSize: "14px" + fontSize: "14px", }, defaultHeaderMargins: { marginTop: "20px", - marginBottom: "10px" + marginBottom: "10px", }, quote: { padding: "10px 20px", margin: "0 0 20px", fontSize: "17.5px", - borderLeft: "5px solid " + grayColor[10] + borderLeft: "5px solid " + grayColor[10], }, quoteText: { margin: "0 0 10px", - fontStyle: "italic" + fontStyle: "italic", }, quoteAuthor: { display: "block", fontSize: "80%", lineHeight: "1.42857143", - color: grayColor[1] + color: grayColor[1], }, mutedText: { - color: grayColor[1] + color: grayColor[1], }, primaryText: { - color: primaryColor[0] + color: primaryColor[0], }, infoText: { - color: infoColor[0] + color: infoColor[0], }, successText: { - color: successColor[0] + color: successColor[0], }, warningText: { - color: warningColor[0] + color: warningColor[0], }, dangerText: { - color: dangerColor[0] - } + color: dangerColor[0], + }, }; export default typographyStyle; diff --git a/jams-react-client/src/assets/jss/material-dashboard-react/dropdownStyle.js b/jams-react-client/src/assets/jss/material-dashboard-react/dropdownStyle.js index 7a5b3764..6e614663 100644 --- a/jams-react-client/src/assets/jss/material-dashboard-react/dropdownStyle.js +++ b/jams-react-client/src/assets/jss/material-dashboard-react/dropdownStyle.js @@ -5,16 +5,16 @@ import { defaultFont, blackColor, grayColor, - hexToRgb + hexToRgb, } from "assets/jss/material-dashboard-react.js"; -const dropdownStyle = theme => ({ +const dropdownStyle = (theme) => ({ buttonLink: { [theme.breakpoints.down("md")]: { display: "flex", marginLeft: "30px", - width: "auto" - } + width: "auto", + }, }, links: { width: "20px", @@ -25,16 +25,16 @@ const dropdownStyle = theme => ({ width: "30px", height: "30px", color: grayColor[9], - marginRight: "15px" - } + marginRight: "15px", + }, }, linkText: { zIndex: "4", ...defaultFont, - fontSize: "14px" + fontSize: "14px", }, popperClose: { - pointerEvents: "none" + pointerEvents: "none", }, popperResponsive: { [theme.breakpoints.down("md")]: { @@ -47,8 +47,8 @@ const dropdownStyle = theme => ({ border: "0", WebkitBoxShadow: "none", boxShadow: "none", - color: "black" - } + color: "black", + }, }, popperNav: { [theme.breakpoints.down("sm")]: { @@ -72,11 +72,11 @@ const dropdownStyle = theme => ({ padding: "10px 15px !important", "&:hover": { backgroundColor: "hsla(0,0%,78%,.2)", - boxShadow: "none" - } - } - } - } + boxShadow: "none", + }, + }, + }, + }, }, dropdown: { borderRadius: "3px", @@ -92,7 +92,7 @@ const dropdownStyle = theme => ({ listStyle: "none", backgroundColor: whiteColor, WebkitBackgroundClip: "padding-box", - backgroundClip: "padding-box" + backgroundClip: "padding-box", }, dropdownItem: { ...defaultFont, @@ -116,9 +116,9 @@ const dropdownStyle = theme => ({ "&:hover": { backgroundColor: primaryColor[0], color: whiteColor, - ...primaryBoxShadow - } - } + ...primaryBoxShadow, + }, + }, }); export default dropdownStyle; diff --git a/jams-react-client/src/assets/jss/material-dashboard-react/layouts/adminStyle.js b/jams-react-client/src/assets/jss/material-dashboard-react/layouts/adminStyle.js index 77f037fc..224045e9 100644 --- a/jams-react-client/src/assets/jss/material-dashboard-react/layouts/adminStyle.js +++ b/jams-react-client/src/assets/jss/material-dashboard-react/layouts/adminStyle.js @@ -1,18 +1,18 @@ import { drawerWidth, transition, - container + container, } from "assets/jss/material-dashboard-react.js"; -const appStyle = theme => ({ +const appStyle = (theme) => ({ wrapper: { position: "relative", top: "0", - height: "100vh" + height: "100vh", }, mainPanel: { [theme.breakpoints.up("md")]: { - width: `calc(100% - ${drawerWidth}px)` + width: `calc(100% - ${drawerWidth}px)`, }, overflow: "auto", position: "relative", @@ -20,7 +20,7 @@ const appStyle = theme => ({ ...transition, maxHeight: "100%", width: "100%", - overflowScrolling: "touch" + overflowScrolling: "touch", }, content: { marginTop: "0px", @@ -28,13 +28,13 @@ const appStyle = theme => ({ marginTop: "30px", }, padding: "30px 15px", - minHeight: "calc(100vh - 123px)" + minHeight: "calc(100vh - 123px)", }, container, map: { marginTop: "0px", - minHeight: "calc(100vh - 63px)" - } + minHeight: "calc(100vh - 63px)", + }, }); export default appStyle; diff --git a/jams-react-client/src/assets/jss/material-dashboard-react/layouts/rtlStyle.js b/jams-react-client/src/assets/jss/material-dashboard-react/layouts/rtlStyle.js index 677daa6f..faa9dcc0 100644 --- a/jams-react-client/src/assets/jss/material-dashboard-react/layouts/rtlStyle.js +++ b/jams-react-client/src/assets/jss/material-dashboard-react/layouts/rtlStyle.js @@ -1,19 +1,19 @@ import { drawerWidth, transition, - container + container, } from "assets/jss/material-dashboard-react.js"; -const appStyle = theme => ({ +const appStyle = (theme) => ({ wrapper: { position: "relative", top: "0", height: "100vh", - direction: "rtl" + direction: "rtl", }, mainPanel: { [theme.breakpoints.up("md")]: { - width: `calc(100% - ${drawerWidth}px)` + width: `calc(100% - ${drawerWidth}px)`, }, overflow: "auto", position: "relative", @@ -21,17 +21,17 @@ const appStyle = theme => ({ ...transition, maxHeight: "100%", width: "100%", - overflowScrolling: "touch" + overflowScrolling: "touch", }, content: { marginTop: "70px", padding: "30px 15px", - minHeight: "calc(100vh - 123px)" + minHeight: "calc(100vh - 123px)", }, container, map: { - marginTop: "70px" - } + marginTop: "70px", + }, }); export default appStyle; diff --git a/jams-react-client/src/assets/jss/material-dashboard-react/tooltipStyle.js b/jams-react-client/src/assets/jss/material-dashboard-react/tooltipStyle.js index bcbd7a0b..9d83efb5 100644 --- a/jams-react-client/src/assets/jss/material-dashboard-react/tooltipStyle.js +++ b/jams-react-client/src/assets/jss/material-dashboard-react/tooltipStyle.js @@ -28,7 +28,7 @@ const tooltipStyle = { wordSpacing: "normal", wordWrap: "normal", whiteSpace: "normal", - lineBreak: "auto" - } + lineBreak: "auto", + }, }; export default tooltipStyle; diff --git a/jams-react-client/src/assets/jss/material-dashboard-react/views/dashboardStyle.js b/jams-react-client/src/assets/jss/material-dashboard-react/views/dashboardStyle.js index fe6f4e9d..42eb7a01 100644 --- a/jams-react-client/src/assets/jss/material-dashboard-react/views/dashboardStyle.js +++ b/jams-react-client/src/assets/jss/material-dashboard-react/views/dashboardStyle.js @@ -2,16 +2,16 @@ import { successColor, whiteColor, grayColor, - hexToRgb + hexToRgb, } from "assets/jss/material-dashboard-react.js"; const dashboardStyle = { successText: { - color: successColor[0] + color: successColor[0], }, upArrowCardCategory: { width: "16px", - height: "16px" + height: "16px", }, stats: { color: grayColor[0], @@ -24,15 +24,15 @@ const dashboardStyle = { height: "16px", position: "relative", marginRight: "3px", - marginLeft: "3px" + marginLeft: "3px", }, "& .fab,& .fas,& .far,& .fal,& .material-icons": { top: "4px", fontSize: "16px", position: "relative", marginRight: "3px", - marginLeft: "3px" - } + marginLeft: "3px", + }, }, cardCategory: { color: grayColor[0], @@ -40,14 +40,14 @@ const dashboardStyle = { fontSize: "14px", marginTop: "0", paddingTop: "10px", - marginBottom: "0" + marginBottom: "0", }, cardCategoryWhite: { color: "rgba(" + hexToRgb(whiteColor) + ",.62)", margin: "0", fontSize: "14px", marginTop: "0", - marginBottom: "0" + marginBottom: "0", }, cardTitle: { color: grayColor[2], @@ -60,8 +60,8 @@ const dashboardStyle = { "& small": { color: grayColor[1], fontWeight: "400", - lineHeight: "1" - } + lineHeight: "1", + }, }, cardTitleWhite: { color: whiteColor, @@ -74,9 +74,9 @@ const dashboardStyle = { "& small": { color: grayColor[1], fontWeight: "400", - lineHeight: "1" - } - } + lineHeight: "1", + }, + }, }; export default dashboardStyle; diff --git a/jams-react-client/src/assets/jss/material-dashboard-react/views/iconsStyle.js b/jams-react-client/src/assets/jss/material-dashboard-react/views/iconsStyle.js index 4043b711..51c80a32 100644 --- a/jams-react-client/src/assets/jss/material-dashboard-react/views/iconsStyle.js +++ b/jams-react-client/src/assets/jss/material-dashboard-react/views/iconsStyle.js @@ -2,7 +2,7 @@ import { boxShadow, whiteColor, grayColor, - hexToRgb + hexToRgb, } from "assets/jss/material-dashboard-react.js"; const iconsStyle = { @@ -10,10 +10,10 @@ const iconsStyle = { width: "100%", height: "500px", border: "0", - ...boxShadow + ...boxShadow, }, iframeContainer: { - margin: "0 -20px 0" + margin: "0 -20px 0", }, cardCategoryWhite: { "&,& a,& a:hover,& a:focus": { @@ -21,11 +21,11 @@ const iconsStyle = { margin: "0", fontSize: "14px", marginTop: "0", - marginBottom: "0" + marginBottom: "0", }, "& a,& a:hover,& a:focus": { - color: whiteColor - } + color: whiteColor, + }, }, cardTitleWhite: { color: whiteColor, @@ -38,9 +38,9 @@ const iconsStyle = { "& small": { color: grayColor[1], fontWeight: "400", - lineHeight: "1" - } - } + lineHeight: "1", + }, + }, }; export default iconsStyle; diff --git a/jams-react-client/src/assets/jss/material-dashboard-react/views/rtlStyle.js b/jams-react-client/src/assets/jss/material-dashboard-react/views/rtlStyle.js index 22d228a9..a0f21097 100644 --- a/jams-react-client/src/assets/jss/material-dashboard-react/views/rtlStyle.js +++ b/jams-react-client/src/assets/jss/material-dashboard-react/views/rtlStyle.js @@ -2,16 +2,16 @@ import { successColor, whiteColor, grayColor, - hexToRgb + hexToRgb, } from "assets/jss/material-dashboard-react.js"; const rtlStyle = { successText: { - color: successColor[0] + color: successColor[0], }, upArrowCardCategory: { width: "16px", - height: "16px" + height: "16px", }, stats: { color: grayColor[0], @@ -24,15 +24,15 @@ const rtlStyle = { height: "16px", position: "relative", marginRight: "3px", - marginLeft: "3px" + marginLeft: "3px", }, "& .fab,& .fas,& .far,& .fal,& .material-icons": { top: "4px", fontSize: "16px", position: "relative", marginRight: "3px", - marginLeft: "3px" - } + marginLeft: "3px", + }, }, cardCategory: { color: grayColor[0], @@ -40,7 +40,7 @@ const rtlStyle = { fontSize: "14px", marginTop: "0", paddingTop: "10px", - marginBottom: "0" + marginBottom: "0", }, cardCategoryWhite: { color: "rgba(" + hexToRgb(whiteColor) + ",.62)", @@ -49,8 +49,8 @@ const rtlStyle = { marginTop: "0", marginBottom: "0", "& a": { - color: whiteColor - } + color: whiteColor, + }, }, cardTitle: { color: grayColor[2], @@ -63,8 +63,8 @@ const rtlStyle = { "& small": { color: grayColor[1], fontWeight: "400", - lineHeight: "1" - } + lineHeight: "1", + }, }, cardTitleWhite: { color: whiteColor, @@ -77,9 +77,9 @@ const rtlStyle = { "& small": { color: grayColor[1], fontWeight: "400", - lineHeight: "1" - } - } + lineHeight: "1", + }, + }, }; export default rtlStyle; diff --git a/jams-react-client/src/components/CaSetup/CaSetup.js b/jams-react-client/src/components/CaSetup/CaSetup.js index d0236c0f..37ec7607 100644 --- a/jams-react-client/src/components/CaSetup/CaSetup.js +++ b/jams-react-client/src/components/CaSetup/CaSetup.js @@ -1,361 +1,419 @@ -import React from 'react'; -import {useHistory} from "react-router-dom"; +import React from "react"; +import { useHistory } from "react-router-dom"; import { Formik, Field } from "formik"; -import * as Yup from 'yup'; -import Button from '@material-ui/core/Button'; -import TextField from '@material-ui/core/TextField'; -import { makeStyles } from '@material-ui/core/styles'; +import * as Yup from "yup"; +import Button from "@material-ui/core/Button"; +import TextField from "@material-ui/core/TextField"; +import { makeStyles } from "@material-ui/core/styles"; import CountrySelect from "components/CountrySelect/CountrySelect.js"; -import auth from '../../auth' -import axios from 'axios'; -import configApiCall from '../../api' -import { api_path_post_install_ca } from '../../globalUrls' +import auth from "../../auth"; +import axios from "axios"; +import configApiCall from "../../api"; +import { api_path_post_install_ca } from "../../globalUrls"; import Select from "@material-ui/core/Select"; import * as tool from "../../tools"; import Input from "@material-ui/core/Input"; import Typography from "@material-ui/core/Typography"; -import i18next from 'i18next'; +import i18next from "i18next"; const useStyles = makeStyles((theme) => ({ - paper: { - marginTop: theme.spacing(8), - display: 'flex', - flexDirection: 'column', - alignItems: 'center', - }, - avatar: { - margin: theme.spacing(1), - backgroundColor: theme.palette.secondary.main, - }, - form: { - width: '100%', // Fix IE 11 issue. - marginTop: theme.spacing(1), - }, - submit: { - margin: theme.spacing(3, 0, 2), - }, + paper: { + marginTop: theme.spacing(8), + display: "flex", + flexDirection: "column", + alignItems: "center", + }, + avatar: { + margin: theme.spacing(1), + backgroundColor: theme.palette.secondary.main, + }, + form: { + width: "100%", // Fix IE 11 issue. + marginTop: theme.spacing(1), + }, + submit: { + margin: theme.spacing(3, 0, 2), + }, })); export default function CaSetup(props) { - const history = useHistory(); - - /** - * Formik Validation Fields - */ - - const initialValuesform1 = {commonname: "", state:"", city:"", organization:"", organizationunit:"", country:""}; - - const initialValuesform2 = {certificatefile: "", privkeyfile:""}; - - const validationSchemaform1 = Yup.object().shape({ - commonname: Yup.string() - .required(i18next.t("common_name_is_required", "Common name is required.")), - state: Yup.string() - .required(i18next.t("state_is_required", "State is required.")), - city: Yup.string() - .required(i18next.t("city_is_required", "City is required.")), - organization: Yup.string() - .required(i18next.t("organization_is_required", "Organization is required.")), - organizationunit: Yup.string() - .required(i18next.t("organization_unit_is_required", "Organization unit is required.")), - country: Yup.string() - .required(i18next.t("country_is_required", "Country is required.")), - }); - - const validationSchemaform2 = Yup.object().shape({ - certificatefile: Yup.mixed() - .required(i18next.t("certificate_file_is_required", "Certificate file is required.")), - privkeyfile: Yup.mixed() - .required(i18next.t("private_key_file_is_required", "Private key file is required.")), - }); - - - const getCertificateOptions = [ - {value: 0, label: i18next.t("create_self_signed_certificate_authority", "Create a self-signed Certificate Authority")}, - {value: 1, label: i18next.t("import_existing_certificate_authority", "Import existing Certificate Authority")}, - ]; - - const validityPeriods = [ - {value: 157784630000, label: i18next.t("5_years", "5 years")}, - {value: 315569260000, label: i18next.t("10_years", "10 years")}, - ]; - - const certificateOptionsItems = tool.buildSelectMenuItems(getCertificateOptions); - const validityPeriodsItems = tool.buildSelectMenuItems(validityPeriods); - const classes = useStyles(); - - const [certificateOpt, setCertificateOpt] = React.useState(getCertificateOptions[0]); - const [validityPeriod, setValidityPeriod] = React.useState(validityPeriods[0]); - - - function handleInstallCA(data) { - if(data.status === 500 || data.status === 512 || data.status === 513) { - props.setError(true) - props.setErrorMessage(i18next.t("unknown_error_occured_while_installing_the_ca", "An unknown error occurred while installing the CA. Please try again.")); - } - else if (data.status === 200){ - auth.uri = '/api/install/auth'; - history.push('/'); - } - + const history = useHistory(); + + /** + * Formik Validation Fields + */ + + const initialValuesform1 = { + commonname: "", + state: "", + city: "", + organization: "", + organizationunit: "", + country: "", + }; + + const initialValuesform2 = { certificatefile: "", privkeyfile: "" }; + + const validationSchemaform1 = Yup.object().shape({ + commonname: Yup.string().required( + i18next.t("common_name_is_required", "Common name is required.") + ), + state: Yup.string().required( + i18next.t("state_is_required", "State is required.") + ), + city: Yup.string().required( + i18next.t("city_is_required", "City is required.") + ), + organization: Yup.string().required( + i18next.t("organization_is_required", "Organization is required.") + ), + organizationunit: Yup.string().required( + i18next.t( + "organization_unit_is_required", + "Organization unit is required." + ) + ), + country: Yup.string().required( + i18next.t("country_is_required", "Country is required.") + ), + }); + + const validationSchemaform2 = Yup.object().shape({ + certificatefile: Yup.mixed().required( + i18next.t("certificate_file_is_required", "Certificate file is required.") + ), + privkeyfile: Yup.mixed().required( + i18next.t("private_key_file_is_required", "Private key file is required.") + ), + }); + + const getCertificateOptions = [ + { + value: 0, + label: i18next.t( + "create_self_signed_certificate_authority", + "Create a self-signed Certificate Authority" + ), + }, + { + value: 1, + label: i18next.t( + "import_existing_certificate_authority", + "Import existing Certificate Authority" + ), + }, + ]; + + const validityPeriods = [ + { value: 157784630000, label: i18next.t("5_years", "5 years") }, + { value: 315569260000, label: i18next.t("10_years", "10 years") }, + ]; + + const certificateOptionsItems = tool.buildSelectMenuItems( + getCertificateOptions + ); + const validityPeriodsItems = tool.buildSelectMenuItems(validityPeriods); + const classes = useStyles(); + + const [certificateOpt, setCertificateOpt] = React.useState( + getCertificateOptions[0] + ); + const [validityPeriod, setValidityPeriod] = React.useState( + validityPeriods[0] + ); + + function handleInstallCA(data) { + if (data.status === 500 || data.status === 512 || data.status === 513) { + props.setError(true); + props.setErrorMessage( + i18next.t( + "unknown_error_occured_while_installing_the_ca", + "An unknown error occurred while installing the CA. Please try again." + ) + ); + } else if (data.status === 200) { + auth.uri = "/api/install/auth"; + history.push("/"); } - - const handleCertifOptionChange = (event) => { - props.setError(false); - setCertificateOpt(getCertificateOptions[event.target.value]); - }; - - const handleValidPeriodChange = (event) => { - props.setError(false); - setValidityPeriod(tool.retrieveArrayElement(event.target.value, validityPeriods)); - }; - - const handleSubmit = (values) => { - let jsonData = {}; - if(certificateOpt.value === 0){ - jsonData = { - 'fields': { - 'commonName': values.commonname, - 'organizationalUnit': values.organizationUnit, - 'organization': values.organization, - 'city': values.city, - 'state': values.state, - 'country': values.country, - 'lifetime': validityPeriod.value - } - } - } - else if(certificateOpt.value === 1){ - jsonData = { - 'caCertificate': values.certificatefile, - 'caKey': values.privkeyfile - } - } - - axios(configApiCall(api_path_post_install_ca, "POST", jsonData, null)).then((response)=>{ - handleInstallCA(response); - }).catch((error)=>{ - props.setError(error); - console.log('Error installing CA Setup: ' + error ); - }) + } + + const handleCertifOptionChange = (event) => { + props.setError(false); + setCertificateOpt(getCertificateOptions[event.target.value]); + }; + + const handleValidPeriodChange = (event) => { + props.setError(false); + setValidityPeriod( + tool.retrieveArrayElement(event.target.value, validityPeriods) + ); + }; + + const handleSubmit = (values) => { + let jsonData = {}; + if (certificateOpt.value === 0) { + jsonData = { + fields: { + commonName: values.commonname, + organizationalUnit: values.organizationUnit, + organization: values.organization, + city: values.city, + state: values.state, + country: values.country, + lifetime: validityPeriod.value, + }, + }; + } else if (certificateOpt.value === 1) { + jsonData = { + caCertificate: values.certificatefile, + caKey: values.privkeyfile, + }; } - if(certificateOpt.value === 0){ - return ( - <Formik - validationSchema={validationSchemaform1} - initialValues={initialValuesform1} - onSubmit={values => { - handleSubmit(values); - }} - > - {(props) => { - const { - values, - touched, - errors, - handleSubmit, - handleChange, - handleBlur, - } = props; - return ( - <form className={classes.form} noValidate onSubmit={handleSubmit}> - <h4> - {i18next.t("ca_setup_header", "Select an option for setting-up the certificate authority that will be used to sign all Jami accounts generated on this JAMS instance.")} - </h4> - <Select - labelId="certificate-option-select-label" - fullWidth - value={certificateOpt.value} - onChange={handleCertifOptionChange} - variant="outlined" - children={certificateOptionsItems} - /> - - <TextField - variant="outlined" - margin="normal" - required - fullWidth - id="commonname" - label={i18next.t("common_name", "Common Name")} - name="commonname" - autoComplete="commonname" - autoFocus - value={values.commonname} - onChange={handleChange} - onBlur={handleBlur} - helperText={(errors.commonname && touched.commonname) && errors.commonname} - /> - - <CountrySelect defaultValue={values.country} {...props}/> - {touched.country && errors.country ? (<span class="spanError">{errors.country}</span>) : null} - - <TextField - variant="outlined" - margin="normal" - required - fullWidth - name="state" - label={i18next.t("state", "State")} - id="state" - autoComplete="state" - value={values.state} - onChange={handleChange} - onBlur={handleBlur} - helperText={(errors.state && touched.state) && errors.state} - /> - - <TextField - variant="outlined" - margin="normal" - required - fullWidth - name="city" - label={i18next.t("cistatety", "City")} - id="city" - autoComplete="city" - value={values.city} - onChange={handleChange} - onBlur={handleBlur} - helperText={(errors.city && touched.city) && errors.city} - /> - - - <TextField - variant="outlined" - margin="normal" - required - fullWidth - name="organization" - label={i18next.t("organization", "Organization")} - id="organization" - autoComplete="organization" - value={values.organization} - onChange={handleChange} - onBlur={handleBlur} - helperText={(errors.organization && touched.organization) && errors.organization} - /> - <TextField - variant="outlined" - margin="normal" - required - fullWidth - name="organizationunit" - label={i18next.t("organization_unit", "Organization Unit")} - id="organizationunit" - autoComplete="organizationunit" - value={values.organizationunit} - onChange={handleChange} - onBlur={handleBlur} - helperText={(errors.organizationunit && touched.organizationunit) && errors.organizationunit} - /> - - <Select - labelId="validity-period-select-label" - margin="normal" - fullWidth - variant="outlined" - value={validityPeriod.value} - onChange={handleValidPeriodChange} - children={validityPeriodsItems} - /> - - <Button - type="submit" - fullWidth - variant="contained" - color="primary" - className={classes.submit} - > - {i18next.t("generate_self_signed_certificate_authority", "Generate Self-Signed Certificate Authority")} - </Button> - - </form> - ); + axios(configApiCall(api_path_post_install_ca, "POST", jsonData, null)) + .then((response) => { + handleInstallCA(response); + }) + .catch((error) => { + props.setError(error); + console.log("Error installing CA Setup: " + error); + }); + }; + if (certificateOpt.value === 0) { + return ( + <Formik + validationSchema={validationSchemaform1} + initialValues={initialValuesform1} + onSubmit={(values) => { + handleSubmit(values); + }} + > + {(props) => { + const { + values, + touched, + errors, + handleSubmit, + handleChange, + handleBlur, + } = props; + return ( + <form className={classes.form} noValidate onSubmit={handleSubmit}> + <h4> + {i18next.t( + "ca_setup_header", + "Select an option for setting-up the certificate authority that will be used to sign all Jami accounts generated on this JAMS instance." + )} + </h4> + <Select + labelId="certificate-option-select-label" + fullWidth + value={certificateOpt.value} + onChange={handleCertifOptionChange} + variant="outlined" + children={certificateOptionsItems} + /> + + <TextField + variant="outlined" + margin="normal" + required + fullWidth + id="commonname" + label={i18next.t("common_name", "Common Name")} + name="commonname" + autoComplete="commonname" + autoFocus + value={values.commonname} + onChange={handleChange} + onBlur={handleBlur} + helperText={ + errors.commonname && touched.commonname && errors.commonname } + /> + + <CountrySelect defaultValue={values.country} {...props} /> + {touched.country && errors.country ? ( + <span class="spanError">{errors.country}</span> + ) : null} + + <TextField + variant="outlined" + margin="normal" + required + fullWidth + name="state" + label={i18next.t("state", "State")} + id="state" + autoComplete="state" + value={values.state} + onChange={handleChange} + onBlur={handleBlur} + helperText={errors.state && touched.state && errors.state} + /> + + <TextField + variant="outlined" + margin="normal" + required + fullWidth + name="city" + label={i18next.t("cistatety", "City")} + id="city" + autoComplete="city" + value={values.city} + onChange={handleChange} + onBlur={handleBlur} + helperText={errors.city && touched.city && errors.city} + /> + + <TextField + variant="outlined" + margin="normal" + required + fullWidth + name="organization" + label={i18next.t("organization", "Organization")} + id="organization" + autoComplete="organization" + value={values.organization} + onChange={handleChange} + onBlur={handleBlur} + helperText={ + errors.organization && + touched.organization && + errors.organization } - </Formik> - ); - } - else if(certificateOpt.value === 1){ - return ( - <Formik - validationSchema={validationSchemaform2} - initialValues={initialValuesform2} - onSubmit={values => { - handleSubmit(values); - }} - >{(props) => { - const { - handleSubmit, - handleChange, - } = props; - return ( - <form className={classes.form} noValidate onSubmit={handleSubmit}> - <h4> - {i18next.t("select_option_setting_up_certificate_authority", "Select an option for setting-up the certificate authority that will be used to sign all Jami accounts generated on this JAMS instance.")} - </h4> - - <Select - labelId="demo-simple-select-label" - fullWidth - value={certificateOpt.value} - onChange={handleCertifOptionChange} - variant="outlined" - children={certificateOptionsItems} - /> - <Typography variant="subtitle1" gutterBottom>CA file (PEM-encoded)</Typography> - <Field name="certificatefile"> - {({field, form}) => ( - <div> - <Input - fullWidth - type="file" - onChange={handleChange} - {...field} - /> - {form.errors.certificatefile && form.touched.certificatefile? <span class="spanError">{form.errors.certificatefile}</span> : null} - </div> - ) - } - </Field> - <Typography variant="subtitle1" gutterBottom>Key File (PEM-encoded)</Typography> - <Field name="privkeyfile"> - {({ - field, - form, - meta, - }) => ( - <div> - <Input - fullWidth - type="file" - {...field} - /> - {meta.touched && meta.error && (<span class="spanError">{meta.error}</span>)} - </div> - ) - } - </Field> - - <Button - type="submit" - fullWidth - variant="contained" - color="primary" - className={classes.submit} - > - {i18next.t("import_certificate_authority", "Import Certificate Authority")} - </Button> - - </form> - ); - }} - </Formik> - ); - } -} \ No newline at end of file + /> + + <TextField + variant="outlined" + margin="normal" + required + fullWidth + name="organizationunit" + label={i18next.t("organization_unit", "Organization Unit")} + id="organizationunit" + autoComplete="organizationunit" + value={values.organizationunit} + onChange={handleChange} + onBlur={handleBlur} + helperText={ + errors.organizationunit && + touched.organizationunit && + errors.organizationunit + } + /> + + <Select + labelId="validity-period-select-label" + margin="normal" + fullWidth + variant="outlined" + value={validityPeriod.value} + onChange={handleValidPeriodChange} + children={validityPeriodsItems} + /> + + <Button + type="submit" + fullWidth + variant="contained" + color="primary" + className={classes.submit} + > + {i18next.t( + "generate_self_signed_certificate_authority", + "Generate Self-Signed Certificate Authority" + )} + </Button> + </form> + ); + }} + </Formik> + ); + } else if (certificateOpt.value === 1) { + return ( + <Formik + validationSchema={validationSchemaform2} + initialValues={initialValuesform2} + onSubmit={(values) => { + handleSubmit(values); + }} + > + {(props) => { + const { handleSubmit, handleChange } = props; + return ( + <form className={classes.form} noValidate onSubmit={handleSubmit}> + <h4> + {i18next.t( + "select_option_setting_up_certificate_authority", + "Select an option for setting-up the certificate authority that will be used to sign all Jami accounts generated on this JAMS instance." + )} + </h4> + + <Select + labelId="demo-simple-select-label" + fullWidth + value={certificateOpt.value} + onChange={handleCertifOptionChange} + variant="outlined" + children={certificateOptionsItems} + /> + <Typography variant="subtitle1" gutterBottom> + CA file (PEM-encoded) + </Typography> + <Field name="certificatefile"> + {({ field, form }) => ( + <div> + <Input + fullWidth + type="file" + onChange={handleChange} + {...field} + /> + {form.errors.certificatefile && + form.touched.certificatefile ? ( + <span class="spanError"> + {form.errors.certificatefile} + </span> + ) : null} + </div> + )} + </Field> + <Typography variant="subtitle1" gutterBottom> + Key File (PEM-encoded) + </Typography> + <Field name="privkeyfile"> + {({ field, form, meta }) => ( + <div> + <Input fullWidth type="file" {...field} /> + {meta.touched && meta.error && ( + <span class="spanError">{meta.error}</span> + )} + </div> + )} + </Field> + + <Button + type="submit" + fullWidth + variant="contained" + color="primary" + className={classes.submit} + > + {i18next.t( + "import_certificate_authority", + "Import Certificate Authority" + )} + </Button> + </form> + ); + }} + </Formik> + ); + } +} diff --git a/jams-react-client/src/components/Card/Card.js b/jams-react-client/src/components/Card/Card.js index 5ab48ffc..567dd7b9 100644 --- a/jams-react-client/src/components/Card/Card.js +++ b/jams-react-client/src/components/Card/Card.js @@ -20,7 +20,7 @@ export default function Card(props) { [classes.cardPlain]: plain, [classes.cardProfile]: profile, [classes.cardChart]: chart, - [className]: className !== undefined + [className]: className !== undefined, }); return ( <div className={cardClasses} {...rest}> @@ -34,5 +34,5 @@ Card.propTypes = { plain: PropTypes.bool, profile: PropTypes.bool, chart: PropTypes.bool, - children: PropTypes.node + children: PropTypes.node, }; diff --git a/jams-react-client/src/components/Card/CardAvatar.js b/jams-react-client/src/components/Card/CardAvatar.js index 58e0368d..67e5e110 100644 --- a/jams-react-client/src/components/Card/CardAvatar.js +++ b/jams-react-client/src/components/Card/CardAvatar.js @@ -14,14 +14,22 @@ const useStyles = makeStyles(styles); export default function CardAvatar(props) { const classes = useStyles(); - const { children, className, plain, profile, displayProfile, editProfile, ...rest } = props; + const { + children, + className, + plain, + profile, + displayProfile, + editProfile, + ...rest + } = props; const cardAvatarClasses = classNames({ [classes.cardAvatar]: true, [classes.cardAvatarProfile]: profile, [classes.cardAvatarDisplayProfile]: displayProfile, [classes.cardAvatarEditProfile]: editProfile, [classes.cardAvatarPlain]: plain, - [className]: className !== undefined + [className]: className !== undefined, }); return ( <div className={cardAvatarClasses} {...rest}> @@ -36,5 +44,5 @@ CardAvatar.propTypes = { profile: PropTypes.bool, displayProfile: PropTypes.bool, editProfile: PropTypes.bool, - plain: PropTypes.bool + plain: PropTypes.bool, }; diff --git a/jams-react-client/src/components/Card/CardBody.js b/jams-react-client/src/components/Card/CardBody.js index 7d059d08..4c65b902 100644 --- a/jams-react-client/src/components/Card/CardBody.js +++ b/jams-react-client/src/components/Card/CardBody.js @@ -19,7 +19,7 @@ export default function CardBody(props) { [classes.cardBody]: true, [classes.cardBodyPlain]: plain, [classes.cardBodyProfile]: profile, - [className]: className !== undefined + [className]: className !== undefined, }); return ( <div className={cardBodyClasses} {...rest}> @@ -32,5 +32,5 @@ CardBody.propTypes = { className: PropTypes.string, plain: PropTypes.bool, profile: PropTypes.bool, - children: PropTypes.node + children: PropTypes.node, }; diff --git a/jams-react-client/src/components/Card/CardFooter.js b/jams-react-client/src/components/Card/CardFooter.js index 0a52c976..9559a388 100644 --- a/jams-react-client/src/components/Card/CardFooter.js +++ b/jams-react-client/src/components/Card/CardFooter.js @@ -21,7 +21,7 @@ export default function CardFooter(props) { [classes.cardFooterProfile]: profile, [classes.cardFooterStats]: stats, [classes.cardFooterChart]: chart, - [className]: className !== undefined + [className]: className !== undefined, }); return ( <div className={cardFooterClasses} {...rest}> @@ -36,5 +36,5 @@ CardFooter.propTypes = { profile: PropTypes.bool, stats: PropTypes.bool, chart: PropTypes.bool, - children: PropTypes.node + children: PropTypes.node, }; diff --git a/jams-react-client/src/components/Card/CardHeader.js b/jams-react-client/src/components/Card/CardHeader.js index 2d38da2d..6c15a0a7 100644 --- a/jams-react-client/src/components/Card/CardHeader.js +++ b/jams-react-client/src/components/Card/CardHeader.js @@ -21,7 +21,7 @@ export default function CardHeader(props) { [classes.cardHeaderPlain]: plain, [classes.cardHeaderStats]: stats, [classes.cardHeaderIcon]: icon, - [className]: className !== undefined + [className]: className !== undefined, }); return ( <div className={cardHeaderClasses} {...rest}> @@ -38,10 +38,10 @@ CardHeader.propTypes = { "danger", "info", "primary", - "rose" + "rose", ]), plain: PropTypes.bool, stats: PropTypes.bool, icon: PropTypes.bool, - children: PropTypes.node + children: PropTypes.node, }; diff --git a/jams-react-client/src/components/Card/CardIcon.js b/jams-react-client/src/components/Card/CardIcon.js index f05a4172..ba728619 100644 --- a/jams-react-client/src/components/Card/CardIcon.js +++ b/jams-react-client/src/components/Card/CardIcon.js @@ -18,7 +18,7 @@ export default function CardIcon(props) { const cardIconClasses = classNames({ [classes.cardIcon]: true, [classes[color + "CardHeader"]]: color, - [className]: className !== undefined + [className]: className !== undefined, }); return ( <div className={cardIconClasses} {...rest}> @@ -35,7 +35,7 @@ CardIcon.propTypes = { "danger", "info", "primary", - "rose" + "rose", ]), - children: PropTypes.node + children: PropTypes.node, }; diff --git a/jams-react-client/src/components/CountrySelect/CountrySelect.js b/jams-react-client/src/components/CountrySelect/CountrySelect.js index b0bef0d5..9b7a4f46 100644 --- a/jams-react-client/src/components/CountrySelect/CountrySelect.js +++ b/jams-react-client/src/components/CountrySelect/CountrySelect.js @@ -1,320 +1,323 @@ -import React from 'react'; -import TextField from '@material-ui/core/TextField'; -import Autocomplete from '@material-ui/lab/Autocomplete'; -import { makeStyles } from '@material-ui/core/styles'; +import React from "react"; +import TextField from "@material-ui/core/TextField"; +import Autocomplete from "@material-ui/lab/Autocomplete"; +import { makeStyles } from "@material-ui/core/styles"; import i18next from "i18next"; // ISO 3166-1 alpha-2 // âš ï¸ No support for IE 11 function countryToFlag(isoCode) { - return typeof String.fromCodePoint !== 'undefined' - ? isoCode - .toUpperCase() - .replace(/./g, (char) => String.fromCodePoint(char.charCodeAt(0) + 127397)) - : isoCode; + return typeof String.fromCodePoint !== "undefined" + ? isoCode + .toUpperCase() + .replace(/./g, (char) => + String.fromCodePoint(char.charCodeAt(0) + 127397) + ) + : isoCode; } const useStyles = makeStyles({ - option: { - fontSize: 15, - '& > span': { - marginRight: 10, - fontSize: 18, - }, + option: { + fontSize: 15, + "& > span": { + marginRight: 10, + fontSize: 18, }, + }, }); export default function CountrySelect(props) { - const classes = useStyles(); + const classes = useStyles(); - - return ( - <Autocomplete - id="country-select-demo" - name="country" - options={countries} - classes={{ - option: classes.option, - }} - onChange={(e, value) => { - value!=null ? props.setFieldValue("country", value.code): props.setFieldValue("country", ""); - }} - autoHighlight - getOptionLabel={(option) => ( - countryToFlag(option.code) + " "+ option.label - )} - renderOption={(option) => ( - <React.Fragment> - <span>{countryToFlag(option.code)}</span> - {option.label} - </React.Fragment> - )} - renderInput={(params) => ( - <TextField - {...params} - label={i18next.t("choose_a_country", "Choose a country")} - name="country" - variant="outlined" - onBlur={props.handleBlur} - inputProps={{ - ...params.inputProps, - autoComplete: 'country', // disable autocomplete and autofill - }} - /> - )} + return ( + <Autocomplete + id="country-select-demo" + name="country" + options={countries} + classes={{ + option: classes.option, + }} + onChange={(e, value) => { + value != null + ? props.setFieldValue("country", value.code) + : props.setFieldValue("country", ""); + }} + autoHighlight + getOptionLabel={(option) => + countryToFlag(option.code) + " " + option.label + } + renderOption={(option) => ( + <React.Fragment> + <span>{countryToFlag(option.code)}</span> + {option.label} + </React.Fragment> + )} + renderInput={(params) => ( + <TextField + {...params} + label={i18next.t("choose_a_country", "Choose a country")} + name="country" + variant="outlined" + onBlur={props.handleBlur} + inputProps={{ + ...params.inputProps, + autoComplete: "country", // disable autocomplete and autofill + }} /> - ); + )} + /> + ); } // From https://bitbucket.org/atlassian/atlaskit-mk-2/raw/4ad0e56649c3e6c973e226b7efaeb28cb240ccb0/packages/core/select/src/data/countries.js const countries = [ - { code: 'AD', label: 'Andorra' }, - { code: 'AE', label: 'United Arab Emirates' }, - { code: 'AF', label: 'Afghanistan' }, - { code: 'AG', label: 'Antigua and Barbuda' }, - { code: 'AI', label: 'Anguilla' }, - { code: 'AL', label: 'Albania' }, - { code: 'AM', label: 'Armenia' }, - { code: 'AO', label: 'Angola' }, - { code: 'AQ', label: 'Antarctica' }, - { code: 'AR', label: 'Argentina' }, - { code: 'AS', label: 'American Samoa' }, - { code: 'AT', label: 'Austria' }, - { code: 'AU', label: 'Australia', suggested: true }, - { code: 'AW', label: 'Aruba' }, - { code: 'AX', label: 'Alland Islands' }, - { code: 'AZ', label: 'Azerbaijan' }, - { code: 'BA', label: 'Bosnia and Herzegovina' }, - { code: 'BB', label: 'Barbados' }, - { code: 'BD', label: 'Bangladesh' }, - { code: 'BE', label: 'Belgium' }, - { code: 'BF', label: 'Burkina Faso' }, - { code: 'BG', label: 'Bulgaria' }, - { code: 'BH', label: 'Bahrain' }, - { code: 'BI', label: 'Burundi' }, - { code: 'BJ', label: 'Benin' }, - { code: 'BL', label: 'Saint Barthelemy' }, - { code: 'BM', label: 'Bermuda' }, - { code: 'BN', label: 'Brunei Darussalam' }, - { code: 'BO', label: 'Bolivia' }, - { code: 'BR', label: 'Brazil' }, - { code: 'BS', label: 'Bahamas' }, - { code: 'BT', label: 'Bhutan' }, - { code: 'BV', label: 'Bouvet Island' }, - { code: 'BW', label: 'Botswana' }, - { code: 'BY', label: 'Belarus' }, - { code: 'BZ', label: 'Belize' }, - { code: 'CA', label: 'Canada', suggested: true }, - { code: 'CC', label: 'Cocos (Keeling) Islands' }, - { code: 'CD', label: 'Congo, Democratic Republic of the' }, - { code: 'CF', label: 'Central African Republic' }, - { code: 'CG', label: 'Congo, Republic of the' }, - { code: 'CH', label: 'Switzerland' }, - { code: 'CI', label: "Cote d'Ivoire" }, - { code: 'CK', label: 'Cook Islands' }, - { code: 'CL', label: 'Chile' }, - { code: 'CM', label: 'Cameroon' }, - { code: 'CN', label: 'China' }, - { code: 'CO', label: 'Colombia' }, - { code: 'CR', label: 'Costa Rica' }, - { code: 'CU', label: 'Cuba' }, - { code: 'CV', label: 'Cape Verde' }, - { code: 'CW', label: 'Curacao' }, - { code: 'CX', label: 'Christmas Island' }, - { code: 'CY', label: 'Cyprus' }, - { code: 'CZ', label: 'Czech Republic' }, - { code: 'DE', label: 'Germany', suggested: true }, - { code: 'DJ', label: 'Djibouti' }, - { code: 'DK', label: 'Denmark' }, - { code: 'DM', label: 'Dominica' }, - { code: 'DO', label: 'Dominican Republic' }, - { code: 'DZ', label: 'Algeria' }, - { code: 'EC', label: 'Ecuador' }, - { code: 'EE', label: 'Estonia' }, - { code: 'EG', label: 'Egypt' }, - { code: 'EH', label: 'Western Sahara' }, - { code: 'ER', label: 'Eritrea' }, - { code: 'ES', label: 'Spain' }, - { code: 'ET', label: 'Ethiopia' }, - { code: 'FI', label: 'Finland' }, - { code: 'FJ', label: 'Fiji' }, - { code: 'FK', label: 'Falkland Islands (Malvinas)' }, - { code: 'FM', label: 'Micronesia, Federated States of' }, - { code: 'FO', label: 'Faroe Islands' }, - { code: 'FR', label: 'France', suggested: true }, - { code: 'GA', label: 'Gabon' }, - { code: 'GB', label: 'United Kingdom' }, - { code: 'GD', label: 'Grenada' }, - { code: 'GE', label: 'Georgia' }, - { code: 'GF', label: 'French Guiana' }, - { code: 'GG', label: 'Guernsey' }, - { code: 'GH', label: 'Ghana' }, - { code: 'GI', label: 'Gibraltar' }, - { code: 'GL', label: 'Greenland' }, - { code: 'GM', label: 'Gambia' }, - { code: 'GN', label: 'Guinea' }, - { code: 'GP', label: 'Guadeloupe' }, - { code: 'GQ', label: 'Equatorial Guinea' }, - { code: 'GR', label: 'Greece' }, - { code: 'GS', label: 'South Georgia and the South Sandwich Islands' }, - { code: 'GT', label: 'Guatemala' }, - { code: 'GU', label: 'Guam' }, - { code: 'GW', label: 'Guinea-Bissau' }, - { code: 'GY', label: 'Guyana' }, - { code: 'HK', label: 'Hong Kong' }, - { code: 'HM', label: 'Heard Island and McDonald Islands' }, - { code: 'HN', label: 'Honduras' }, - { code: 'HR', label: 'Croatia' }, - { code: 'HT', label: 'Haiti' }, - { code: 'HU', label: 'Hungary' }, - { code: 'ID', label: 'Indonesia' }, - { code: 'IE', label: 'Ireland' }, - { code: 'IL', label: 'Israel' }, - { code: 'IM', label: 'Isle of Man' }, - { code: 'IN', label: 'India' }, - { code: 'IO', label: 'British Indian Ocean Territory' }, - { code: 'IQ', label: 'Iraq' }, - { code: 'IR', label: 'Iran, Islamic Republic of' }, - { code: 'IS', label: 'Iceland' }, - { code: 'IT', label: 'Italy' }, - { code: 'JE', label: 'Jersey' }, - { code: 'JM', label: 'Jamaica' }, - { code: 'JO', label: 'Jordan' }, - { code: 'JP', label: 'Japan', suggested: true }, - { code: 'KE', label: 'Kenya' }, - { code: 'KG', label: 'Kyrgyzstan' }, - { code: 'KH', label: 'Cambodia' }, - { code: 'KI', label: 'Kiribati' }, - { code: 'KM', label: 'Comoros' }, - { code: 'KN', label: 'Saint Kitts and Nevis' }, - { code: 'KP', label: "Korea, Democratic People's Republic of" }, - { code: 'KR', label: 'Korea, Republic of' }, - { code: 'KW', label: 'Kuwait' }, - { code: 'KY', label: 'Cayman Islands' }, - { code: 'KZ', label: 'Kazakhstan' }, - { code: 'LA', label: "Lao People's Democratic Republic" }, - { code: 'LB', label: 'Lebanon' }, - { code: 'LC', label: 'Saint Lucia' }, - { code: 'LI', label: 'Liechtenstein' }, - { code: 'LK', label: 'Sri Lanka' }, - { code: 'LR', label: 'Liberia' }, - { code: 'LS', label: 'Lesotho' }, - { code: 'LT', label: 'Lithuania' }, - { code: 'LU', label: 'Luxembourg' }, - { code: 'LV', label: 'Latvia' }, - { code: 'LY', label: 'Libya' }, - { code: 'MA', label: 'Morocco' }, - { code: 'MC', label: 'Monaco' }, - { code: 'MD', label: 'Moldova, Republic of' }, - { code: 'ME', label: 'Montenegro' }, - { code: 'MF', label: 'Saint Martin (French part)' }, - { code: 'MG', label: 'Madagascar' }, - { code: 'MH', label: 'Marshall Islands' }, - { code: 'MK', label: 'Macedonia, the Former Yugoslav Republic of' }, - { code: 'ML', label: 'Mali' }, - { code: 'MM', label: 'Myanmar' }, - { code: 'MN', label: 'Mongolia' }, - { code: 'MO', label: 'Macao' }, - { code: 'MP', label: 'Northern Mariana Islands' }, - { code: 'MQ', label: 'Martinique' }, - { code: 'MR', label: 'Mauritania' }, - { code: 'MS', label: 'Montserrat' }, - { code: 'MT', label: 'Malta' }, - { code: 'MU', label: 'Mauritius' }, - { code: 'MV', label: 'Maldives' }, - { code: 'MW', label: 'Malawi' }, - { code: 'MX', label: 'Mexico' }, - { code: 'MY', label: 'Malaysia' }, - { code: 'MZ', label: 'Mozambique' }, - { code: 'NA', label: 'Namibia' }, - { code: 'NC', label: 'New Caledonia' }, - { code: 'NE', label: 'Niger' }, - { code: 'NF', label: 'Norfolk Island' }, - { code: 'NG', label: 'Nigeria' }, - { code: 'NI', label: 'Nicaragua' }, - { code: 'NL', label: 'Netherlands' }, - { code: 'NO', label: 'Norway' }, - { code: 'NP', label: 'Nepal' }, - { code: 'NR', label: 'Nauru' }, - { code: 'NU', label: 'Niue' }, - { code: 'NZ', label: 'New Zealand' }, - { code: 'OM', label: 'Oman' }, - { code: 'PA', label: 'Panama' }, - { code: 'PE', label: 'Peru' }, - { code: 'PF', label: 'French Polynesia' }, - { code: 'PG', label: 'Papua New Guinea' }, - { code: 'PH', label: 'Philippines' }, - { code: 'PK', label: 'Pakistan' }, - { code: 'PL', label: 'Poland' }, - { code: 'PM', label: 'Saint Pierre and Miquelon' }, - { code: 'PN', label: 'Pitcairn' }, - { code: 'PR', label: 'Puerto Rico' }, - { code: 'PS', label: 'Palestine, State of' }, - { code: 'PT', label: 'Portugal' }, - { code: 'PW', label: 'Palau' }, - { code: 'PY', label: 'Paraguay' }, - { code: 'QA', label: 'Qatar' }, - { code: 'RE', label: 'Reunion' }, - { code: 'RO', label: 'Romania' }, - { code: 'RS', label: 'Serbia' }, - { code: 'RU', label: 'Russian Federation' }, - { code: 'RW', label: 'Rwanda' }, - { code: 'SA', label: 'Saudi Arabia' }, - { code: 'SB', label: 'Solomon Islands' }, - { code: 'SC', label: 'Seychelles' }, - { code: 'SD', label: 'Sudan' }, - { code: 'SE', label: 'Sweden' }, - { code: 'SG', label: 'Singapore' }, - { code: 'SH', label: 'Saint Helena' }, - { code: 'SI', label: 'Slovenia' }, - { code: 'SJ', label: 'Svalbard and Jan Mayen' }, - { code: 'SK', label: 'Slovakia' }, - { code: 'SL', label: 'Sierra Leone' }, - { code: 'SM', label: 'San Marino' }, - { code: 'SN', label: 'Senegal' }, - { code: 'SO', label: 'Somalia' }, - { code: 'SR', label: 'Suriname' }, - { code: 'SS', label: 'South Sudan' }, - { code: 'ST', label: 'Sao Tome and Principe' }, - { code: 'SV', label: 'El Salvador' }, - { code: 'SX', label: 'Sint Maarten (Dutch part)' }, - { code: 'SY', label: 'Syrian Arab Republic' }, - { code: 'SZ', label: 'Swaziland' }, - { code: 'TC', label: 'Turks and Caicos Islands' }, - { code: 'TD', label: 'Chad' }, - { code: 'TF', label: 'French Southern Territories' }, - { code: 'TG', label: 'Togo' }, - { code: 'TH', label: 'Thailand' }, - { code: 'TJ', label: 'Tajikistan' }, - { code: 'TK', label: 'Tokelau' }, - { code: 'TL', label: 'Timor-Leste' }, - { code: 'TM', label: 'Turkmenistan' }, - { code: 'TN', label: 'Tunisia' }, - { code: 'TO', label: 'Tonga' }, - { code: 'TR', label: 'Turkey' }, - { code: 'TT', label: 'Trinidad and Tobago' }, - { code: 'TV', label: 'Tuvalu' }, - { code: 'TW', label: 'Taiwan, Province of China' }, - { code: 'TZ', label: 'United Republic of Tanzania' }, - { code: 'UA', label: 'Ukraine' }, - { code: 'UG', label: 'Uganda' }, - { code: 'US', label: 'United States', suggested: true }, - { code: 'UY', label: 'Uruguay' }, - { code: 'UZ', label: 'Uzbekistan' }, - { code: 'VA', label: 'Holy See (Vatican City State)' }, - { code: 'VC', label: 'Saint Vincent and the Grenadines' }, - { code: 'VE', label: 'Venezuela' }, - { code: 'VG', label: 'British Virgin Islands' }, - { code: 'VI', label: 'US Virgin Islands' }, - { code: 'VN', label: 'Vietnam' }, - { code: 'VU', label: 'Vanuatu' }, - { code: 'WF', label: 'Wallis and Futuna' }, - { code: 'WS', label: 'Samoa' }, - { code: 'XK', label: 'Kosovo' }, - { code: 'YE', label: 'Yemen' }, - { code: 'YT', label: 'Mayotte' }, - { code: 'ZA', label: 'South Africa' }, - { code: 'ZM', label: 'Zambia' }, - { code: 'ZW', label: 'Zimbabwe' }, -]; \ No newline at end of file + { code: "AD", label: "Andorra" }, + { code: "AE", label: "United Arab Emirates" }, + { code: "AF", label: "Afghanistan" }, + { code: "AG", label: "Antigua and Barbuda" }, + { code: "AI", label: "Anguilla" }, + { code: "AL", label: "Albania" }, + { code: "AM", label: "Armenia" }, + { code: "AO", label: "Angola" }, + { code: "AQ", label: "Antarctica" }, + { code: "AR", label: "Argentina" }, + { code: "AS", label: "American Samoa" }, + { code: "AT", label: "Austria" }, + { code: "AU", label: "Australia", suggested: true }, + { code: "AW", label: "Aruba" }, + { code: "AX", label: "Alland Islands" }, + { code: "AZ", label: "Azerbaijan" }, + { code: "BA", label: "Bosnia and Herzegovina" }, + { code: "BB", label: "Barbados" }, + { code: "BD", label: "Bangladesh" }, + { code: "BE", label: "Belgium" }, + { code: "BF", label: "Burkina Faso" }, + { code: "BG", label: "Bulgaria" }, + { code: "BH", label: "Bahrain" }, + { code: "BI", label: "Burundi" }, + { code: "BJ", label: "Benin" }, + { code: "BL", label: "Saint Barthelemy" }, + { code: "BM", label: "Bermuda" }, + { code: "BN", label: "Brunei Darussalam" }, + { code: "BO", label: "Bolivia" }, + { code: "BR", label: "Brazil" }, + { code: "BS", label: "Bahamas" }, + { code: "BT", label: "Bhutan" }, + { code: "BV", label: "Bouvet Island" }, + { code: "BW", label: "Botswana" }, + { code: "BY", label: "Belarus" }, + { code: "BZ", label: "Belize" }, + { code: "CA", label: "Canada", suggested: true }, + { code: "CC", label: "Cocos (Keeling) Islands" }, + { code: "CD", label: "Congo, Democratic Republic of the" }, + { code: "CF", label: "Central African Republic" }, + { code: "CG", label: "Congo, Republic of the" }, + { code: "CH", label: "Switzerland" }, + { code: "CI", label: "Cote d'Ivoire" }, + { code: "CK", label: "Cook Islands" }, + { code: "CL", label: "Chile" }, + { code: "CM", label: "Cameroon" }, + { code: "CN", label: "China" }, + { code: "CO", label: "Colombia" }, + { code: "CR", label: "Costa Rica" }, + { code: "CU", label: "Cuba" }, + { code: "CV", label: "Cape Verde" }, + { code: "CW", label: "Curacao" }, + { code: "CX", label: "Christmas Island" }, + { code: "CY", label: "Cyprus" }, + { code: "CZ", label: "Czech Republic" }, + { code: "DE", label: "Germany", suggested: true }, + { code: "DJ", label: "Djibouti" }, + { code: "DK", label: "Denmark" }, + { code: "DM", label: "Dominica" }, + { code: "DO", label: "Dominican Republic" }, + { code: "DZ", label: "Algeria" }, + { code: "EC", label: "Ecuador" }, + { code: "EE", label: "Estonia" }, + { code: "EG", label: "Egypt" }, + { code: "EH", label: "Western Sahara" }, + { code: "ER", label: "Eritrea" }, + { code: "ES", label: "Spain" }, + { code: "ET", label: "Ethiopia" }, + { code: "FI", label: "Finland" }, + { code: "FJ", label: "Fiji" }, + { code: "FK", label: "Falkland Islands (Malvinas)" }, + { code: "FM", label: "Micronesia, Federated States of" }, + { code: "FO", label: "Faroe Islands" }, + { code: "FR", label: "France", suggested: true }, + { code: "GA", label: "Gabon" }, + { code: "GB", label: "United Kingdom" }, + { code: "GD", label: "Grenada" }, + { code: "GE", label: "Georgia" }, + { code: "GF", label: "French Guiana" }, + { code: "GG", label: "Guernsey" }, + { code: "GH", label: "Ghana" }, + { code: "GI", label: "Gibraltar" }, + { code: "GL", label: "Greenland" }, + { code: "GM", label: "Gambia" }, + { code: "GN", label: "Guinea" }, + { code: "GP", label: "Guadeloupe" }, + { code: "GQ", label: "Equatorial Guinea" }, + { code: "GR", label: "Greece" }, + { code: "GS", label: "South Georgia and the South Sandwich Islands" }, + { code: "GT", label: "Guatemala" }, + { code: "GU", label: "Guam" }, + { code: "GW", label: "Guinea-Bissau" }, + { code: "GY", label: "Guyana" }, + { code: "HK", label: "Hong Kong" }, + { code: "HM", label: "Heard Island and McDonald Islands" }, + { code: "HN", label: "Honduras" }, + { code: "HR", label: "Croatia" }, + { code: "HT", label: "Haiti" }, + { code: "HU", label: "Hungary" }, + { code: "ID", label: "Indonesia" }, + { code: "IE", label: "Ireland" }, + { code: "IL", label: "Israel" }, + { code: "IM", label: "Isle of Man" }, + { code: "IN", label: "India" }, + { code: "IO", label: "British Indian Ocean Territory" }, + { code: "IQ", label: "Iraq" }, + { code: "IR", label: "Iran, Islamic Republic of" }, + { code: "IS", label: "Iceland" }, + { code: "IT", label: "Italy" }, + { code: "JE", label: "Jersey" }, + { code: "JM", label: "Jamaica" }, + { code: "JO", label: "Jordan" }, + { code: "JP", label: "Japan", suggested: true }, + { code: "KE", label: "Kenya" }, + { code: "KG", label: "Kyrgyzstan" }, + { code: "KH", label: "Cambodia" }, + { code: "KI", label: "Kiribati" }, + { code: "KM", label: "Comoros" }, + { code: "KN", label: "Saint Kitts and Nevis" }, + { code: "KP", label: "Korea, Democratic People's Republic of" }, + { code: "KR", label: "Korea, Republic of" }, + { code: "KW", label: "Kuwait" }, + { code: "KY", label: "Cayman Islands" }, + { code: "KZ", label: "Kazakhstan" }, + { code: "LA", label: "Lao People's Democratic Republic" }, + { code: "LB", label: "Lebanon" }, + { code: "LC", label: "Saint Lucia" }, + { code: "LI", label: "Liechtenstein" }, + { code: "LK", label: "Sri Lanka" }, + { code: "LR", label: "Liberia" }, + { code: "LS", label: "Lesotho" }, + { code: "LT", label: "Lithuania" }, + { code: "LU", label: "Luxembourg" }, + { code: "LV", label: "Latvia" }, + { code: "LY", label: "Libya" }, + { code: "MA", label: "Morocco" }, + { code: "MC", label: "Monaco" }, + { code: "MD", label: "Moldova, Republic of" }, + { code: "ME", label: "Montenegro" }, + { code: "MF", label: "Saint Martin (French part)" }, + { code: "MG", label: "Madagascar" }, + { code: "MH", label: "Marshall Islands" }, + { code: "MK", label: "Macedonia, the Former Yugoslav Republic of" }, + { code: "ML", label: "Mali" }, + { code: "MM", label: "Myanmar" }, + { code: "MN", label: "Mongolia" }, + { code: "MO", label: "Macao" }, + { code: "MP", label: "Northern Mariana Islands" }, + { code: "MQ", label: "Martinique" }, + { code: "MR", label: "Mauritania" }, + { code: "MS", label: "Montserrat" }, + { code: "MT", label: "Malta" }, + { code: "MU", label: "Mauritius" }, + { code: "MV", label: "Maldives" }, + { code: "MW", label: "Malawi" }, + { code: "MX", label: "Mexico" }, + { code: "MY", label: "Malaysia" }, + { code: "MZ", label: "Mozambique" }, + { code: "NA", label: "Namibia" }, + { code: "NC", label: "New Caledonia" }, + { code: "NE", label: "Niger" }, + { code: "NF", label: "Norfolk Island" }, + { code: "NG", label: "Nigeria" }, + { code: "NI", label: "Nicaragua" }, + { code: "NL", label: "Netherlands" }, + { code: "NO", label: "Norway" }, + { code: "NP", label: "Nepal" }, + { code: "NR", label: "Nauru" }, + { code: "NU", label: "Niue" }, + { code: "NZ", label: "New Zealand" }, + { code: "OM", label: "Oman" }, + { code: "PA", label: "Panama" }, + { code: "PE", label: "Peru" }, + { code: "PF", label: "French Polynesia" }, + { code: "PG", label: "Papua New Guinea" }, + { code: "PH", label: "Philippines" }, + { code: "PK", label: "Pakistan" }, + { code: "PL", label: "Poland" }, + { code: "PM", label: "Saint Pierre and Miquelon" }, + { code: "PN", label: "Pitcairn" }, + { code: "PR", label: "Puerto Rico" }, + { code: "PS", label: "Palestine, State of" }, + { code: "PT", label: "Portugal" }, + { code: "PW", label: "Palau" }, + { code: "PY", label: "Paraguay" }, + { code: "QA", label: "Qatar" }, + { code: "RE", label: "Reunion" }, + { code: "RO", label: "Romania" }, + { code: "RS", label: "Serbia" }, + { code: "RU", label: "Russian Federation" }, + { code: "RW", label: "Rwanda" }, + { code: "SA", label: "Saudi Arabia" }, + { code: "SB", label: "Solomon Islands" }, + { code: "SC", label: "Seychelles" }, + { code: "SD", label: "Sudan" }, + { code: "SE", label: "Sweden" }, + { code: "SG", label: "Singapore" }, + { code: "SH", label: "Saint Helena" }, + { code: "SI", label: "Slovenia" }, + { code: "SJ", label: "Svalbard and Jan Mayen" }, + { code: "SK", label: "Slovakia" }, + { code: "SL", label: "Sierra Leone" }, + { code: "SM", label: "San Marino" }, + { code: "SN", label: "Senegal" }, + { code: "SO", label: "Somalia" }, + { code: "SR", label: "Suriname" }, + { code: "SS", label: "South Sudan" }, + { code: "ST", label: "Sao Tome and Principe" }, + { code: "SV", label: "El Salvador" }, + { code: "SX", label: "Sint Maarten (Dutch part)" }, + { code: "SY", label: "Syrian Arab Republic" }, + { code: "SZ", label: "Swaziland" }, + { code: "TC", label: "Turks and Caicos Islands" }, + { code: "TD", label: "Chad" }, + { code: "TF", label: "French Southern Territories" }, + { code: "TG", label: "Togo" }, + { code: "TH", label: "Thailand" }, + { code: "TJ", label: "Tajikistan" }, + { code: "TK", label: "Tokelau" }, + { code: "TL", label: "Timor-Leste" }, + { code: "TM", label: "Turkmenistan" }, + { code: "TN", label: "Tunisia" }, + { code: "TO", label: "Tonga" }, + { code: "TR", label: "Turkey" }, + { code: "TT", label: "Trinidad and Tobago" }, + { code: "TV", label: "Tuvalu" }, + { code: "TW", label: "Taiwan, Province of China" }, + { code: "TZ", label: "United Republic of Tanzania" }, + { code: "UA", label: "Ukraine" }, + { code: "UG", label: "Uganda" }, + { code: "US", label: "United States", suggested: true }, + { code: "UY", label: "Uruguay" }, + { code: "UZ", label: "Uzbekistan" }, + { code: "VA", label: "Holy See (Vatican City State)" }, + { code: "VC", label: "Saint Vincent and the Grenadines" }, + { code: "VE", label: "Venezuela" }, + { code: "VG", label: "British Virgin Islands" }, + { code: "VI", label: "US Virgin Islands" }, + { code: "VN", label: "Vietnam" }, + { code: "VU", label: "Vanuatu" }, + { code: "WF", label: "Wallis and Futuna" }, + { code: "WS", label: "Samoa" }, + { code: "XK", label: "Kosovo" }, + { code: "YE", label: "Yemen" }, + { code: "YT", label: "Mayotte" }, + { code: "ZA", label: "South Africa" }, + { code: "ZM", label: "Zambia" }, + { code: "ZW", label: "Zimbabwe" }, +]; diff --git a/jams-react-client/src/components/CreateAdmin/CreateAdmin.js b/jams-react-client/src/components/CreateAdmin/CreateAdmin.js index dcb8af4d..31951800 100644 --- a/jams-react-client/src/components/CreateAdmin/CreateAdmin.js +++ b/jams-react-client/src/components/CreateAdmin/CreateAdmin.js @@ -51,15 +51,41 @@ export default function CreateAdmin(props) { }, validationSchema: Yup.object({ username: Yup.string() - .max(60, i18next.t("must_be_60_characters_or_less", "Must be 60 characters or less")) + .max( + 60, + i18next.t( + "must_be_60_characters_or_less", + "Must be 60 characters or less" + ) + ) .required(i18next.t("username_is_required", "Username is required!")), password: Yup.string() - .max(50, i18next.t("must_be_50_characters_or_less", "Must be 50 characters or less")) + .max( + 50, + i18next.t( + "must_be_50_characters_or_less", + "Must be 50 characters or less" + ) + ) .required("Password is required"), confirmPassword: Yup.string() - .oneOf([Yup.ref("password"), null], i18next.t("password_must_match", "Passwords must match")) - .max(50, i18next.t("must_be_50_characters_or_less", "Must be 50 characters or less")) - .required(i18next.t("password_confirmation_required", "Password confirmation is required.")), + .oneOf( + [Yup.ref("password"), null], + i18next.t("password_must_match", "Passwords must match") + ) + .max( + 50, + i18next.t( + "must_be_50_characters_or_less", + "Must be 50 characters or less" + ) + ) + .required( + i18next.t( + "password_confirmation_required", + "Password confirmation is required." + ) + ), }), onSubmit: (values) => { @@ -82,13 +108,13 @@ export default function CreateAdmin(props) { password: values.password, }; axios(configApiCall(api_path_post_install_admin, "PUT", jsonData, null)) - .then((response) => { - createAdminCallBackHandler(response); - }) - .catch((error) => { - props.setErrorMessage(error); - props.setError(true); - }); + .then((response) => { + createAdminCallBackHandler(response); + }) + .catch((error) => { + props.setErrorMessage(error); + props.setError(true); + }); } return ( diff --git a/jams-react-client/src/components/CustomButtons/Button.js b/jams-react-client/src/components/CustomButtons/Button.js index 9cf835f8..166cb8e8 100644 --- a/jams-react-client/src/components/CustomButtons/Button.js +++ b/jams-react-client/src/components/CustomButtons/Button.js @@ -38,7 +38,7 @@ export default function RegularButton(props) { [classes.block]: block, [classes.link]: link, [classes.justIcon]: justIcon, - [className]: className + [className]: className, }); return ( <Button {...rest} classes={muiClasses} className={btnClasses}> @@ -56,7 +56,7 @@ RegularButton.propTypes = { "danger", "rose", "white", - "transparent" + "transparent", ]), size: PropTypes.oneOf(["sm", "lg"]), simple: PropTypes.bool, @@ -68,5 +68,5 @@ RegularButton.propTypes = { className: PropTypes.string, // use this to pass the classes props from Material-UI muiClasses: PropTypes.object, - children: PropTypes.node + children: PropTypes.node, }; diff --git a/jams-react-client/src/components/CustomInput/CustomInput.js b/jams-react-client/src/components/CustomInput/CustomInput.js index 782d38ad..59e17957 100644 --- a/jams-react-client/src/components/CustomInput/CustomInput.js +++ b/jams-react-client/src/components/CustomInput/CustomInput.js @@ -23,20 +23,20 @@ export default function CustomInput(props) { labelProps, inputProps, error, - success + success, } = props; const labelClasses = classNames({ [" " + classes.labelRootError]: error, - [" " + classes.labelRootSuccess]: success && !error + [" " + classes.labelRootSuccess]: success && !error, }); const underlineClasses = classNames({ [classes.underlineError]: error, [classes.underlineSuccess]: success && !error, - [classes.underline]: true + [classes.underline]: true, }); const marginTop = classNames({ - [classes.marginTop]: labelText === undefined + [classes.marginTop]: labelText === undefined, }); return ( <FormControl @@ -56,7 +56,7 @@ export default function CustomInput(props) { classes={{ root: marginTop, disabled: classes.disabled, - underline: underlineClasses + underline: underlineClasses, }} id={id} {...inputProps} @@ -77,5 +77,5 @@ CustomInput.propTypes = { inputProps: PropTypes.object, formControlProps: PropTypes.object, error: PropTypes.bool, - success: PropTypes.bool + success: PropTypes.bool, }; diff --git a/jams-react-client/src/components/CustomPopupState/CustomPopupState.js b/jams-react-client/src/components/CustomPopupState/CustomPopupState.js index 9e1c44ea..5ee4948b 100644 --- a/jams-react-client/src/components/CustomPopupState/CustomPopupState.js +++ b/jams-react-client/src/components/CustomPopupState/CustomPopupState.js @@ -1,39 +1,40 @@ -import React from 'react'; -import InfoIcon from '@material-ui/icons/Info'; -import Popover from '@material-ui/core/Popover'; -import PopupState, { bindTrigger, bindPopover } from 'material-ui-popup-state'; -import IconButton from '@material-ui/core/IconButton'; -import Box from '@material-ui/core/Box'; -import Typography from '@material-ui/core/Typography'; - +import React from "react"; +import InfoIcon from "@material-ui/icons/Info"; +import Popover from "@material-ui/core/Popover"; +import PopupState, { bindTrigger, bindPopover } from "material-ui-popup-state"; +import IconButton from "@material-ui/core/IconButton"; +import Box from "@material-ui/core/Box"; +import Typography from "@material-ui/core/Typography"; export default function CustomPopupState(props) { - - return( -<IconButton> - -<PopupState variant="popover" popupId="demo-popup-popover"> - {(popupState) => ( - <div> - <InfoIcon color="disabled" fontSize="small" {...bindTrigger(popupState)} /> - <Popover - {...bindPopover(popupState)} - anchorOrigin={{ - vertical: 'top', - horizontal: 'left', - }} - transformOrigin={{ - vertical: 'bottom', - horizontal: 'left', - }} - > - <Box p={1}> - <Typography>{props.message}</Typography> - </Box> - </Popover> - </div> - )} -</PopupState> -</IconButton> - ); -} \ No newline at end of file + return ( + <IconButton> + <PopupState variant="popover" popupId="demo-popup-popover"> + {(popupState) => ( + <div> + <InfoIcon + color="disabled" + fontSize="small" + {...bindTrigger(popupState)} + /> + <Popover + {...bindPopover(popupState)} + anchorOrigin={{ + vertical: "top", + horizontal: "left", + }} + transformOrigin={{ + vertical: "bottom", + horizontal: "left", + }} + > + <Box p={1}> + <Typography>{props.message}</Typography> + </Box> + </Popover> + </div> + )} + </PopupState> + </IconButton> + ); +} diff --git a/jams-react-client/src/components/CustomTabs/CustomTabs.js b/jams-react-client/src/components/CustomTabs/CustomTabs.js index 1d153fa8..6c151f2a 100644 --- a/jams-react-client/src/components/CustomTabs/CustomTabs.js +++ b/jams-react-client/src/components/CustomTabs/CustomTabs.js @@ -26,7 +26,7 @@ export default function CustomTabs(props) { const { headerColor, plainTabs, tabs, title, rtlActive } = props; const cardTitle = classNames({ [classes.cardTitle]: true, - [classes.cardTitleRTL]: rtlActive + [classes.cardTitleRTL]: rtlActive, }); return ( <Card plain={plainTabs}> @@ -38,7 +38,7 @@ export default function CustomTabs(props) { classes={{ root: classes.tabsRoot, indicator: classes.displayNone, - scrollButtons: classes.displayNone + scrollButtons: classes.displayNone, }} variant="scrollable" scrollButtons="auto" @@ -47,7 +47,7 @@ export default function CustomTabs(props) { var icon = {}; if (prop.tabIcon) { icon = { - icon: <prop.tabIcon /> + icon: <prop.tabIcon />, }; } return ( @@ -55,7 +55,7 @@ export default function CustomTabs(props) { classes={{ root: classes.tabRootButton, selected: classes.tabSelected, - wrapper: classes.tabWrapper + wrapper: classes.tabWrapper, }} key={key} label={prop.tabName} @@ -84,16 +84,16 @@ CustomTabs.propTypes = { "danger", "info", "primary", - "rose" + "rose", ]), title: PropTypes.string, tabs: PropTypes.arrayOf( PropTypes.shape({ tabName: PropTypes.string.isRequired, tabIcon: PropTypes.object, - tabContent: PropTypes.node.isRequired + tabContent: PropTypes.node.isRequired, }) ), rtlActive: PropTypes.bool, - plainTabs: PropTypes.bool + plainTabs: PropTypes.bool, }; diff --git a/jams-react-client/src/components/CustomizedSteppers/CustomizedSteppers.js b/jams-react-client/src/components/CustomizedSteppers/CustomizedSteppers.js index 71518121..cf12276b 100644 --- a/jams-react-client/src/components/CustomizedSteppers/CustomizedSteppers.js +++ b/jams-react-client/src/components/CustomizedSteppers/CustomizedSteppers.js @@ -1,35 +1,35 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { makeStyles } from '@material-ui/core/styles'; -import clsx from 'clsx'; -import Stepper from '@material-ui/core/Stepper'; -import Step from '@material-ui/core/Step'; -import StepLabel from '@material-ui/core/StepLabel'; -import Check from '@material-ui/icons/Check'; -import SettingsIcon from '@material-ui/icons/Settings'; -import GroupAddIcon from '@material-ui/icons/GroupAdd'; -import VideoLabelIcon from '@material-ui/icons/VideoLabel'; +import React from "react"; +import PropTypes from "prop-types"; +import { makeStyles } from "@material-ui/core/styles"; +import clsx from "clsx"; +import Stepper from "@material-ui/core/Stepper"; +import Step from "@material-ui/core/Step"; +import StepLabel from "@material-ui/core/StepLabel"; +import Check from "@material-ui/icons/Check"; +import SettingsIcon from "@material-ui/icons/Settings"; +import GroupAddIcon from "@material-ui/icons/GroupAdd"; +import VideoLabelIcon from "@material-ui/icons/VideoLabel"; -import i18next from 'i18next'; +import i18next from "i18next"; const useQontoStepIconStyles = makeStyles({ root: { - color: '#eaeaf0', - display: 'flex', + color: "#eaeaf0", + display: "flex", height: 22, - alignItems: 'center', + alignItems: "center", }, active: { - color: '#784af4', + color: "#784af4", }, circle: { width: 8, height: 8, - borderRadius: '50%', - backgroundColor: 'currentColor', + borderRadius: "50%", + backgroundColor: "currentColor", }, completed: { - color: '#784af4', + color: "#784af4", zIndex: 1, fontSize: 18, }, @@ -45,7 +45,11 @@ function QontoStepIcon(props) { [classes.active]: active, })} > - {completed ? <Check className={classes.completed} /> : <div className={classes.circle} />} + {completed ? ( + <Check className={classes.completed} /> + ) : ( + <div className={classes.circle} /> + )} </div> ); } @@ -63,24 +67,24 @@ QontoStepIcon.propTypes = { const useColorlibStepIconStyles = makeStyles({ root: { - backgroundColor: '#ccc', + backgroundColor: "#ccc", zIndex: 1, - color: '#fff', + color: "#fff", width: 50, height: 50, - display: 'flex', - borderRadius: '50%', - justifyContent: 'center', - alignItems: 'center', + display: "flex", + borderRadius: "50%", + justifyContent: "center", + alignItems: "center", }, active: { backgroundImage: - 'linear-gradient( 136deg, rgb(242,113,33) 0%, rgb(233,64,87) 50%, rgb(138,35,135) 100%)', - boxShadow: '0 4px 10px 0 rgba(0,0,0,.25)', + "linear-gradient( 136deg, rgb(242,113,33) 0%, rgb(233,64,87) 50%, rgb(138,35,135) 100%)", + boxShadow: "0 4px 10px 0 rgba(0,0,0,.25)", }, completed: { backgroundImage: - 'linear-gradient( 136deg, rgb(242,113,33) 0%, rgb(233,64,87) 50%, rgb(138,35,135) 100%)', + "linear-gradient( 136deg, rgb(242,113,33) 0%, rgb(233,64,87) 50%, rgb(138,35,135) 100%)", }, }); @@ -123,7 +127,7 @@ ColorlibStepIcon.propTypes = { const useStyles = makeStyles((theme) => ({ root: { - width: '100%', + width: "100%", }, button: { marginRight: theme.spacing(1), @@ -135,7 +139,12 @@ const useStyles = makeStyles((theme) => ({ })); function getSteps() { - return [i18next.t("create_administrator_user", 'Create Administrator User'), i18next.t("certificate_authority_setup", 'Certificate Authority Setup'), i18next.t("identity_management", 'Identity Management'), i18next.t("server_parameters", 'Server Parameters')]; + return [ + i18next.t("create_administrator_user", "Create Administrator User"), + i18next.t("certificate_authority_setup", "Certificate Authority Setup"), + i18next.t("identity_management", "Identity Management"), + i18next.t("server_parameters", "Server Parameters"), + ]; } export default function CustomizedSteppers(props) { diff --git a/jams-react-client/src/components/Devices/Devices.js b/jams-react-client/src/components/Devices/Devices.js index 9f053633..06793004 100755 --- a/jams-react-client/src/components/Devices/Devices.js +++ b/jams-react-client/src/components/Devices/Devices.js @@ -1,36 +1,38 @@ -import React, {useEffect} from "react"; +import React, { useEffect } from "react"; import { useHistory } from "react-router-dom"; import classnames from "classnames"; -import {Formik, Field} from "formik"; +import { Formik, Field } from "formik"; // @material-ui/core components import { makeStyles } from "@material-ui/core/styles"; import Tooltip from "@material-ui/core/Tooltip"; import IconButton from "@material-ui/core/IconButton"; import Button from "components/CustomButtons/Button.js"; import Table from "@material-ui/core/Table"; -import TableHead from '@material-ui/core/TableHead'; +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 Dialog from '@material-ui/core/Dialog'; -import DialogActions from '@material-ui/core/DialogActions'; -import DialogContent from '@material-ui/core/DialogContent'; -import DialogContentText from '@material-ui/core/DialogContentText'; -import DialogTitle from '@material-ui/core/DialogTitle'; -import TextField from '@material-ui/core/TextField'; +import Dialog from "@material-ui/core/Dialog"; +import DialogActions from "@material-ui/core/DialogActions"; +import DialogContent from "@material-ui/core/DialogContent"; +import DialogContentText from "@material-ui/core/DialogContentText"; +import DialogTitle from "@material-ui/core/DialogTitle"; +import TextField from "@material-ui/core/TextField"; // @material-ui/icons import Edit from "@material-ui/icons/Edit"; import Close from "@material-ui/icons/Close"; // core components import styles from "assets/jss/material-dashboard-react/components/devicesStyle.js"; -import auth from "auth.js" +import auth from "auth.js"; import configApiCall from "api.js"; import { - api_path_delete_admin_device_revoke, api_path_delete_auth_device_revoke, - api_path_get_admin_devices, - api_path_get_auth_devices, api_path_rename_device + api_path_delete_admin_device_revoke, + api_path_delete_auth_device_revoke, + api_path_get_admin_devices, + api_path_get_auth_devices, + api_path_rename_device, } from "../../globalUrls"; import axios from "axios"; @@ -39,278 +41,359 @@ import i18next from "i18next"; const useStyles = makeStyles(styles); export default function Devices(props) { - const classes = useStyles(); - const history = useHistory(); + const classes = useStyles(); + const history = useHistory(); - const [devices, setDevices] = React.useState([]) - const [selectedDevice, setSelectedDevice]= React.useState({}); - const [displayName, setDisplayName] = React.useState("") - const [openEdit, setOpenEdit] = React.useState(false); - const [openRevoke, setOpenRevoke] = React.useState(false); - const userData = { - "username": props.username - }; + const [devices, setDevices] = React.useState([]); + const [selectedDevice, setSelectedDevice] = React.useState({}); + const [displayName, setDisplayName] = React.useState(""); + const [openEdit, setOpenEdit] = React.useState(false); + const [openRevoke, setOpenRevoke] = React.useState(false); + const userData = { + username: props.username, + }; - useEffect(() => { - auth.checkDirectoryType(() => { - if(auth.hasAdminScope()){ - axios(configApiCall(api_path_get_admin_devices, 'GET', userData, null)).then((response)=>{ - if(response.data.length == 0) { - setDevices([]); - }else{ - var resultSet = JSON.parse(response.data.replace(/\s+/g, ' ').trim()); - setDevices(resultSet) - } - }).catch((error) =>{ - console.log(error); - if (error.response.status === 401) { - auth.authenticated = false; - history.push("/signin"); - } - }); + useEffect(() => { + auth.checkDirectoryType(() => { + if (auth.hasAdminScope()) { + axios(configApiCall(api_path_get_admin_devices, "GET", userData, null)) + .then((response) => { + if (response.data.length == 0) { + setDevices([]); + } else { + var resultSet = JSON.parse( + response.data.replace(/\s+/g, " ").trim() + ); + setDevices(resultSet); } - else{ - axios(configApiCall(api_path_get_auth_devices, 'GET', null, null)).then((response)=>{ - if(response.data.length == 0) { - setDevices([]); - }else{ - var resultSet = JSON.parse(response.data.replace(/\s+/g, ' ').trim()); - setDevices(resultSet) - } - }).catch((error) =>{ - if (error.response.status === 401) { - auth.authenticated = false; - history.push("/signin"); - } - }); + }) + .catch((error) => { + console.log(error); + if (error.response.status === 401) { + auth.authenticated = false; + history.push("/signin"); } - }) - }, [selectedDevice]); - - function getDeviceStatus(device) { - if (!(device.revoked)) { - return 'Active'; - } - else { - return 'Revoked'; + }); + } else { + axios(configApiCall(api_path_get_auth_devices, "GET", null, null)) + .then((response) => { + if (response.data.length == 0) { + setDevices([]); + } else { + var resultSet = JSON.parse( + response.data.replace(/\s+/g, " ").trim() + ); + setDevices(resultSet); + } + }) + .catch((error) => { + if (error.response.status === 401) { + auth.authenticated = false; + history.push("/signin"); + } + }); + } + }); + }, [selectedDevice]); - } + function getDeviceStatus(device) { + if (!device.revoked) { + return "Active"; + } else { + return "Revoked"; } + } - function getDeviceId(device) { - return device.deviceId; - } + function getDeviceId(device) { + return device.deviceId; + } - const handleClickEdit = (e, device) => { - e.preventDefault(); - setOpenEdit(true); - setSelectedDevice(device); - } + const handleClickEdit = (e, device) => { + e.preventDefault(); + setOpenEdit(true); + setSelectedDevice(device); + }; - const handleClickRevoke = (e, device) => { - e.preventDefault(); - setOpenRevoke(true); - setSelectedDevice(device); - } + const handleClickRevoke = (e, device) => { + e.preventDefault(); + setOpenRevoke(true); + setSelectedDevice(device); + }; - const handleClose = () => { - setOpenEdit(false); - setOpenRevoke(false); - setSelectedDevice({}); - } - const handleCancel = () => { - setOpenEdit(false); - setOpenRevoke(false); - setSelectedDevice({}); - } + const handleClose = () => { + setOpenEdit(false); + setOpenRevoke(false); + setSelectedDevice({}); + }; + const handleCancel = () => { + setOpenEdit(false); + setOpenRevoke(false); + setSelectedDevice({}); + }; - const handleUpdate = () => { - if(auth.hasAdminScope()){ - const data = { - username: props.username, - deviceId: selectedDevice.deviceId, - deviceName: displayName - } - axios(configApiCall(api_path_delete_admin_device_revoke+"?username="+ data.username+"&deviceId="+data.deviceId+"&deviceName="+data.deviceName, 'PUT', null, null)).then((response)=>{ - setSelectedDevice({}); - setOpenEdit(false); - } - ).catch((error) =>{ - console.log(error); - }); - } - else{ - const data = { - deviceName: displayName - } - axios(configApiCall(api_path_rename_device+"/"+selectedDevice.deviceId+ "?deviceName="+ data.deviceName, 'PUT', null, null)).then((response)=>{ - setSelectedDevice({}); - setOpenEdit(false); - } - ).catch((error) =>{ - console.log(error); - }); - } + const handleUpdate = () => { + if (auth.hasAdminScope()) { + const data = { + username: props.username, + deviceId: selectedDevice.deviceId, + deviceName: displayName, + }; + axios( + configApiCall( + api_path_delete_admin_device_revoke + + "?username=" + + data.username + + "&deviceId=" + + data.deviceId + + "&deviceName=" + + data.deviceName, + "PUT", + null, + null + ) + ) + .then((response) => { + setSelectedDevice({}); + setOpenEdit(false); + }) + .catch((error) => { + console.log(error); + }); + } else { + const data = { + deviceName: displayName, + }; + axios( + configApiCall( + api_path_rename_device + + "/" + + selectedDevice.deviceId + + "?deviceName=" + + data.deviceName, + "PUT", + null, + null + ) + ) + .then((response) => { + setSelectedDevice({}); + setOpenEdit(false); + }) + .catch((error) => { + console.log(error); + }); } + }; - const handleDeviceRevoke = () => { - if(auth.hasAdminScope()){ - const data = { - username: props.username, - deviceId: selectedDevice.deviceId, - } - axios(configApiCall(api_path_delete_admin_device_revoke+"?username="+ data.username+"&deviceId="+data.deviceId, 'DELETE', null, null)).then((response)=>{ - setSelectedDevice({}); - setOpenRevoke(false); - } - ).catch((error) =>{ - console.log(error); - }); - } - else{ - - axios(configApiCall(api_path_delete_auth_device_revoke+"/"+selectedDevice.deviceId, 'DELETE', null, null)).then((response)=>{ - setSelectedDevice({}); - setOpenRevoke(false); - } - ).catch((error) =>{ - console.log(error); - }); - } + const handleDeviceRevoke = () => { + if (auth.hasAdminScope()) { + const data = { + username: props.username, + deviceId: selectedDevice.deviceId, + }; + axios( + configApiCall( + api_path_delete_admin_device_revoke + + "?username=" + + data.username + + "&deviceId=" + + data.deviceId, + "DELETE", + null, + null + ) + ) + .then((response) => { + setSelectedDevice({}); + setOpenRevoke(false); + }) + .catch((error) => { + console.log(error); + }); + } else { + axios( + configApiCall( + api_path_delete_auth_device_revoke + "/" + selectedDevice.deviceId, + "DELETE", + null, + null + ) + ) + .then((response) => { + setSelectedDevice({}); + setOpenRevoke(false); + }) + .catch((error) => { + console.log(error); + }); } + }; - /** - * Formik Validation - */ - const validateDisplayName = displaynamevalue => { - let error; - if (!displaynamevalue) { - error = 'Required'; - } - return error; + /** + * Formik Validation + */ + const validateDisplayName = (displaynamevalue) => { + let error; + if (!displaynamevalue) { + error = "Required"; } + return error; + }; - const tableCellClasses = classnames(classes.tableCell); - return ( - <div> - <Table className={classes.table}> - <TableHead> - <TableRow> - <TableCell>{i18next.t("device_name", "Device Name")}</TableCell> - <TableCell>{i18next.t("device_id", "Device Id")}</TableCell> - <TableCell align="right">{i18next.t("status", "Status")}</TableCell> - <TableCell align="right">{i18next.t("actions", "Actions")}</TableCell> - </TableRow> - </TableHead> - {devices != null && - <TableBody> - {devices.map(device => - <TableRow key={device.displayName} className={classes.tableRow}> - <TableCell className={tableCellClasses}> - {device.displayName} - </TableCell> - <TableCell className={tableCellClasses}>{getDeviceId(device)}</TableCell> - <TableCell align="right" className={tableCellClasses}>{getDeviceStatus(device)}</TableCell> - {!(device.revoked) && - <TableCell align="right" className={classes.tableActions}> - <Tooltip - id="tooltip-top" - title="Edit Device" - placement="top" - classes={{ tooltip: classes.tooltip }} - > - <IconButton - aria-label="Edit" - className={classes.tableActionButton} - onClick={e =>handleClickEdit(e, device)} - > - <Edit - className={ - classes.tableActionButtonIcon + " " + classes.edit - } - /> - </IconButton> - </Tooltip> - <Tooltip - id="tooltip-top-start" - title={i18next.t("revoke_device", "Revoke Device")} - placement="top" - classes={{ tooltip: classes.tooltip }} - > - <IconButton - aria-label="Close" - className={classes.tableActionButton} - onClick={e => handleClickRevoke(e,device)} - > - <Close - className={ - classes.tableActionButtonIcon + " " + classes.close - } - /> - </IconButton> - </Tooltip> - </TableCell> - } - </TableRow> - )} - </TableBody>} - </Table> - <Dialog open={openEdit} onClose={handleClose} aria-labelledby="form-dialog-title"> - <DialogTitle id="form-edit-dialog-title">{i18next.t("update_device_information", "Update Device Information")}</DialogTitle> - <Formik initialValues={{ - displayName: selectedDevice.displayName, - }} + const tableCellClasses = classnames(classes.tableCell); + return ( + <div> + <Table className={classes.table}> + <TableHead> + <TableRow> + <TableCell>{i18next.t("device_name", "Device Name")}</TableCell> + <TableCell>{i18next.t("device_id", "Device Id")}</TableCell> + <TableCell align="right">{i18next.t("status", "Status")}</TableCell> + <TableCell align="right"> + {i18next.t("actions", "Actions")} + </TableCell> + </TableRow> + </TableHead> + {devices != null && ( + <TableBody> + {devices.map((device) => ( + <TableRow key={device.displayName} className={classes.tableRow}> + <TableCell className={tableCellClasses}> + {device.displayName} + </TableCell> + <TableCell className={tableCellClasses}> + {getDeviceId(device)} + </TableCell> + <TableCell align="right" className={tableCellClasses}> + {getDeviceStatus(device)} + </TableCell> + {!device.revoked && ( + <TableCell align="right" className={classes.tableActions}> + <Tooltip + id="tooltip-top" + title="Edit Device" + placement="top" + classes={{ tooltip: classes.tooltip }} + > + <IconButton + aria-label="Edit" + className={classes.tableActionButton} + onClick={(e) => handleClickEdit(e, device)} + > + <Edit + className={ + classes.tableActionButtonIcon + " " + classes.edit + } + /> + </IconButton> + </Tooltip> + <Tooltip + id="tooltip-top-start" + title={i18next.t("revoke_device", "Revoke Device")} + placement="top" + classes={{ tooltip: classes.tooltip }} + > + <IconButton + aria-label="Close" + className={classes.tableActionButton} + onClick={(e) => handleClickRevoke(e, device)} + > + <Close + className={ + classes.tableActionButtonIcon + " " + classes.close + } + /> + </IconButton> + </Tooltip> + </TableCell> + )} + </TableRow> + ))} + </TableBody> + )} + </Table> + <Dialog + open={openEdit} + onClose={handleClose} + aria-labelledby="form-dialog-title" + > + <DialogTitle id="form-edit-dialog-title"> + {i18next.t("update_device_information", "Update Device Information")} + </DialogTitle> + <Formik + initialValues={{ + displayName: selectedDevice.displayName, + }} + > + {({ errors, touched, validateField }) => ( + <form> + <DialogContent> + <Field name="displayName" validate={validateDisplayName}> + {({ field }) => ( + <div> + <TextField + autoFocus + margin="dense" + id="name" + label={i18next.t( + "device_display_name", + "Device Display Name" + )} + fullWidth + onChange={setDisplayName(field.value)} + helperText={ + errors.displayName && + touched.displayName && + errors.displayName + } + {...field} + /> + </div> + )} + </Field> + </DialogContent> + <DialogActions> + <Button onClick={handleCancel} color="primary"> + {i18next.t("cancel", "Cancel")} + </Button> + <Button + onClick={() => + validateField("displayName").then(() => handleUpdate()) + } + color="primary" > - {({ errors, touched, validateField}) => ( - <form> - <DialogContent> - <Field name="displayName" validate={validateDisplayName} > - {({field}) => ( - <div> - <TextField - autoFocus - margin="dense" - id="name" - label={i18next.t("device_display_name", "Device Display Name")} - fullWidth - onChange={setDisplayName(field.value)} - helperText={(errors.displayName && touched.displayName) && errors.displayName} - {...field} - /> - </div> - ) - } - </Field> - </DialogContent> - <DialogActions> - <Button onClick={handleCancel} color="primary"> - {i18next.t("cancel", "Cancel")} - </Button> - <Button onClick={() => validateField('displayName').then(() =>handleUpdate())} color="primary"> - {i18next.t("update", "Update")} - </Button> - </DialogActions> - </form> - )} - </Formik> - </Dialog> - <Dialog open={openRevoke} onClose={handleClose} aria-labelledby="form-dialog-title"> - <DialogTitle id="form-revoke-dialog-title">{i18next.t("revoke_device", "Revoke Device")}</DialogTitle> - <DialogContent> - <DialogContentText> - {i18next.t("are_you_sure_you_want_to_revoke_this_device", "Are you sure you want to revoke this device?")} - </DialogContentText> - </DialogContent> - <DialogActions> - <Button onClick={handleCancel} color="primary"> - {i18next.t("cancel", "Cancel")} - </Button> - <Button onClick={handleDeviceRevoke} color="primary"> - {i18next.t("confirm_revoke", "Confirm Revoke")} - </Button> - </DialogActions> - </Dialog> - </div> - ); + {i18next.t("update", "Update")} + </Button> + </DialogActions> + </form> + )} + </Formik> + </Dialog> + <Dialog + open={openRevoke} + onClose={handleClose} + aria-labelledby="form-dialog-title" + > + <DialogTitle id="form-revoke-dialog-title"> + {i18next.t("revoke_device", "Revoke Device")} + </DialogTitle> + <DialogContent> + <DialogContentText> + {i18next.t( + "are_you_sure_you_want_to_revoke_this_device", + "Are you sure you want to revoke this device?" + )} + </DialogContentText> + </DialogContent> + <DialogActions> + <Button onClick={handleCancel} color="primary"> + {i18next.t("cancel", "Cancel")} + </Button> + <Button onClick={handleDeviceRevoke} color="primary"> + {i18next.t("confirm_revoke", "Confirm Revoke")} + </Button> + </DialogActions> + </Dialog> + </div> + ); } - diff --git a/jams-react-client/src/components/Drawer/Drawer.js b/jams-react-client/src/components/Drawer/Drawer.js index ea35a6dc..f0747706 100644 --- a/jams-react-client/src/components/Drawer/Drawer.js +++ b/jams-react-client/src/components/Drawer/Drawer.js @@ -18,13 +18,13 @@ const useStyles = makeStyles((theme) => ({ width: "100%", [theme.breakpoints.up("xl")]: { width: "400px", - } + }, }, fullList: { width: "100%", [theme.breakpoints.up("xl")]: { width: "400px", - } + }, }, search: { width: "100%", @@ -38,54 +38,66 @@ const useStyles = makeStyles((theme) => ({ export default function TemporaryDrawer(props) { const classes = useStyles(); - useEffect(() => { - }, []); - + useEffect(() => {}, []); const listUsers = () => ( <List> - {props.type === "user" ? ( props.targets && props.targets.filter((target) => !props.existingTargets.some(t => target.username == t.username)).map((target) => ( - <ListItem - button - key={target.username} - onClick={() => { - props.addElementToTarget(target); - props.setOpenDrawer(false); - }} - > - <Avatar - style={{ marginRight: "10px" }} - alt={target.username} - src={ - target.profilePicture - ? "data:image/png;base64, " + target.profilePicture - : noProfilePicture - } - /> - <ListItemText - primary={ - target.username === "" - ? target.id - : target.firstName === "" || target.lastName === "" - ? target.username - : target.firstName + " " + target.lastName - } - /> - </ListItem> - ))) : ( props.targets && props.targets.filter((target) => !props.existingTargets.some(t => target.name == t.name)).map((target) => ( - <ListItem - button - key={target.name} - onClick={() => { - props.addElementToTarget(target); - props.setOpenDrawer(false); - }} - > - <ListItemText - primary={target.name} - /> - </ListItem> - )))} + {props.type === "user" + ? props.targets && + props.targets + .filter( + (target) => + !props.existingTargets.some( + (t) => target.username == t.username + ) + ) + .map((target) => ( + <ListItem + button + key={target.username} + onClick={() => { + props.addElementToTarget(target); + props.setOpenDrawer(false); + }} + > + <Avatar + style={{ marginRight: "10px" }} + alt={target.username} + src={ + target.profilePicture + ? "data:image/png;base64, " + target.profilePicture + : noProfilePicture + } + /> + <ListItemText + primary={ + target.username === "" + ? target.id + : target.firstName === "" || target.lastName === "" + ? target.username + : target.firstName + " " + target.lastName + } + /> + </ListItem> + )) + : props.targets && + props.targets + .filter( + (target) => + !props.existingTargets.some((t) => target.name == t.name) + ) + .map((target) => ( + <ListItem + button + key={target.name} + onClick={() => { + props.addElementToTarget(target); + props.setOpenDrawer(false); + }} + > + <ListItemText primary={target.name} /> + </ListItem> + ))} </List> ); @@ -111,7 +123,8 @@ export default function TemporaryDrawer(props) { > <div className={clsx(classes.list, { - [classes.fullList]: props.direction === "top" || props.direction === "bottom", + [classes.fullList]: + props.direction === "top" || props.direction === "bottom", })} role="presentation" > diff --git a/jams-react-client/src/components/FixedPlugin/FixedPlugin.js b/jams-react-client/src/components/FixedPlugin/FixedPlugin.js index 98984412..dea5626d 100644 --- a/jams-react-client/src/components/FixedPlugin/FixedPlugin.js +++ b/jams-react-client/src/components/FixedPlugin/FixedPlugin.js @@ -22,7 +22,7 @@ export default function FixedPlugin(props) { return ( <div className={classnames("fixed-plugin", { - "rtl-fixed-plugin": props.rtlActive + "rtl-fixed-plugin": props.rtlActive, })} > <div id="fixedPluginClasses" className={props.fixedClasses}> @@ -186,5 +186,5 @@ FixedPlugin.propTypes = { fixedClasses: PropTypes.string, bgColor: PropTypes.oneOf(["purple", "blue", "green", "orange", "red"]), handleColorClick: PropTypes.func, - handleImageClick: PropTypes.func + handleImageClick: PropTypes.func, }; diff --git a/jams-react-client/src/components/Footer/Footer.js b/jams-react-client/src/components/Footer/Footer.js index 1387e46b..8dc03ebc 100755 --- a/jams-react-client/src/components/Footer/Footer.js +++ b/jams-react-client/src/components/Footer/Footer.js @@ -8,7 +8,7 @@ import List from "@material-ui/core/List"; // core components import styles from "assets/jss/material-dashboard-react/components/footerStyle.js"; -const pjson = require('../../../package.json'); +const pjson = require("../../../package.json"); const useStyles = makeStyles(styles); @@ -19,8 +19,8 @@ export default function Footer(props) { <div className={classes.container}> <p className={classes.right}> <span> - JAMS Version {pjson.version.slice(0, 3)} - - © {1900 + new Date().getYear()}{" "} + JAMS Version {pjson.version.slice(0, 3)} - ©{" "} + {1900 + new Date().getYear()}{" "} <a href="https://savoirfairelinux.com" target="_blank" diff --git a/jams-react-client/src/components/Grid/GridContainer.js b/jams-react-client/src/components/Grid/GridContainer.js index 635a2a95..e4f81135 100644 --- a/jams-react-client/src/components/Grid/GridContainer.js +++ b/jams-react-client/src/components/Grid/GridContainer.js @@ -7,8 +7,8 @@ import Grid from "@material-ui/core/Grid"; const styles = { grid: { - // margin: "0 -15px !important", - width: "unset", + // margin: "0 -15px !important", + width: "unset", }, }; diff --git a/jams-react-client/src/components/Grid/GridItem.js b/jams-react-client/src/components/Grid/GridItem.js index f7a82de0..bb74c2a2 100644 --- a/jams-react-client/src/components/Grid/GridItem.js +++ b/jams-react-client/src/components/Grid/GridItem.js @@ -8,7 +8,7 @@ import Grid from "@material-ui/core/Grid"; const styles = { grid: { padding: "0 5px !important", - } + }, }; const useStyles = makeStyles(styles); @@ -24,5 +24,5 @@ export default function GridItem(props) { } GridItem.propTypes = { - children: PropTypes.node + children: PropTypes.node, }; diff --git a/jams-react-client/src/components/IdentityManagement/AdStorageForm.js b/jams-react-client/src/components/IdentityManagement/AdStorageForm.js index 877fd3cd..2880ea1f 100644 --- a/jams-react-client/src/components/IdentityManagement/AdStorageForm.js +++ b/jams-react-client/src/components/IdentityManagement/AdStorageForm.js @@ -7,14 +7,17 @@ import TextField from "@material-ui/core/TextField"; import Radio from "@material-ui/core/Radio"; import RadioGroup from "@material-ui/core/RadioGroup"; -import i18next from 'i18next'; +import i18next from "i18next"; export default function AdStorageForm(props) { return ( <Grid container spacing={3}> <Grid item xs={12}> <Typography variant="subtitle1" gutterBottom color="primary"> - {i18next.t("active_directory_server_informations", "Active Directory server information")} + {i18next.t( + "active_directory_server_informations", + "Active Directory server information" + )} </Typography> </Grid> <Grid item xs={6}> diff --git a/jams-react-client/src/components/IdentityManagement/IdentityManagement.js b/jams-react-client/src/components/IdentityManagement/IdentityManagement.js index 71451215..48d54d25 100644 --- a/jams-react-client/src/components/IdentityManagement/IdentityManagement.js +++ b/jams-react-client/src/components/IdentityManagement/IdentityManagement.js @@ -20,7 +20,7 @@ import AdStorageForm from "./AdStorageForm"; import auth from "../../auth"; import * as Yup from "yup"; -import i18next from 'i18next'; +import i18next from "i18next"; const useStyles = makeStyles((theme) => ({ paper: { @@ -63,10 +63,18 @@ export default function IdentityManagement(props) { }; const validationSchemaLDAPform = Yup.object().shape({ - servername: Yup.string().required(i18next.t("servername_is_required", "Server name is required.")), - ldapadminusername: Yup.string().required(i18next.t("username_is_required", "Username is required!")), - ldappassword: Yup.string().required(i18next.t("password_is_required", "Password is required!")), - basedn: Yup.string().required(i18next.t("domain_name_is_required", "Domain name is required.")), + servername: Yup.string().required( + i18next.t("servername_is_required", "Server name is required.") + ), + ldapadminusername: Yup.string().required( + i18next.t("username_is_required", "Username is required!") + ), + ldappassword: Yup.string().required( + i18next.t("password_is_required", "Password is required!") + ), + basedn: Yup.string().required( + i18next.t("domain_name_is_required", "Domain name is required.") + ), }); const validationSchemaADform = Yup.object().shape({ @@ -74,11 +82,21 @@ export default function IdentityManagement(props) { .typeError(i18next.t("port_must_be_a_number", "Port must be a number.")) .positive(i18next.t("port_must_be_positive", "Port must be positive.")) .integer(i18next.t("port_must_be_an_integer", "Port must be an integer.")) - .required(i18next.t("port_number_is_required", "Port number is required.")), - host: Yup.string().required(i18next.t("host_is_required", "Host is required.")), - adadminusername: Yup.string().required(i18next.t("username_is_required", "Username is required!")), - domainname: Yup.string().required(i18next.t("domain_name_is_required", "Domain name is required.")), - adpassword: Yup.string().required(i18next.t("password_is_required", "Password is required!")), + .required( + i18next.t("port_number_is_required", "Port number is required.") + ), + host: Yup.string().required( + i18next.t("host_is_required", "Host is required.") + ), + adadminusername: Yup.string().required( + i18next.t("username_is_required", "Username is required!") + ), + domainname: Yup.string().required( + i18next.t("domain_name_is_required", "Domain name is required.") + ), + adpassword: Yup.string().required( + i18next.t("password_is_required", "Password is required!") + ), }); const directoryTypes = [ @@ -221,7 +239,10 @@ export default function IdentityManagement(props) { }) .catch(() => { props.setErrorMessage( - i18next.t("information_appears_incorrect_connection_directory_failed", "The information provided appears to be incorrect, the connection to the directory has failed. Please check the information and credentials provided and try again.") + i18next.t( + "information_appears_incorrect_connection_directory_failed", + "The information provided appears to be incorrect, the connection to the directory has failed. Please check the information and credentials provided and try again." + ) ); props.setError(true); }); @@ -237,7 +258,10 @@ export default function IdentityManagement(props) { }) .catch(() => { props.setErrorMessage( - i18next.t("information_appears_incorrect_connection_directory_failed", "The information provided appears to be incorrect, the connection to the directory has failed. Please check the information and credentials provided and try again.") + i18next.t( + "information_appears_incorrect_connection_directory_failed", + "The information provided appears to be incorrect, the connection to the directory has failed. Please check the information and credentials provided and try again." + ) ); props.setError(true); }); @@ -283,12 +307,15 @@ export default function IdentityManagement(props) { return ( <form className={classes.form} noValidate onSubmit={handleLocalSubmit}> <Typography variant="h5" gutterBottom color="primary"> - {i18next.t("identity_management", "Identity Management")} + {i18next.t("identity_management", "Identity Management")} </Typography> <Grid container spacing={3}> <Grid item xs={12}> <Typography variant="body1" gutterBottom> - {i18next.t("select_type_of_user_directory", "Select the type of user directory to be integrated with JAMS")} + {i18next.t( + "select_type_of_user_directory", + "Select the type of user directory to be integrated with JAMS" + )} </Typography> <Select labelId="demo-simple-select-label" @@ -341,7 +368,10 @@ export default function IdentityManagement(props) { <Grid container spacing={3}> <Grid item xs={12}> <Typography variant="body1" gutterBottom> - {i18next.t("select_type_of_user_directory", "Select the type of user directory to be integrated with JAMS")} + {i18next.t( + "select_type_of_user_directory", + "Select the type of user directory to be integrated with JAMS" + )} </Typography> <Select labelId="demo-simple-select-label" @@ -361,7 +391,10 @@ export default function IdentityManagement(props) { color="primary" className={classes.submit} > - {i18next.t("set_identity_parameters", "Set identity parameters")} + {i18next.t( + "set_identity_parameters", + "Set identity parameters" + )} </Button> </form> ); @@ -394,7 +427,10 @@ export default function IdentityManagement(props) { <Grid container spacing={3}> <Grid item xs={12}> <Typography variant="body1" gutterBottom> - {i18next.t("select_type_of_user_directory", "Select the type of user directory to be integrated with JAMS")} + {i18next.t( + "select_type_of_user_directory", + "Select the type of user directory to be integrated with JAMS" + )} </Typography> <Select labelId="demo-simple-select-label" @@ -414,7 +450,10 @@ export default function IdentityManagement(props) { color="primary" className={classes.submit} > - {i18next.t("set_identity_parameters", "Set identity parameters")} + {i18next.t( + "set_identity_parameters", + "Set identity parameters" + )} </Button> </form> ); diff --git a/jams-react-client/src/components/IdentityManagement/LdapStorageForm.js b/jams-react-client/src/components/IdentityManagement/LdapStorageForm.js index fbf06bb9..ab6f51be 100644 --- a/jams-react-client/src/components/IdentityManagement/LdapStorageForm.js +++ b/jams-react-client/src/components/IdentityManagement/LdapStorageForm.js @@ -1,106 +1,148 @@ -import React from 'react'; -import FormControlLabel from '@material-ui/core/FormControlLabel'; -import Typography from '@material-ui/core/Typography'; -import Grid from '@material-ui/core/Grid'; +import React from "react"; +import FormControlLabel from "@material-ui/core/FormControlLabel"; +import Typography from "@material-ui/core/Typography"; +import Grid from "@material-ui/core/Grid"; -import TextField from '@material-ui/core/TextField'; -import Radio from '@material-ui/core/Radio'; -import RadioGroup from '@material-ui/core/RadioGroup'; -import Select from '@material-ui/core/Select'; -import CustomPopupState from '../CustomPopupState/CustomPopupState' +import TextField from "@material-ui/core/TextField"; +import Radio from "@material-ui/core/Radio"; +import RadioGroup from "@material-ui/core/RadioGroup"; +import Select from "@material-ui/core/Select"; +import CustomPopupState from "../CustomPopupState/CustomPopupState"; -import i18next from 'i18next'; +import i18next from "i18next"; export default function LdapStorageForm(props) { + return ( + <Grid container spacing={3}> + <Grid item xs={12}> + <Typography variant="subtitle1" gutterBottom color="primary"> + {i18next.t("ldap_server_information", "LDAP Server informations")} + </Typography> + </Grid> + <Grid item xs={12}> + <TextField + variant="outlined" + margin="normal" + required + fullWidth + id="servername" + label={i18next.t("server_address", "Server address")} + name="servername" + autoComplete="servername" + value={props.values.servername} + onChange={props.handleChange} + onBlur={props.handleBlur} + helperText={ + props.errors.servername && + props.touched.servername && + props.errors.servername + } + /> + </Grid> - return ( - <Grid container spacing={3}> - <Grid item xs={12}> - <Typography variant="subtitle1" gutterBottom color="primary">{i18next.t("ldap_server_information", "LDAP Server informations")}</Typography> - </Grid> - <Grid item xs={12}> - <TextField - variant="outlined" - margin="normal" - required - fullWidth - id="servername" - label={i18next.t("server_address", "Server address")} - name="servername" - autoComplete="servername" - value={props.values.servername} - onChange={props.handleChange} - onBlur={props.handleBlur} - helperText={(props.errors.servername && props.touched.servername) && props.errors.servername} - /> - </Grid> - - <Grid item xs={6}> - <TextField - variant="outlined" - margin="normal" - required - fullWidth - id="adminusername" - label={i18next.t("administrator_username", "Administrator username")} - name="ldapadminusername" - autoComplete="adminusername" - value={props.values.ldapadminusername} - onChange={props.handleChange} - onBlur={props.handleBlur} - helperText={(props.errors.ldapadminusername && props.touched.ldapadminusername) && props.errors.ldapadminusername} - /> - </Grid> - <Grid item xs={6}> - <TextField - variant="outlined" - margin="normal" - required - fullWidth - id="password" - label={i18next.t("password", "Password")} - name="ldappassword" - autoComplete="password" - type="password" - value={props.values.ldappassword} - onChange={props.handleChange} - onBlur={props.handleBlur} - helperText={(props.errors.ldappassword && props.touched.ldappassword) && props.errors.ldappassword} - /> - </Grid> - <Grid item xs={12}> - <TextField - variant="outlined" - id="basedn" - label={i18next.t("base_dn_please_use_ldap_convention", "Base DN (Please use LDAP convention)")} - name="basedn" - autoComplete="basedn" - required - fullWidth - value={props.values.basedn} - onChange={props.handleChange} - onBlur={props.handleBlur} - helperText={(props.errors.basedn && props.touched.basedn) && props.errors.basedn} - /> - </Grid> - <Grid item xs={12}> - <Typography variant="subtitle1" gutterBottom color="primary">Use Start TLS</Typography> - <RadioGroup row aria-label="useStartTLS" name="useStartTLS" value={props.useStartTLS} onChange={props.handleUseStartTLSChange} > - <FormControlLabel value="true" control={<Radio color="primary"/>} label={i18next.t("yes", "Yes")} /> - <FormControlLabel value="false" control={<Radio color="default"/>} label={i18next.t("no", "No")} /> - </RadioGroup> - </Grid> - <Grid item xs={12}> - <Typography variant="subtitle1" gutterBottom color="primary">Filter<CustomPopupState message={i18next.t("field_ldap_structure_contains_username", "This is the field in your LDAP structure which contains the username.")}/></Typography> - <Select - labelId="filter-ldap-select" - fullWidth - value={props.ldapFilter.value} - onChange={props.handleFilterIdChange} - variant="outlined" - children={props.ldapFiltersTypesItems} - /> - </Grid> - </Grid> - ); -} \ No newline at end of file + <Grid item xs={6}> + <TextField + variant="outlined" + margin="normal" + required + fullWidth + id="adminusername" + label={i18next.t("administrator_username", "Administrator username")} + name="ldapadminusername" + autoComplete="adminusername" + value={props.values.ldapadminusername} + onChange={props.handleChange} + onBlur={props.handleBlur} + helperText={ + props.errors.ldapadminusername && + props.touched.ldapadminusername && + props.errors.ldapadminusername + } + /> + </Grid> + <Grid item xs={6}> + <TextField + variant="outlined" + margin="normal" + required + fullWidth + id="password" + label={i18next.t("password", "Password")} + name="ldappassword" + autoComplete="password" + type="password" + value={props.values.ldappassword} + onChange={props.handleChange} + onBlur={props.handleBlur} + helperText={ + props.errors.ldappassword && + props.touched.ldappassword && + props.errors.ldappassword + } + /> + </Grid> + <Grid item xs={12}> + <TextField + variant="outlined" + id="basedn" + label={i18next.t( + "base_dn_please_use_ldap_convention", + "Base DN (Please use LDAP convention)" + )} + name="basedn" + autoComplete="basedn" + required + fullWidth + value={props.values.basedn} + onChange={props.handleChange} + onBlur={props.handleBlur} + helperText={ + props.errors.basedn && props.touched.basedn && props.errors.basedn + } + /> + </Grid> + <Grid item xs={12}> + <Typography variant="subtitle1" gutterBottom color="primary"> + Use Start TLS + </Typography> + <RadioGroup + row + aria-label="useStartTLS" + name="useStartTLS" + value={props.useStartTLS} + onChange={props.handleUseStartTLSChange} + > + <FormControlLabel + value="true" + control={<Radio color="primary" />} + label={i18next.t("yes", "Yes")} + /> + <FormControlLabel + value="false" + control={<Radio color="default" />} + label={i18next.t("no", "No")} + /> + </RadioGroup> + </Grid> + <Grid item xs={12}> + <Typography variant="subtitle1" gutterBottom color="primary"> + Filter + <CustomPopupState + message={i18next.t( + "field_ldap_structure_contains_username", + "This is the field in your LDAP structure which contains the username." + )} + /> + </Typography> + <Select + labelId="filter-ldap-select" + fullWidth + value={props.ldapFilter.value} + onChange={props.handleFilterIdChange} + variant="outlined" + children={props.ldapFiltersTypesItems} + /> + </Grid> + </Grid> + ); +} diff --git a/jams-react-client/src/components/IdentityManagement/LocalStorageForm.js b/jams-react-client/src/components/IdentityManagement/LocalStorageForm.js index c827f3a3..1fd17ff0 100644 --- a/jams-react-client/src/components/IdentityManagement/LocalStorageForm.js +++ b/jams-react-client/src/components/IdentityManagement/LocalStorageForm.js @@ -1,33 +1,39 @@ -import React from 'react'; -import FormControlLabel from '@material-ui/core/FormControlLabel'; -import Checkbox from '@material-ui/core/Checkbox'; -import Typography from '@material-ui/core/Typography'; -import Grid from '@material-ui/core/Grid'; -import CustomPopupState from '../CustomPopupState/CustomPopupState' +import React from "react"; +import FormControlLabel from "@material-ui/core/FormControlLabel"; +import Checkbox from "@material-ui/core/Checkbox"; +import Typography from "@material-ui/core/Typography"; +import Grid from "@material-ui/core/Grid"; +import CustomPopupState from "../CustomPopupState/CustomPopupState"; -import i18next from 'i18next'; +import i18next from "i18next"; export default function LocalStorageForm(props) { - - return ( - <Grid container spacing={3}> - <Grid item xs={12}> - <Typography variant="subtitle1" gutterBottom color="primary">{i18next.t("advanced_settings", "Advanced settings")}</Typography> - </Grid> - <Grid item xs={12}> - <FormControlLabel - control={ - <Checkbox - checked={props.nameServerChecked} - onChange={props.handleNameServerChange} - inputProps={{ 'aria-label': 'primary checkbox' }} - color="primary" - /> - } - label={i18next.t("use_public_nameserver", "Use public nameserver")} - /> - <CustomPopupState message={i18next.t("check_box_register_usernames_on_jami_public_nameserver", "Check this box if you want to register your usernames on Jami's public name server.")}/> - </Grid> - </Grid> - ); -} \ No newline at end of file + return ( + <Grid container spacing={3}> + <Grid item xs={12}> + <Typography variant="subtitle1" gutterBottom color="primary"> + {i18next.t("advanced_settings", "Advanced settings")} + </Typography> + </Grid> + <Grid item xs={12}> + <FormControlLabel + control={ + <Checkbox + checked={props.nameServerChecked} + onChange={props.handleNameServerChange} + inputProps={{ "aria-label": "primary checkbox" }} + color="primary" + /> + } + label={i18next.t("use_public_nameserver", "Use public nameserver")} + /> + <CustomPopupState + message={i18next.t( + "check_box_register_usernames_on_jami_public_nameserver", + "Check this box if you want to register your usernames on Jami's public name server." + )} + /> + </Grid> + </Grid> + ); +} diff --git a/jams-react-client/src/components/LanguagePicker/LanguagePicker.js b/jams-react-client/src/components/LanguagePicker/LanguagePicker.js index 107b77c6..a86d5427 100644 --- a/jams-react-client/src/components/LanguagePicker/LanguagePicker.js +++ b/jams-react-client/src/components/LanguagePicker/LanguagePicker.js @@ -12,44 +12,46 @@ import { useTranslation } from "react-i18next"; export default function LanguagePicker(props) { const history = useHistory(); - const [language, setLanguage] = React.useState(i18next.language || window.localStorage.i18nextLng || "en"); + const [language, setLanguage] = React.useState( + i18next.language || window.localStorage.i18nextLng || "en" + ); const [languages, setLanguages] = React.useState([]); const { i18n } = useTranslation(); const handleChange = (value) => { setLanguage(value); - i18n.changeLanguage(value).then(()=>{ + i18n.changeLanguage(value).then(() => { history.push(props.navigationTarget); - }) + }); }; useEffect(() => { - fetch("/available_languages.json").then(res => res.json()).then((result) => { - const response = result.languages; - let translates_languages = [{ "code": "en", "name": "English"}]; - - response.forEach((lang) => - { - if(result.stats[lang.code]["translated"]["percentage"] > 0.01){ - translates_languages.push(lang); - } - }) + fetch("/available_languages.json") + .then((res) => res.json()) + .then((result) => { + const response = result.languages; + let translates_languages = [{ code: "en", name: "English" }]; - let exists = false; - translates_languages.map((option) => { - if (option.code === language) { - exists = true; - } - }) - if (!exists ) { - setLanguage("en"); - i18n.changeLanguage("en"); - } - setLanguages(translates_languages) - }) + response.forEach((lang) => { + if (result.stats[lang.code]["translated"]["percentage"] > 0.01) { + translates_languages.push(lang); + } + }); - }, [language]) + let exists = false; + translates_languages.map((option) => { + if (option.code === language) { + exists = true; + } + }); + if (!exists) { + setLanguage("en"); + i18n.changeLanguage("en"); + } + setLanguages(translates_languages); + }); + }, [language]); return ( <PopupState variant="popover" popupId="demo-popup-menu"> diff --git a/jams-react-client/src/components/Navbars/AdminNavbarLinks.js b/jams-react-client/src/components/Navbars/AdminNavbarLinks.js index ef329b0a..f3cc665f 100644 --- a/jams-react-client/src/components/Navbars/AdminNavbarLinks.js +++ b/jams-react-client/src/components/Navbars/AdminNavbarLinks.js @@ -24,7 +24,7 @@ export default function AdminNavbarLinks(props) { const classes = useStyles(); const [openProfile, setOpenProfile] = React.useState(null); - const handleClickProfile = event => { + const handleClickProfile = (event) => { if (openProfile && openProfile.contains(event.target)) { setOpenProfile(null); } else { @@ -34,7 +34,7 @@ export default function AdminNavbarLinks(props) { const handleOtherAction = () => { // Do nothing - } + }; return ( <div> @@ -70,7 +70,7 @@ export default function AdminNavbarLinks(props) { id="profile-menu-list-grow" style={{ transformOrigin: - placement === "bottom" ? "center top" : "center bottom" + placement === "bottom" ? "center top" : "center bottom", }} > <Paper> diff --git a/jams-react-client/src/components/Navbars/Navbar.js b/jams-react-client/src/components/Navbars/Navbar.js index fd31db21..7e66562c 100755 --- a/jams-react-client/src/components/Navbars/Navbar.js +++ b/jams-react-client/src/components/Navbars/Navbar.js @@ -20,14 +20,17 @@ export default function Header(props) { const classes = useStyles(); const { color } = props; const appBarClasses = classNames({ - [" " + classes[color]]: color + [" " + classes[color]]: color, }); return ( <AppBar className={classes.appBar + appBarClasses}> <Toolbar className={classes.container}> <div className={classes.flex}> - <Button color="transparent" href="#" className={classes.title}> - </Button> + <Button + color="transparent" + href="#" + className={classes.title} + ></Button> </div> <Hidden mdUp implementation="css"> <IconButton @@ -47,5 +50,5 @@ Header.propTypes = { color: PropTypes.oneOf(["primary", "info", "success", "warning", "danger"]), rtlActive: PropTypes.bool, handleDrawerToggle: PropTypes.func, - routes: PropTypes.arrayOf(PropTypes.object) + routes: PropTypes.arrayOf(PropTypes.object), }; diff --git a/jams-react-client/src/components/Navbars/RTLNavbarLinks.js b/jams-react-client/src/components/Navbars/RTLNavbarLinks.js index d2eb4274..93b3f5ee 100644 --- a/jams-react-client/src/components/Navbars/RTLNavbarLinks.js +++ b/jams-react-client/src/components/Navbars/RTLNavbarLinks.js @@ -25,7 +25,7 @@ const useStyles = makeStyles(styles); export default function RTLNavbarLinks() { const classes = useStyles(); const [open, setOpen] = React.useState(null); - const handleToggle = event => { + const handleToggle = (event) => { if (open && open.contains(event.target)) { setOpen(null); } else { @@ -42,13 +42,13 @@ export default function RTLNavbarLinks() { <div className={classes.searchWrapper}> <CustomInput formControlProps={{ - className: classes.margin + " " + classes.search + className: classes.margin + " " + classes.search, }} inputProps={{ placeholder: "جستجو...", inputProps: { - "aria-label": "Search" - } + "aria-label": "Search", + }, }} /> <Button color="white" aria-label="edit" justIcon round> @@ -102,7 +102,7 @@ export default function RTLNavbarLinks() { id="menu-list-grow" style={{ transformOrigin: - placement === "bottom" ? "center top" : "center bottom" + placement === "bottom" ? "center top" : "center bottom", }} > <Paper> diff --git a/jams-react-client/src/components/PasswordDialog/PasswordDialog.js b/jams-react-client/src/components/PasswordDialog/PasswordDialog.js index 1b80b857..f3053003 100644 --- a/jams-react-client/src/components/PasswordDialog/PasswordDialog.js +++ b/jams-react-client/src/components/PasswordDialog/PasswordDialog.js @@ -46,7 +46,7 @@ const styles = (theme) => ({ }, whiteButtonText: { color: "white", - } + }, }); const useStyles = makeStyles(styles); diff --git a/jams-react-client/src/components/ServerParameters/ServerParameters.js b/jams-react-client/src/components/ServerParameters/ServerParameters.js index 16efbb7f..4fe0c7af 100644 --- a/jams-react-client/src/components/ServerParameters/ServerParameters.js +++ b/jams-react-client/src/components/ServerParameters/ServerParameters.js @@ -18,7 +18,7 @@ import { api_path_post_install_server } from "../../globalUrls"; import auth from "auth"; import * as Yup from "yup"; -import i18next from 'i18next'; +import i18next from "i18next"; const useStyles = makeStyles((theme) => ({ paper: { @@ -44,7 +44,9 @@ export default function ServerParameters(props) { // Formik validation fields const initialValues = { domain: window.location.origin }; const validationSchema = Yup.object().shape({ - domain: Yup.string().required(i18next.t("domain_is_required", "Domain is required.")), + domain: Yup.string().required( + i18next.t("domain_is_required", "Domain is required.") + ), }); const certificateRevocationTypes = [ @@ -107,40 +109,45 @@ export default function ServerParameters(props) { auth.installed = true; auth.authenticated = true; auth.admin = true; - window.localStorage.setItem('scope', 'true'); + window.localStorage.setItem("scope", "true"); auth.checkDirectoryType(() => { history.push("/users"); }); } function handleSubmit(values) { - let jsonData = {}; - let re = new RegExp(/^http[s]?:\/\/\w+(\.\w+)*(:[0-9]+)?\/?(\/[.\w]*)*$/); - let nohttpre = new RegExp(/^\w+(\.\w+)*(:[0-9]+)?\/?(\/[.\w]*)*$/); + let jsonData = {}; + let re = new RegExp(/^http[s]?:\/\/\w+(\.\w+)*(:[0-9]+)?\/?(\/[.\w]*)*$/); + let nohttpre = new RegExp(/^\w+(\.\w+)*(:[0-9]+)?\/?(\/[.\w]*)*$/); - if (values.domain.match(nohttpre)) - values.domain = (window.location.protocol) + "//" + values.domain; + if (values.domain.match(nohttpre)) + values.domain = window.location.protocol + "//" + values.domain; - if (values.domain.match(re)) { - jsonData = { - serverDomain: values.domain, - crlLifetime: certificateRevocation.value, - deviceLifetime: deviceLifetime.value, - userLifetime: userAccountLifetime.value, - sipConfig: sipConfigurationTemplate, - signingAlgorithm: "SHA512WITHRSA", - }; - axios(configApiCall(api_path_post_install_server, "POST", jsonData, null)) - .then((response) => { - callBackServerParameters(); - }) - .catch((error) => { - console.log("Error installing server parameters: " + error); - }); - } else { - props.setError(true); - props.setErrorMessage(i18next.t("please_enter_valid_cors_domain_url", "Please enter a valid CORS domain URL.")); - } + if (values.domain.match(re)) { + jsonData = { + serverDomain: values.domain, + crlLifetime: certificateRevocation.value, + deviceLifetime: deviceLifetime.value, + userLifetime: userAccountLifetime.value, + sipConfig: sipConfigurationTemplate, + signingAlgorithm: "SHA512WITHRSA", + }; + axios(configApiCall(api_path_post_install_server, "POST", jsonData, null)) + .then((response) => { + callBackServerParameters(); + }) + .catch((error) => { + console.log("Error installing server parameters: " + error); + }); + } else { + props.setError(true); + props.setErrorMessage( + i18next.t( + "please_enter_valid_cors_domain_url", + "Please enter a valid CORS domain URL." + ) + ); + } } const handleCertificateRevocationChange = (event) => { @@ -185,17 +192,28 @@ export default function ServerParameters(props) { return ( <form className={classes.form} noValidate onSubmit={handleSubmit}> <Typography variant="h5" gutterBottom color="primary"> - {i18next.t("server_parameters", "Server Parameters")} + {i18next.t("server_parameters", "Server Parameters")} </Typography> <Typography variant="body1" gutterBottom> - {i18next.t("global_parameters_cover_general_configuration_of_servers_engine", "The global parameters cover the general configuration of the server's engine.")} + {i18next.t( + "global_parameters_cover_general_configuration_of_servers_engine", + "The global parameters cover the general configuration of the server's engine." + )} </Typography> <Typography variant="subtitle1" gutterBottom> - {i18next.t("cors_domain_name", "CORS domain name")} - <CustomPopupState message={i18next.t("set_domain_of_web_cleint_server_to_connect_to_hans_admin_dashboard_and_jami_accounts_also_to_set_client_crls_ocsps", "Set the domain of the web client-server to connect to the JAMS admin dashboard and Jami accounts. It is also used to define where the clients should download CRLs and submit OCSP queries. In case you are running a proxied instance (i.e. JAMS behind IIS), please make sure to set this field correctly, otherwise devices will not be able to download CRLs or validate certificates.")} /> + {i18next.t("cors_domain_name", "CORS domain name")} + <CustomPopupState + message={i18next.t( + "set_domain_of_web_cleint_server_to_connect_to_hans_admin_dashboard_and_jami_accounts_also_to_set_client_crls_ocsps", + "Set the domain of the web client-server to connect to the JAMS admin dashboard and Jami accounts. It is also used to define where the clients should download CRLs and submit OCSP queries. In case you are running a proxied instance (i.e. JAMS behind IIS), please make sure to set this field correctly, otherwise devices will not be able to download CRLs or validate certificates." + )} + /> </Typography> <Typography variant="body1" gutterBottom> - {i18next.t("domain_name_of_web_client_server", "The domain name of your web client server.")} + {i18next.t( + "domain_name_of_web_client_server", + "The domain name of your web client server." + )} </Typography> <TextField variant="outlined" @@ -213,8 +231,16 @@ export default function ServerParameters(props) { helperText={errors.domain && touched.domain && errors.domain} /> <Typography variant="subtitle1" gutterBottom> - {i18next.t("certificate_revocation_list_lifetime", "Certificate Revocation List Lifetime")} - <CustomPopupState message={i18next.t("set_liftetime_crl_list_certificates_revoked", "Set the lifetime of the CRL which contains the list of the certificates that have been revoked before their scheduled expiration date.")} /> + {i18next.t( + "certificate_revocation_list_lifetime", + "Certificate Revocation List Lifetime" + )} + <CustomPopupState + message={i18next.t( + "set_liftetime_crl_list_certificates_revoked", + "Set the lifetime of the CRL which contains the list of the certificates that have been revoked before their scheduled expiration date." + )} + /> </Typography> <Select labelId="certificate-revocation-select-label" @@ -249,11 +275,17 @@ export default function ServerParameters(props) { /> {userlifeDisabled ? ( <span class="spanError"> - {i18next.t("account_lifetime_should_be_bigger_to_device_lifetime", "The account lifetime should be longer than the Device lifetime.")} + {i18next.t( + "account_lifetime_should_be_bigger_to_device_lifetime", + "The account lifetime should be longer than the Device lifetime." + )} </span> ) : null} <Typography variant="subtitle1" gutterBottom> - {i18next.t("sip_configuration_template", "SIP Configuration Template")} + {i18next.t( + "sip_configuration_template", + "SIP Configuration Template" + )} </Typography> <Input fullWidth diff --git a/jams-react-client/src/components/Sidebar/Sidebar.js b/jams-react-client/src/components/Sidebar/Sidebar.js index fd15bd6d..81d24416 100755 --- a/jams-react-client/src/components/Sidebar/Sidebar.js +++ b/jams-react-client/src/components/Sidebar/Sidebar.js @@ -56,13 +56,14 @@ export default function Sidebar(props) { var links = ( <List className={classes.list}> - <ListItem - className={classes.itemLink} - >{brand}</ListItem> - <div className={classes.itemLinkSeparator}><hr/></div> + <ListItem className={classes.itemLink}>{brand}</ListItem> + <div className={classes.itemLinkSeparator}> + <hr /> + </div> {routes.map((prop, key) => { - if( prop.admin && !auth.hasAdminScope()) return; - if( !prop.admin && auth.hasAdminScope() && prop.path === "/user/admin") return; + if (prop.admin && !auth.hasAdminScope()) return; + if (!prop.admin && auth.hasAdminScope() && prop.path === "/user/admin") + return; var activePro = " "; var listItemClasses; if (prop.path === "/upgrade-to-pro") { @@ -96,23 +97,28 @@ export default function Sidebar(props) { key={key} > <Link to={`${prop.path}`}> - <ListItem - button - className={classes.itemLink + listItemClasses} - > + <ListItem button className={classes.itemLink + listItemClasses}> {typeof prop.icon === "string" ? ( <Icon - className={classNames(classes.itemIcon, whiteFontClasses, { - [classes.itemIconRTL]: props.rtlActive, - })} + className={classNames( + classes.itemIcon, + whiteFontClasses, + { + [classes.itemIconRTL]: props.rtlActive, + } + )} > {prop.icon} </Icon> ) : ( <prop.icon - className={classNames(classes.itemIcon, whiteFontClasses, { - [classes.itemIconRTL]: props.rtlActive, - })} + className={classNames( + classes.itemIcon, + whiteFontClasses, + { + [classes.itemIconRTL]: props.rtlActive, + } + )} /> )} <ListItemText @@ -133,7 +139,6 @@ export default function Sidebar(props) { var bottomLinks = ( <List className={classes.bottomlist}> - {open && ( <ListItem button diff --git a/jams-react-client/src/components/Snackbar/Snackbar.js b/jams-react-client/src/components/Snackbar/Snackbar.js index 4b4e6ebf..2aca6a5e 100644 --- a/jams-react-client/src/components/Snackbar/Snackbar.js +++ b/jams-react-client/src/components/Snackbar/Snackbar.js @@ -17,7 +17,7 @@ export default function Snackbar(props) { const { message, color, close, icon, place, open, rtlActive } = props; var action = []; const messageClasses = classNames({ - [classes.iconMessage]: icon !== undefined + [classes.iconMessage]: icon !== undefined, }); if (close !== undefined) { action = [ @@ -29,7 +29,7 @@ export default function Snackbar(props) { onClick={() => props.closeNotification()} > <Close className={classes.close} /> - </IconButton> + </IconButton>, ]; } return ( @@ -41,7 +41,7 @@ export default function Snackbar(props) { ? "left" : place.indexOf("c") !== -1 ? "center" - : "right" + : "right", }} open={open} message={ @@ -55,8 +55,8 @@ export default function Snackbar(props) { classes: { root: classes.root + " " + classes[color], message: classes.message, - action: classNames({ [classes.actionRTL]: rtlActive }) - } + action: classNames({ [classes.actionRTL]: rtlActive }), + }, }} /> ); @@ -70,5 +70,5 @@ Snackbar.propTypes = { place: PropTypes.oneOf(["tl", "tr", "tc", "br", "bl", "bc"]), open: PropTypes.bool, rtlActive: PropTypes.bool, - closeNotification: PropTypes.func + closeNotification: PropTypes.func, }; diff --git a/jams-react-client/src/components/Snackbar/SnackbarContent.js b/jams-react-client/src/components/Snackbar/SnackbarContent.js index f0002739..ebbaa422 100644 --- a/jams-react-client/src/components/Snackbar/SnackbarContent.js +++ b/jams-react-client/src/components/Snackbar/SnackbarContent.js @@ -17,7 +17,7 @@ export default function SnackbarContent(props) { const { message, color, close, icon, rtlActive } = props; var action = []; const messageClasses = classNames({ - [classes.iconMessage]: icon !== undefined + [classes.iconMessage]: icon !== undefined, }); if (close !== undefined) { action = [ @@ -28,7 +28,7 @@ export default function SnackbarContent(props) { color="info" > <Close className={classes.close} /> - </IconButton> + </IconButton>, ]; } return ( @@ -42,7 +42,7 @@ export default function SnackbarContent(props) { classes={{ root: classes.root + " " + classes[color], message: classes.message, - action: classNames({ [classes.actionRTL]: rtlActive }) + action: classNames({ [classes.actionRTL]: rtlActive }), }} action={action} /> @@ -54,5 +54,5 @@ SnackbarContent.propTypes = { color: PropTypes.oneOf(["info", "success", "warning", "danger", "primary"]), close: PropTypes.bool, icon: PropTypes.object, - rtlActive: PropTypes.bool + rtlActive: PropTypes.bool, }; diff --git a/jams-react-client/src/components/Table/Table.js b/jams-react-client/src/components/Table/Table.js index 91ad32db..80343ba0 100644 --- a/jams-react-client/src/components/Table/Table.js +++ b/jams-react-client/src/components/Table/Table.js @@ -55,7 +55,7 @@ export default function CustomTable(props) { } CustomTable.defaultProps = { - tableHeaderColor: "gray" + tableHeaderColor: "gray", }; CustomTable.propTypes = { @@ -66,8 +66,8 @@ CustomTable.propTypes = { "success", "info", "rose", - "gray" + "gray", ]), tableHead: PropTypes.arrayOf(PropTypes.string), - tableData: PropTypes.arrayOf(PropTypes.arrayOf(PropTypes.string)) + tableData: PropTypes.arrayOf(PropTypes.arrayOf(PropTypes.string)), }; diff --git a/jams-react-client/src/components/Tasks/Tasks.js b/jams-react-client/src/components/Tasks/Tasks.js index 4ab65b2f..c9c7a432 100755 --- a/jams-react-client/src/components/Tasks/Tasks.js +++ b/jams-react-client/src/components/Tasks/Tasks.js @@ -22,7 +22,7 @@ const useStyles = makeStyles(styles); export default function Tasks(props) { const classes = useStyles(); const [checked, setChecked] = React.useState([...props.checkedIndexes]); - const handleToggle = value => { + const handleToggle = (value) => { const currentIndex = checked.indexOf(value); const newChecked = [...checked]; if (currentIndex === -1) { @@ -34,12 +34,12 @@ export default function Tasks(props) { }; const { tasksIndexes, tasks, rtlActive } = props; const tableCellClasses = classnames(classes.tableCell, { - [classes.tableCellRTL]: rtlActive + [classes.tableCellRTL]: rtlActive, }); return ( <Table className={classes.table}> <TableBody> - {tasksIndexes.map(value => ( + {tasksIndexes.map((value) => ( <TableRow key={value} className={classes.tableRow}> <TableCell className={tableCellClasses}> <Checkbox @@ -50,7 +50,7 @@ export default function Tasks(props) { icon={<Check className={classes.uncheckedIcon} />} classes={{ checked: classes.checked, - root: classes.root + root: classes.root, }} /> </TableCell> @@ -102,5 +102,5 @@ Tasks.propTypes = { tasksIndexes: PropTypes.arrayOf(PropTypes.number), tasks: PropTypes.arrayOf(PropTypes.node), rtlActive: PropTypes.bool, - checkedIndexes: PropTypes.array + checkedIndexes: PropTypes.array, }; diff --git a/jams-react-client/src/components/Typography/Danger.js b/jams-react-client/src/components/Typography/Danger.js index aba10f5d..61bb44a9 100755 --- a/jams-react-client/src/components/Typography/Danger.js +++ b/jams-react-client/src/components/Typography/Danger.js @@ -18,5 +18,5 @@ export default function Danger(props) { } Danger.propTypes = { - children: PropTypes.node + children: PropTypes.node, }; diff --git a/jams-react-client/src/components/Typography/Info.js b/jams-react-client/src/components/Typography/Info.js index a2deeda8..633e3f57 100755 --- a/jams-react-client/src/components/Typography/Info.js +++ b/jams-react-client/src/components/Typography/Info.js @@ -18,5 +18,5 @@ export default function Info(props) { } Info.propTypes = { - children: PropTypes.node + children: PropTypes.node, }; diff --git a/jams-react-client/src/components/Typography/Muted.js b/jams-react-client/src/components/Typography/Muted.js index 97a31e45..e817c869 100755 --- a/jams-react-client/src/components/Typography/Muted.js +++ b/jams-react-client/src/components/Typography/Muted.js @@ -18,5 +18,5 @@ export default function Muted(props) { } Muted.propTypes = { - children: PropTypes.node + children: PropTypes.node, }; diff --git a/jams-react-client/src/components/Typography/Primary.js b/jams-react-client/src/components/Typography/Primary.js index f0713a00..cd73db4b 100755 --- a/jams-react-client/src/components/Typography/Primary.js +++ b/jams-react-client/src/components/Typography/Primary.js @@ -18,5 +18,5 @@ export default function Primary(props) { } Primary.propTypes = { - children: PropTypes.node + children: PropTypes.node, }; diff --git a/jams-react-client/src/components/Typography/Quote.js b/jams-react-client/src/components/Typography/Quote.js index 26426692..72acd8ba 100755 --- a/jams-react-client/src/components/Typography/Quote.js +++ b/jams-react-client/src/components/Typography/Quote.js @@ -20,5 +20,5 @@ export default function Quote(props) { Quote.propTypes = { text: PropTypes.node, - author: PropTypes.node + author: PropTypes.node, }; diff --git a/jams-react-client/src/components/Typography/Success.js b/jams-react-client/src/components/Typography/Success.js index 573b9ea5..959a6b34 100755 --- a/jams-react-client/src/components/Typography/Success.js +++ b/jams-react-client/src/components/Typography/Success.js @@ -18,5 +18,5 @@ export default function Success(props) { } Success.propTypes = { - children: PropTypes.node + children: PropTypes.node, }; diff --git a/jams-react-client/src/components/Typography/Warning.js b/jams-react-client/src/components/Typography/Warning.js index 1a85b77f..28e8e1b9 100755 --- a/jams-react-client/src/components/Typography/Warning.js +++ b/jams-react-client/src/components/Typography/Warning.js @@ -18,5 +18,5 @@ export default function Warning(props) { } Warning.propTypes = { - children: PropTypes.node + children: PropTypes.node, }; diff --git a/jams-react-client/src/configured.route.js b/jams-react-client/src/configured.route.js index 32200089..d56b33dc 100644 --- a/jams-react-client/src/configured.route.js +++ b/jams-react-client/src/configured.route.js @@ -1,38 +1,34 @@ - -import React from 'react' -import { Route } from 'react-router-dom' -import auth from './auth' +import React from "react"; +import { Route } from "react-router-dom"; +import auth from "./auth"; import SignUp from "layouts/SignUp"; import SignIn from "layouts/SignIn"; export const ConfiguredRoute = ({ component: Component, ...rest }) => { - return ( - <Route {...rest} render={ - - (props) => { - if (auth.hasAdmin()) { - if(auth.isInstalled()){ - return <Component {...props} /> - }else if(!auth.isInstalled() && auth.isAuthenticated()){ - if(auth.uri === '/api/install/ca' || auth.uri === 'start'){ - return <SignUp step={1}/> - } - else if (auth.uri === '/api/install/auth'){ - return <SignUp step={2}/> - } else if (auth.uri === '/api/install/settings'){ - return <SignUp step={3}/> - } else { - console.log('Error no matching path for configuration') - } - - }else { - return <SignIn /> - } - } else { - return <SignUp step={0}/> - } - + return ( + <Route + {...rest} + render={(props) => { + if (auth.hasAdmin()) { + if (auth.isInstalled()) { + return <Component {...props} />; + } else if (!auth.isInstalled() && auth.isAuthenticated()) { + if (auth.uri === "/api/install/ca" || auth.uri === "start") { + return <SignUp step={1} />; + } else if (auth.uri === "/api/install/auth") { + return <SignUp step={2} />; + } else if (auth.uri === "/api/install/settings") { + return <SignUp step={3} />; + } else { + console.log("Error no matching path for configuration"); } - } /> - ) -} \ No newline at end of file + } else { + return <SignIn />; + } + } else { + return <SignUp step={0} />; + } + }} + /> + ); +}; diff --git a/jams-react-client/src/globalUrls.js b/jams-react-client/src/globalUrls.js index 9d7f89c4..aef3865f 100644 --- a/jams-react-client/src/globalUrls.js +++ b/jams-react-client/src/globalUrls.js @@ -111,5 +111,5 @@ module.exports = { api_path_get_group_members, api_path_post_group_member, api_path_delete_group_member, - api_path_get_admin_user_groups + api_path_get_admin_user_groups, }; diff --git a/jams-react-client/src/i18n.js b/jams-react-client/src/i18n.js index f5a0df3e..34cce348 100644 --- a/jams-react-client/src/i18n.js +++ b/jams-react-client/src/i18n.js @@ -1,6 +1,6 @@ import i18next from "i18next"; import LanguageDetector from "i18next-browser-languagedetector"; -import Backend from 'i18next-http-backend'; +import Backend from "i18next-http-backend"; import { initReactI18next } from "react-i18next"; i18next diff --git a/jams-react-client/src/index.js b/jams-react-client/src/index.js index dc95954d..8f9b8c4d 100644 --- a/jams-react-client/src/index.js +++ b/jams-react-client/src/index.js @@ -31,7 +31,7 @@ import GroupsRoute from "routes/GroupsRoute.js"; import GroupRoute from "routes/GroupRoute.js"; import BlueprintsRoute from "routes/BlueprintsRoute.js"; import BlueprintRoute from "routes/BlueprintRoute.js"; -import SettingsRoute from "routes/SettingsRoute.js"; +import SettingsRoute from "routes/SettingsRoute.js"; import SignIn from "layouts/SignIn.js"; @@ -54,7 +54,10 @@ auth.checkServerInstalled(() => { <ProtectedRoute path="/groups" component={GroupsRoute} /> <ProtectedRoute path="/group/:groupid" component={GroupRoute} /> <ProtectedRoute path="/blueprints" component={BlueprintsRoute} /> - <ProtectedRoute path="/blueprint/:blueprintname" component={BlueprintRoute} /> + <ProtectedRoute + path="/blueprint/:blueprintname" + component={BlueprintRoute} + /> <ProtectedRoute path="/settings" component={SettingsRoute} /> <Redirect from="/" to="/signin" /> </Switch> diff --git a/jams-react-client/src/layouts/BaseLayout.js b/jams-react-client/src/layouts/BaseLayout.js index 89f336d3..115f5518 100644 --- a/jams-react-client/src/layouts/BaseLayout.js +++ b/jams-react-client/src/layouts/BaseLayout.js @@ -29,13 +29,10 @@ import logo from "assets/img/jams_logo_white_no_gnu_package.svg"; import auth from "auth"; import configApiCall from "api.js"; -import { - api_path_get_start_update -} from "globalUrls"; +import { api_path_get_start_update } from "globalUrls"; import axios from "axios"; - import Dialog from "@material-ui/core/Dialog/Dialog"; import DialogTitle from "@material-ui/core/DialogTitle/DialogTitle"; import DialogContent from "@material-ui/core/DialogContent/DialogContent"; @@ -90,7 +87,7 @@ export default function Admin(props) { icon: Group, component: Groups, layout: "/admin", - admin: true + admin: true, }, { path: "/blueprints", @@ -98,7 +95,7 @@ export default function Admin(props) { icon: AllInbox, component: Blueprints, layout: "/admin", - admin: true + admin: true, }, { path: "/settings", @@ -106,7 +103,7 @@ export default function Admin(props) { icon: SettingsIcon, component: Settings, layout: "/admin", - admin: true + admin: true, }, ]; @@ -124,20 +121,29 @@ export default function Admin(props) { if (auth.hasAdminScope()) { if (auth.isActivated()) { setDialogMessage( - i18next.t("new_version_jams_available", "A new version of JAMS is available. Would you like to update now?") + i18next.t( + "new_version_jams_available", + "A new version of JAMS is available. Would you like to update now?" + ) ); setMessageYes("Update Now"); setMessageNo("Update Later"); } else { setDialogMessage( - i18next.t("running_community_version_jams", "You are currently running the community version of JAMS. Would you like to purchase a JAMS subscription?") + i18next.t( + "running_community_version_jams", + "You are currently running the community version of JAMS. Would you like to purchase a JAMS subscription?" + ) ); setMessageYes("Yes, go to Jami Store"); setMessageNo("No thanks"); } } else { setDialogMessage( - i18next.t("you_are_not_allowed_to_access_this_section", "You are not allowed to access this section. Please contact your administrator to get administrator privileges.") + i18next.t( + "you_are_not_allowed_to_access_this_section", + "You are not allowed to access this section. Please contact your administrator to get administrator privileges." + ) ); } }; @@ -148,7 +154,12 @@ export default function Admin(props) { auth.getUpdates(() => { if (auth.isUpdateAvailable()) { setOpen(true); - setMessage(i18next.t("an_update_is_available_for_jams", "An update is available for JAMS.")); + setMessage( + i18next.t( + "an_update_is_available_for_jams", + "An update is available for JAMS." + ) + ); } }); }); @@ -177,14 +188,24 @@ export default function Admin(props) { const handleUpdate = () => { setQuery(false); if (auth.isActivated()) { - setSnackbarMessage(i18next.t("updating_jams_shutting_down_shortly", "Updating JAMS, shutting down shortly...")); + setSnackbarMessage( + i18next.t( + "updating_jams_shutting_down_shortly", + "Updating JAMS, shutting down shortly..." + ) + ); axios(configApiCall(api_path_get_start_update, "POST", null, null)) .then(() => { handleCancel(); setUpdating(true); }) .catch((error) => { - setSnackbarMessage(i18next.t("error_while_attempting_update_jams", "Error occurred while attempting to update JAMS:") + error); + setSnackbarMessage( + i18next.t( + "error_while_attempting_update_jams", + "Error occurred while attempting to update JAMS:" + ) + error + ); }); } }; @@ -232,14 +253,9 @@ export default function Admin(props) { /> <div className={classes.mainPanel} ref={mainPanel}> - <Navbar - routes={Routes} - handleDrawerToggle={handleDrawerToggle} - /> - <div className={classes.map}> - {props.component} - </div> - <Footer /> + <Navbar routes={Routes} handleDrawerToggle={handleDrawerToggle} /> + <div className={classes.map}>{props.component}</div> + <Footer /> </div> </div> ); diff --git a/jams-react-client/src/layouts/ListLayout.js b/jams-react-client/src/layouts/ListLayout.js index 8183f126..34f68700 100644 --- a/jams-react-client/src/layouts/ListLayout.js +++ b/jams-react-client/src/layouts/ListLayout.js @@ -11,7 +11,7 @@ import Footer from "components/Footer/Footer.js"; import Sidebar from "components/Sidebar/Sidebar.js"; // @material-ui/icons -import AccountCircleIcon from '@material-ui/icons/AccountCircle'; +import AccountCircleIcon from "@material-ui/icons/AccountCircle"; import Person from "@material-ui/icons/Person"; import Group from "@material-ui/icons/Group"; import AllInbox from "@material-ui/icons/AllInbox"; @@ -30,13 +30,10 @@ import logo from "assets/img/jams_logo_white_no_gnu_package.svg"; import auth from "auth"; import configApiCall from "api.js"; -import { - api_path_get_start_update -} from "globalUrls"; +import { api_path_get_start_update } from "globalUrls"; import axios from "axios"; - import Dialog from "@material-ui/core/Dialog/Dialog"; import DialogTitle from "@material-ui/core/DialogTitle/DialogTitle"; import DialogContent from "@material-ui/core/DialogContent/DialogContent"; @@ -77,7 +74,7 @@ export default function Admin(props) { icon: AccountCircleIcon, component: Users, layout: "/admin", - admin: false + admin: false, }, { path: "/users", @@ -85,7 +82,7 @@ export default function Admin(props) { icon: Person, component: Users, layout: "/admin", - admin: false + admin: false, }, { path: "/groups", @@ -93,7 +90,7 @@ export default function Admin(props) { icon: Group, component: Groups, layout: "/admin", - admin: true + admin: true, }, { path: "/blueprints", @@ -101,7 +98,7 @@ export default function Admin(props) { icon: AllInbox, component: Blueprints, layout: "/admin", - admin: true + admin: true, }, { path: "/settings", @@ -109,7 +106,7 @@ export default function Admin(props) { icon: SettingsIcon, component: Settings, layout: "/admin", - admin: true + admin: true, }, ]; @@ -127,20 +124,29 @@ export default function Admin(props) { if (auth.hasAdminScope()) { if (auth.isActivated()) { setDialogMessage( - i18next.t("new_version_jams_available", "A new version of JAMS is available. Would you like to update now?") + i18next.t( + "new_version_jams_available", + "A new version of JAMS is available. Would you like to update now?" + ) ); setMessageYes("Update Now"); setMessageNo("Update Later"); } else { setDialogMessage( - i18next.t("running_community_version_jams", "You are currently running the community version of JAMS. Would you like to purchase a JAMS subscription?") + i18next.t( + "running_community_version_jams", + "You are currently running the community version of JAMS. Would you like to purchase a JAMS subscription?" + ) ); setMessageYes("Yes, go to Jami Store"); setMessageNo("No thanks"); } } else { setDialogMessage( - i18next.t("you_are_not_allowed_to_access_this_section", "You are not allowed to access this section. Please contact your administrator to get administrator privileges.") + i18next.t( + "you_are_not_allowed_to_access_this_section", + "You are not allowed to access this section. Please contact your administrator to get administrator privileges." + ) ); } }; @@ -151,7 +157,12 @@ export default function Admin(props) { auth.getUpdates(() => { if (auth.isUpdateAvailable()) { setOpen(true); - setMessage(i18next.t("an_update_is_available_for_jams", "An update is available for JAMS.")); + setMessage( + i18next.t( + "an_update_is_available_for_jams", + "An update is available for JAMS." + ) + ); } }); }); @@ -180,14 +191,24 @@ export default function Admin(props) { const handleUpdate = () => { setQuery(false); if (auth.isActivated()) { - setSnackbarMessage(i18next.t("updating_jams_shutting_down_shortly", "Updating JAMS, shutting down shortly...")); + setSnackbarMessage( + i18next.t( + "updating_jams_shutting_down_shortly", + "Updating JAMS, shutting down shortly..." + ) + ); axios(configApiCall(api_path_get_start_update, "POST", null, null)) .then(() => { handleCancel(); setUpdating(true); }) .catch((error) => { - setSnackbarMessage(i18next.t("error_while_attempting_update_jams", "Error occurred while attempting to update JAMS:") + error); + setSnackbarMessage( + i18next.t( + "error_while_attempting_update_jams", + "Error occurred while attempting to update JAMS:" + ) + error + ); }); } }; @@ -235,14 +256,11 @@ export default function Admin(props) { /> <div className={classes.mainPanel} ref={mainPanel}> - <Navbar - routes={Routes} - handleDrawerToggle={handleDrawerToggle} - /> - <div className={classes.content}> - <div className={classes.container}>{props.component}</div> - </div> - <Footer /> + <Navbar routes={Routes} handleDrawerToggle={handleDrawerToggle} /> + <div className={classes.content}> + <div className={classes.container}>{props.component}</div> + </div> + <Footer /> </div> </div> ); diff --git a/jams-react-client/src/layouts/SignIn.js b/jams-react-client/src/layouts/SignIn.js index 5ac22318..24dcf233 100644 --- a/jams-react-client/src/layouts/SignIn.js +++ b/jams-react-client/src/layouts/SignIn.js @@ -74,12 +74,11 @@ export default function SignIn(props) { React.useEffect(() => { if (auth.isAuthenticated() && auth.isInstalled()) { - if(auth.hasAdminScope()) - history.push("/users"); + if (auth.hasAdminScope()) history.push("/users"); else { - if(auth.getUsername() !== null) { + if (auth.getUsername() !== null) { history.push(`/user/${auth.getUsername()}`); - } + } } } }); @@ -94,12 +93,11 @@ export default function SignIn(props) { auth.checkLastKnownStep(() => { auth.checkDirectoryType(() => { if (auth.isServerInstalled()) { - if(auth.hasAdminScope()) - history.push("/users"); + if (auth.hasAdminScope()) history.push("/users"); else { - if(auth.getUsername() !== null) { + if (auth.getUsername() !== null) { history.push(`/user/${auth.getUsername()}`); - } + } } } else { history.push("/"); diff --git a/jams-react-client/src/layouts/SignUp.js b/jams-react-client/src/layouts/SignUp.js index 2a56946e..eafda0e1 100644 --- a/jams-react-client/src/layouts/SignUp.js +++ b/jams-react-client/src/layouts/SignUp.js @@ -110,7 +110,7 @@ export default function SignUp(props) { <Box mt={8}> <Copyright /> </Box> - <Box mt={8} justifyContent="center" > + <Box mt={8} justifyContent="center"> <LanguagePicker navigationTarget={"/"} /> </Box> </Paper> diff --git a/jams-react-client/src/protected.route.js b/jams-react-client/src/protected.route.js index 35eeb0eb..bf48b92f 100644 --- a/jams-react-client/src/protected.route.js +++ b/jams-react-client/src/protected.route.js @@ -1,27 +1,27 @@ -import React from 'react' -import { Route, Redirect } from 'react-router-dom' -import auth from './auth' +import React from "react"; +import { Route, Redirect } from "react-router-dom"; +import auth from "./auth"; export const ProtectedRoute = ({ component: Component, ...rest }) => { - return ( - <Route {...rest} render={ - (props) => { - - if (auth.isAuthenticated() && auth.isInstalled()) { - return <Component {...props} /> - } - else { - return <Redirect to={{ - pathname: "/", - state: { - from: props.location - } - } - - } /> - } - - } - } /> - ) -} + return ( + <Route + {...rest} + render={(props) => { + if (auth.isAuthenticated() && auth.isInstalled()) { + return <Component {...props} />; + } else { + return ( + <Redirect + to={{ + pathname: "/", + state: { + from: props.location, + }, + }} + /> + ); + } + }} + /> + ); +}; diff --git a/jams-react-client/src/routes/BlueprintRoute.js b/jams-react-client/src/routes/BlueprintRoute.js index d9f87304..69958c57 100644 --- a/jams-react-client/src/routes/BlueprintRoute.js +++ b/jams-react-client/src/routes/BlueprintRoute.js @@ -3,8 +3,10 @@ import React from "react"; import BaseLayout from "layouts/BaseLayout.js"; import Blueprint from "views/Blueprint/Blueprint"; -export default function BlueprintRoute (props) { - return ( - <BaseLayout component={<Blueprint blueprintName={props.match.params.blueprintname} />} /> - ) -} \ No newline at end of file +export default function BlueprintRoute(props) { + return ( + <BaseLayout + component={<Blueprint blueprintName={props.match.params.blueprintname} />} + /> + ); +} diff --git a/jams-react-client/src/routes/BlueprintsRoute.js b/jams-react-client/src/routes/BlueprintsRoute.js index 35037ee6..5faa5f57 100644 --- a/jams-react-client/src/routes/BlueprintsRoute.js +++ b/jams-react-client/src/routes/BlueprintsRoute.js @@ -4,8 +4,6 @@ import Blueprints from "views/Blueprints/Blueprints.js"; import ListLayout from "layouts/ListLayout.js"; -export default function BlueprintsRoute () { - return ( - <ListLayout component={<Blueprints />} /> - ) -} \ No newline at end of file +export default function BlueprintsRoute() { + return <ListLayout component={<Blueprints />} />; +} diff --git a/jams-react-client/src/routes/CreateUserRoute.js b/jams-react-client/src/routes/CreateUserRoute.js index 031f871e..59a8afec 100644 --- a/jams-react-client/src/routes/CreateUserRoute.js +++ b/jams-react-client/src/routes/CreateUserRoute.js @@ -4,16 +4,14 @@ import EditCreateUserProfile from "views/UserProfile/EditCreateUserProfile.js"; import ListLayout from "layouts/ListLayout.js"; -export default function CreateUserRoute () { - return ( - <ListLayout component={<EditCreateUserProfile createUser={true} />} /> - ) +export default function CreateUserRoute() { + return <ListLayout component={<EditCreateUserProfile createUser={true} />} />; } // <EditCreateUserProfile - // createUser={createUser} - // setCreateUser={setCreateUser} - // setError={props.setError} - // setErrorMessage={props.setErrorMessage} - // setSeverity={props.setSeverity} - // /> \ No newline at end of file +// createUser={createUser} +// setCreateUser={setCreateUser} +// setError={props.setError} +// setErrorMessage={props.setErrorMessage} +// setSeverity={props.setSeverity} +// /> diff --git a/jams-react-client/src/routes/GroupRoute.js b/jams-react-client/src/routes/GroupRoute.js index d33110e1..1e3e21f7 100644 --- a/jams-react-client/src/routes/GroupRoute.js +++ b/jams-react-client/src/routes/GroupRoute.js @@ -3,8 +3,10 @@ import React from "react"; import ListLayout from "layouts/ListLayout.js"; import EditGroup from "views/Groups/EditGroup.js"; -export default function GroupRoute (props) { - return ( - <ListLayout component={<EditGroup groupid={props.match.params.groupid} />} /> - ) -} \ No newline at end of file +export default function GroupRoute(props) { + return ( + <ListLayout + component={<EditGroup groupid={props.match.params.groupid} />} + /> + ); +} diff --git a/jams-react-client/src/routes/GroupsRoute.js b/jams-react-client/src/routes/GroupsRoute.js index db4bc713..2f016c19 100644 --- a/jams-react-client/src/routes/GroupsRoute.js +++ b/jams-react-client/src/routes/GroupsRoute.js @@ -3,8 +3,6 @@ import React from "react"; import ListLayout from "layouts/ListLayout.js"; import Groups from "views/Groups/Groups.js"; -export default function GroupsRoute () { - return ( - <ListLayout component={<Groups />} /> - ) -} \ No newline at end of file +export default function GroupsRoute() { + return <ListLayout component={<Groups />} />; +} diff --git a/jams-react-client/src/routes/SettingsRoute.js b/jams-react-client/src/routes/SettingsRoute.js index c645ee93..134e2d8d 100644 --- a/jams-react-client/src/routes/SettingsRoute.js +++ b/jams-react-client/src/routes/SettingsRoute.js @@ -4,8 +4,6 @@ import Settings from "views/Settings/Settings.js"; import BaseLayout from "layouts/BaseLayout.js"; -export default function SettingsRoute (props) { - return ( - <BaseLayout component={<Settings />} /> - ) -} \ No newline at end of file +export default function SettingsRoute(props) { + return <BaseLayout component={<Settings />} />; +} diff --git a/jams-react-client/src/routes/UserRoute.js b/jams-react-client/src/routes/UserRoute.js index 5a765ab7..3f3e1ff3 100644 --- a/jams-react-client/src/routes/UserRoute.js +++ b/jams-react-client/src/routes/UserRoute.js @@ -4,8 +4,10 @@ import UserProfile from "views/UserProfile/UserProfile.js"; import BaseLayout from "layouts/BaseLayout.js"; -export default function UsersRoute (props) { - return ( - <BaseLayout component={<UserProfile username={props.match.params.username} />} /> - ) -} \ No newline at end of file +export default function UsersRoute(props) { + return ( + <BaseLayout + component={<UserProfile username={props.match.params.username} />} + /> + ); +} diff --git a/jams-react-client/src/routes/UsersRoute.js b/jams-react-client/src/routes/UsersRoute.js index 668f097a..565e8247 100644 --- a/jams-react-client/src/routes/UsersRoute.js +++ b/jams-react-client/src/routes/UsersRoute.js @@ -4,8 +4,6 @@ import Users from "views/Users/Users.js"; import ListLayout from "layouts/ListLayout.js"; -export default function UsersRoute () { - return ( - <ListLayout component={<Users />} /> - ) -} \ No newline at end of file +export default function UsersRoute() { + return <ListLayout component={<Users />} />; +} diff --git a/jams-react-client/src/routes/routes.js b/jams-react-client/src/routes/routes.js index 03eafaed..71e1bc08 100644 --- a/jams-react-client/src/routes/routes.js +++ b/jams-react-client/src/routes/routes.js @@ -68,5 +68,4 @@ export default function Routes() { ]; return dashboardRoutes; - -} \ No newline at end of file +} diff --git a/jams-react-client/src/tools.js b/jams-react-client/src/tools.js index 3c6fe215..ba579019 100644 --- a/jams-react-client/src/tools.js +++ b/jams-react-client/src/tools.js @@ -1,33 +1,31 @@ -import React from 'react'; -import MenuItem from '@material-ui/core/MenuItem'; +import React from "react"; +import MenuItem from "@material-ui/core/MenuItem"; export function buildSelectMenuItems(elements) { - return elements.map((d) => - <MenuItem value={d.value}>{d.label}</MenuItem> - ) + return elements.map((d) => <MenuItem value={d.value}>{d.label}</MenuItem>); } // read file content export function readSingleFile(evt, fieldContents) { - var f = evt.target.files[0]; - if (f) { - var r = new FileReader(); - r.onload = function (e) { - var contents = e.target.result; - fieldContents=contents; - } - console.log(fieldContents); - r.readAsText(f); - return fieldContents - } + var f = evt.target.files[0]; + if (f) { + var r = new FileReader(); + r.onload = function (e) { + var contents = e.target.result; + fieldContents = contents; + }; + console.log(fieldContents); + r.readAsText(f); + return fieldContents; + } } -export function retrieveArrayElement(value, elements){ - for(let i=0; i < elements.length;i++){ - if(elements[i].value === value){ - return elements[i]; - } +export function retrieveArrayElement(value, elements) { + for (let i = 0; i < elements.length; i++) { + if (elements[i].value === value) { + return elements[i]; } + } } -export default {buildSelectMenuItems, readSingleFile, retrieveArrayElement}; \ No newline at end of file +export default { buildSelectMenuItems, readSingleFile, retrieveArrayElement }; diff --git a/jams-react-client/src/variables/charts.js b/jams-react-client/src/variables/charts.js index 828133eb..59d9d7b7 100755 --- a/jams-react-client/src/variables/charts.js +++ b/jams-react-client/src/variables/charts.js @@ -18,11 +18,11 @@ var delays2 = 80, const dailySalesChart = { data: { labels: ["M", "T", "W", "T", "F", "S", "S"], - series: [[12, 17, 7, 17, 23, 18, 38]] + series: [[12, 17, 7, 17, 23, 18, 38]], }, options: { lineSmooth: Chartist.Interpolation.cardinal({ - tension: 0 + tension: 0, }), low: 0, high: 50, // creative tim: we recommend you to set the high sa the biggest value + something for a better look @@ -30,12 +30,12 @@ const dailySalesChart = { top: 0, right: 0, bottom: 0, - left: 0 - } + left: 0, + }, }, // for animation animation: { - draw: function(data) { + draw: function (data) { if (data.type === "line" || data.type === "area") { data.element.animate({ d: { @@ -47,8 +47,8 @@ const dailySalesChart = { .translate(0, data.chartRect.height()) .stringify(), to: data.path.clone().stringify(), - easing: Chartist.Svg.Easing.easeOutQuint - } + easing: Chartist.Svg.Easing.easeOutQuint, + }, }); } else if (data.type === "point") { data.element.animate({ @@ -57,12 +57,12 @@ const dailySalesChart = { dur: durations, from: 0, to: 1, - easing: "ease" - } + easing: "ease", + }, }); } - } - } + }, + }, }; // ############################## @@ -83,13 +83,13 @@ const emailsSubscriptionChart = { "Sep", "Oct", "Nov", - "Dec" + "Dec", ], - series: [[542, 443, 320, 780, 553, 453, 326, 434, 568, 610, 756, 895]] + series: [[542, 443, 320, 780, 553, 453, 326, 434, 568, 610, 756, 895]], }, options: { axisX: { - showGrid: false + showGrid: false, }, low: 0, high: 1000, @@ -97,8 +97,8 @@ const emailsSubscriptionChart = { top: 0, right: 5, bottom: 0, - left: 0 - } + left: 0, + }, }, responsiveOptions: [ [ @@ -106,15 +106,15 @@ const emailsSubscriptionChart = { { seriesBarDistance: 5, axisX: { - labelInterpolationFnc: function(value) { + labelInterpolationFnc: function (value) { return value[0]; - } - } - } - ] + }, + }, + }, + ], ], animation: { - draw: function(data) { + draw: function (data) { if (data.type === "bar") { data.element.animate({ opacity: { @@ -122,12 +122,12 @@ const emailsSubscriptionChart = { dur: durations2, from: 0, to: 1, - easing: "ease" - } + easing: "ease", + }, }); } - } - } + }, + }, }; // ############################## @@ -137,11 +137,11 @@ const emailsSubscriptionChart = { const completedTasksChart = { data: { labels: ["12am", "3pm", "6pm", "9pm", "12pm", "3am", "6am", "9am"], - series: [[230, 750, 450, 300, 280, 240, 200, 190]] + series: [[230, 750, 450, 300, 280, 240, 200, 190]], }, options: { lineSmooth: Chartist.Interpolation.cardinal({ - tension: 0 + tension: 0, }), low: 0, high: 1000, // creative tim: we recommend you to set the high sa the biggest value + something for a better look @@ -149,11 +149,11 @@ const completedTasksChart = { top: 0, right: 0, bottom: 0, - left: 0 - } + left: 0, + }, }, animation: { - draw: function(data) { + draw: function (data) { if (data.type === "line" || data.type === "area") { data.element.animate({ d: { @@ -165,8 +165,8 @@ const completedTasksChart = { .translate(0, data.chartRect.height()) .stringify(), to: data.path.clone().stringify(), - easing: Chartist.Svg.Easing.easeOutQuint - } + easing: Chartist.Svg.Easing.easeOutQuint, + }, }); } else if (data.type === "point") { data.element.animate({ @@ -175,16 +175,16 @@ const completedTasksChart = { dur: durations, from: 0, to: 1, - easing: "ease" - } + easing: "ease", + }, }); } - } - } + }, + }, }; module.exports = { dailySalesChart, emailsSubscriptionChart, - completedTasksChart + completedTasksChart, }; diff --git a/jams-react-client/src/variables/general.js b/jams-react-client/src/variables/general.js index 1c0b3633..f8e665da 100755 --- a/jams-react-client/src/variables/general.js +++ b/jams-react-client/src/variables/general.js @@ -6,21 +6,21 @@ var bugs = [ 'Sign contract for "What are conference organizers afraid of?"', "Lines From Great Russian Literature? Or E-mails From My Boss?", "Flooded: One year later, assessing what was lost and what was found when a ravaging rain swept through metro Detroit", - "Create 4 Invisible User Experiences you Never Knew About" + "Create 4 Invisible User Experiences you Never Knew About", ]; var website = [ "Flooded: One year later, assessing what was lost and what was found when a ravaging rain swept through metro Detroit", - 'Sign contract for "What are conference organizers afraid of?"' + 'Sign contract for "What are conference organizers afraid of?"', ]; var server = [ "Lines From Great Russian Literature? Or E-mails From My Boss?", "Flooded: One year later, assessing what was lost and what was found when a ravaging rain swept through metro Detroit", - 'Sign contract for "What are conference organizers afraid of?"' + 'Sign contract for "What are conference organizers afraid of?"', ]; module.exports = { // these 3 are used to create the tasks lists in TasksCard - Dashboard view bugs, website, - server + server, }; diff --git a/jams-react-client/src/views/Blueprint/Blueprint.js b/jams-react-client/src/views/Blueprint/Blueprint.js index 7ea53ff7..29b3d6b8 100644 --- a/jams-react-client/src/views/Blueprint/Blueprint.js +++ b/jams-react-client/src/views/Blueprint/Blueprint.js @@ -1,18 +1,16 @@ import React from "react"; -import PropTypes from 'prop-types'; -import AppBar from '@material-ui/core/AppBar'; -import Tabs from '@material-ui/core/Tabs'; -import Tab from '@material-ui/core/Tab'; -import Typography from '@material-ui/core/Typography'; -import Box from '@material-ui/core/Box'; +import PropTypes from "prop-types"; +import AppBar from "@material-ui/core/AppBar"; +import Tabs from "@material-ui/core/Tabs"; +import Tab from "@material-ui/core/Tab"; +import Typography from "@material-ui/core/Typography"; +import Box from "@material-ui/core/Box"; -import EditBlueprintPermissions from "./EditBlueprintPermissions" -import EditBlueprintConfiguration from "./EditBlueprintConfiguration" +import EditBlueprintPermissions from "./EditBlueprintPermissions"; +import EditBlueprintConfiguration from "./EditBlueprintConfiguration"; -import { - infoColor -} from "assets/jss/material-dashboard-react.js"; +import { infoColor } from "assets/jss/material-dashboard-react.js"; import i18next from "i18next"; @@ -45,7 +43,7 @@ TabPanel.propTypes = { function a11yProps(index) { return { id: `simple-tab-${index}`, - 'aria-controls': `simple-tabpanel-${index}`, + "aria-controls": `simple-tabpanel-${index}`, }; } @@ -55,7 +53,7 @@ const styles = { margin: "0", fontSize: "14px", marginTop: "0", - marginBottom: "0" + marginBottom: "0", }, cardTitleWhite: { color: "#FFFFFF", @@ -64,12 +62,11 @@ const styles = { fontWeight: "300", fontFamily: "'Roboto', 'Helvetica', 'Arial', sans-serif", marginBottom: "3px", - textDecoration: "none" - } + textDecoration: "none", + }, }; export default function Blueprint(props) { - const [value, setValue] = React.useState(0); const handleChange = (event, newValue) => { @@ -78,16 +75,26 @@ export default function Blueprint(props) { return ( <div> <AppBar position="static" style={{ background: infoColor[0] }}> - <Tabs value={value} onChange={handleChange} aria-label="simple tabs example"> - <Tab label={i18next.t("permissions", "Permissions")} {...a11yProps(0)} /> - <Tab label={i18next.t("configuration", "Configuration")} {...a11yProps(1)} /> + <Tabs + value={value} + onChange={handleChange} + aria-label="simple tabs example" + > + <Tab + label={i18next.t("permissions", "Permissions")} + {...a11yProps(0)} + /> + <Tab + label={i18next.t("configuration", "Configuration")} + {...a11yProps(1)} + /> </Tabs> </AppBar> <TabPanel value={value} index={0}> - <EditBlueprintPermissions blueprintName={props.blueprintName} /> + <EditBlueprintPermissions blueprintName={props.blueprintName} /> </TabPanel> <TabPanel value={value} index={1}> - <EditBlueprintConfiguration blueprintName={props.blueprintName} /> + <EditBlueprintConfiguration blueprintName={props.blueprintName} /> </TabPanel> </div> ); diff --git a/jams-react-client/src/views/Blueprint/EditBlueprintConfiguration.js b/jams-react-client/src/views/Blueprint/EditBlueprintConfiguration.js index 94483f52..0820df8b 100644 --- a/jams-react-client/src/views/Blueprint/EditBlueprintConfiguration.js +++ b/jams-react-client/src/views/Blueprint/EditBlueprintConfiguration.js @@ -311,13 +311,25 @@ export default function EditBlueprintConfiguration(props) { setOpen(false); setSeverity("success"); setOpen(true); - setMessage(i18next.t("updated_blueprint_configuration_successfully", "Blueprint configuration successfully updated.")); + setMessage( + i18next.t( + "updated_blueprint_configuration_successfully", + "Blueprint configuration successfully updated." + ) + ); }) .catch((error) => { setOpen(false); setSeverity("error"); setOpen(true); - setMessage(i18next.t("error_updating_blueprint_configuration", "Error occurred while updating blueprint configuration.") + error + "!"); + setMessage( + i18next.t( + "error_updating_blueprint_configuration", + "Error occurred while updating blueprint configuration." + ) + + error + + "!" + ); }); }; @@ -387,14 +399,24 @@ export default function EditBlueprintConfiguration(props) { <CardIcon color="info"> <BuildOutlinedIcon /> </CardIcon> - <p className={classes.cardCategory}>{i18next.t("configuration", "Configuration")}</p> + <p className={classes.cardCategory}> + {i18next.t("configuration", "Configuration")} + </p> <h3 className={classes.cardTitle}>{props.blueprintName}</h3> </CardHeader> <CardBody profile> <div className={classes.root}> <Grid container spacing={2}> <Grid item xs={12} sm={12} md={12}> - <FormLabel component="legend">UPnP <CustomPopupState message={i18next.t("upnp_custom_popup", "UPnP allows Jami to automatically open network ports to establish peer-to-peer communications.")} /></FormLabel> + <FormLabel component="legend"> + UPnP{" "} + <CustomPopupState + message={i18next.t( + "upnp_custom_popup", + "UPnP allows Jami to automatically open network ports to establish peer-to-peer communications." + )} + /> + </FormLabel> <FormControlLabel control={ <Switch @@ -417,7 +439,15 @@ export default function EditBlueprintConfiguration(props) { </Grid> <Grid item xs={12} sm={12} md={12}> <FormControl component="fieldset"> - <FormLabel component="legend">TURN <CustomPopupState message={i18next.t("turn_server_configuration_popup", "Configure a TURN server to establish a connection when peer-to-peer communication is not possible")} /></FormLabel> + <FormLabel component="legend"> + TURN{" "} + <CustomPopupState + message={i18next.t( + "turn_server_configuration_popup", + "Configure a TURN server to establish a connection when peer-to-peer communication is not possible" + )} + /> + </FormLabel> <RadioGroup value={selectedTurnOption} aria-label="gender" @@ -427,12 +457,18 @@ export default function EditBlueprintConfiguration(props) { <FormControlLabel value="defaultTurn" control={<StyledRadio />} - label={i18next.t("use_jami_default_turn_configuration", "Use Jami default TURN configuration")} + label={i18next.t( + "use_jami_default_turn_configuration", + "Use Jami default TURN configuration" + )} /> <FormControlLabel value="customTurn" control={<StyledRadio />} - label={i18next.t("use_a_custom_turn_configuration", "Use a custom TURN configuration")} + label={i18next.t( + "use_a_custom_turn_configuration", + "Use a custom TURN configuration" + )} /> <FormGroup row @@ -445,7 +481,10 @@ export default function EditBlueprintConfiguration(props) { > <FormControl className={classes.margin} size="large"> <InputLabel htmlFor="turnServer"> - {i18next.t("turn_server_address", "TURN Server address")} + {i18next.t( + "turn_server_address", + "TURN Server address" + )} </InputLabel> <Input id="turnServer" @@ -477,7 +516,10 @@ export default function EditBlueprintConfiguration(props) { > <FormControl className={classes.margin} size="large"> <InputLabel htmlFor="turnServerUserName"> - {i18next.t("turn_server_username", "TURN server username")} + {i18next.t( + "turn_server_username", + "TURN server username" + )} </InputLabel> <Input id="turnServerUserName" @@ -509,7 +551,10 @@ export default function EditBlueprintConfiguration(props) { > <FormControl className={classes.margin} size="large"> <InputLabel htmlFor="turnServerPassword"> - {i18next.t("turn_server_password", "TURN server password")} + {i18next.t( + "turn_server_password", + "TURN server password" + )} </InputLabel> <Input disabled={!turnEnabled} @@ -548,7 +593,10 @@ export default function EditBlueprintConfiguration(props) { <FormControlLabel value="disabledTurn" control={<StyledRadio />} - label={i18next.t("disable_turn_configuration", "Disable TURN configuration")} + label={i18next.t( + "disable_turn_configuration", + "Disable TURN configuration" + )} /> </RadioGroup> </FormControl> @@ -556,7 +604,15 @@ export default function EditBlueprintConfiguration(props) { <Grid item xs={12} sm={12} md={4}></Grid> <Grid item xs={12} sm={12} md={12}> <FormControl component="fieldset"> - <FormLabel component="legend">DHT Proxy <CustomPopupState message={i18next.t("dht_configuration_popup", "Configure the DHT proxy server used by this account")} /></FormLabel> + <FormLabel component="legend"> + DHT Proxy{" "} + <CustomPopupState + message={i18next.t( + "dht_configuration_popup", + "Configure the DHT proxy server used by this account" + )} + /> + </FormLabel> <RadioGroup value={selectedDHTProxyOption} aria-label="gender" @@ -566,12 +622,18 @@ export default function EditBlueprintConfiguration(props) { <FormControlLabel value="defaultDHTProxy" control={<StyledRadio />} - label={i18next.t("use_jami_default_dht_proxy_configuration", "Use Jami default DHT Proxy configuration")} + label={i18next.t( + "use_jami_default_dht_proxy_configuration", + "Use Jami default DHT Proxy configuration" + )} /> <FormControlLabel value="customDHTProxy" control={<StyledRadio />} - label={i18next.t("use_a_custom_dht_proxy_configuration", "Use a custom DHT Proxy configuration")} + label={i18next.t( + "use_a_custom_dht_proxy_configuration", + "Use a custom DHT Proxy configuration" + )} /> <FormGroup row> <FormControl @@ -585,7 +647,10 @@ export default function EditBlueprintConfiguration(props) { }} > <InputLabel htmlFor="proxyServer"> - {i18next.t("dht_proxy_server_name", "DHT proxy server name")} + {i18next.t( + "dht_proxy_server_name", + "DHT proxy server name" + )} </InputLabel> <Input id="proxyServer" @@ -618,7 +683,10 @@ export default function EditBlueprintConfiguration(props) { }} > <InputLabel htmlFor="dhtProxyListUrl"> - {i18next.t("dht_proxy_list_url", "DHT proxy List URL")} + {i18next.t( + "dht_proxy_list_url", + "DHT proxy List URL" + )} </InputLabel> <Input id="proxyServer" @@ -642,7 +710,10 @@ export default function EditBlueprintConfiguration(props) { <FormControlLabel value="disabledDHTProxy" control={<StyledRadio />} - label={i18next.t("disable_dht_proxy_configuration", "Disable DHT Proxy configuration")} + label={i18next.t( + "disable_dht_proxy_configuration", + "Disable DHT Proxy configuration" + )} /> </RadioGroup> </FormControl> diff --git a/jams-react-client/src/views/Blueprint/EditBlueprintPermissions.js b/jams-react-client/src/views/Blueprint/EditBlueprintPermissions.js index aebb2a16..96c4ba95 100644 --- a/jams-react-client/src/views/Blueprint/EditBlueprintPermissions.js +++ b/jams-react-client/src/views/Blueprint/EditBlueprintPermissions.js @@ -18,12 +18,12 @@ import FormControlLabel from "@material-ui/core/FormControlLabel"; import FormLabel from "@material-ui/core/FormLabel"; import Button from "components/CustomButtons/Button.js"; -import AddCircleOutlineIcon from '@material-ui/icons/AddCircleOutline'; +import AddCircleOutlineIcon from "@material-ui/icons/AddCircleOutline"; import Avatar from "@material-ui/core/Avatar"; import Table from "@material-ui/core/Table"; -import TableHead from '@material-ui/core/TableHead'; +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"; @@ -38,14 +38,14 @@ import noProfilePicture from "assets/img/faces/no-profile-picture.png"; import axios from "axios"; import configApiCall from "../../api"; -import { +import { api_path_blueprints, api_path_get_user_directory_search, api_path_get_ns_name_from_addr, - api_path_get_user_profile + api_path_get_user_profile, } from "../../globalUrls"; -import TemporaryDrawer from "components/Drawer/Drawer" +import TemporaryDrawer from "components/Drawer/Drawer"; import dashboardStyle from "assets/jss/material-dashboard-react/views/dashboardStyle.js"; @@ -164,13 +164,13 @@ export default function EditBlueprintPermissions(props) { .then((response) => { let profiles = []; const profilesResults = response.data.profiles; - profilesResults.forEach((profile) =>{ - let existingUser = false; - users.forEach((user)=>{ - if(profile.username === user.username) existingUser = true; - }) - if(!existingUser) profiles.push(profile); - }) + profilesResults.forEach((profile) => { + let existingUser = false; + users.forEach((user) => { + if (profile.username === user.username) existingUser = true; + }); + if (!existingUser) profiles.push(profile); + }); setUsers(profiles); }) .catch((error) => { @@ -212,13 +212,21 @@ export default function EditBlueprintPermissions(props) { setAllowLookup(policyData["allowLookup"]); policyData["defaultModerators"].split("/").forEach((id) => { - if(id !== "undefined" && id !== ""){ - axios(configApiCall(api_path_get_ns_name_from_addr + id), null, null).then((usernameResponse) => { + if (id !== "undefined" && id !== "") { + axios( + configApiCall(api_path_get_ns_name_from_addr + id), + null, + null + ).then((usernameResponse) => { let username = usernameResponse.data.name; - axios(configApiCall(api_path_get_user_profile + username), null, null).then((userProfileResponse) => { + axios( + configApiCall(api_path_get_user_profile + username), + null, + null + ).then((userProfileResponse) => { let userProfiles = blueprintModerators; userProfileResponse.data["id"] = id; - userProfiles.push(userProfileResponse.data) + userProfiles.push(userProfileResponse.data); setBlueprintModerators(userProfiles); // This state update is added to refresh the list of moderators setOpenDrawer(true); @@ -226,7 +234,7 @@ export default function EditBlueprintPermissions(props) { }); }); } - }) + }); }) .catch((error) => { console.log( @@ -292,13 +300,25 @@ export default function EditBlueprintPermissions(props) { setOpen(false); setSeverity("success"); setOpen(true); - setMessage(i18next.t("updated_blueprint_permissions_successfully", "Blueprint permissions successfully updated.")); + setMessage( + i18next.t( + "updated_blueprint_permissions_successfully", + "Blueprint permissions successfully updated." + ) + ); }) .catch((error) => { setOpen(false); setSeverity("error"); setOpen(true); - setMessage(i18next.t("error_updating_blueprint_permissions", "Error occurred while updating blueprint permissions.") + error + "!"); + setMessage( + i18next.t( + "error_updating_blueprint_permissions", + "Error occurred while updating blueprint permissions." + ) + + error + + "!" + ); }); }; @@ -307,21 +327,24 @@ export default function EditBlueprintPermissions(props) { }; const addModeratorToBlueprint = (user) => { - handleUpdatePermissions("defaultModerators", defaultModerators + user.id + "/"); - setDefaultModerators(defaultModerators + user.id + "/"); - let newBlueprintModerators = blueprintModerators; - newBlueprintModerators.push(user); - setBlueprintModerators(newBlueprintModerators); - } + handleUpdatePermissions( + "defaultModerators", + defaultModerators + user.id + "/" + ); + setDefaultModerators(defaultModerators + user.id + "/"); + let newBlueprintModerators = blueprintModerators; + newBlueprintModerators.push(user); + setBlueprintModerators(newBlueprintModerators); + }; const removeModeratorFromBlueprint = (user) => { - let newDefaultModerators = defaultModerators.replace( user.id + "/", "") + let newDefaultModerators = defaultModerators.replace(user.id + "/", ""); handleUpdatePermissions("defaultModerators", newDefaultModerators); setDefaultModerators(newDefaultModerators); let newBlueprintModerators = blueprintModerators; newBlueprintModerators.splice(newBlueprintModerators.indexOf(user), 1); setBlueprintModerators(newBlueprintModerators); - } + }; return ( <div> @@ -336,16 +359,19 @@ export default function EditBlueprintPermissions(props) { {message} </Alert> </Snackbar> - <TemporaryDrawer - openDrawer={openDrawer} - setOpenDrawer={setOpenDrawer} - direction="right" - placeholder={i18next.t("add_moderator_to_blueprint", "Add moderator to blueprint ...")} - searchTargets={searchUsers} - targets={users} - existingTargets={blueprintModerators} - addElementToTarget={addModeratorToBlueprint} - type="user" + <TemporaryDrawer + openDrawer={openDrawer} + setOpenDrawer={setOpenDrawer} + direction="right" + placeholder={i18next.t( + "add_moderator_to_blueprint", + "Add moderator to blueprint ..." + )} + searchTargets={searchUsers} + targets={users} + existingTargets={blueprintModerators} + addElementToTarget={addModeratorToBlueprint} + type="user" /> <GridContainer> <GridItem xs={12} sm={12} md={6}> @@ -354,202 +380,285 @@ export default function EditBlueprintPermissions(props) { <CardIcon color="info"> <PriorityHighOutlinedIcon /> </CardIcon> - <p className={classes.cardCategory}>{i18next.t("permissions", "Permissions")}</p> + <p className={classes.cardCategory}> + {i18next.t("permissions", "Permissions")} + </p> <h3 className={classes.cardTitle}>{props.blueprintName}</h3> </CardHeader> <CardBody profile> <div className={classes.root}> <Grid container spacing={5}> <Grid item xs={12} sm={12} md={12}> - <Grid container spacing={2}> - <Grid item xs={12} sm={12} md={12}> - <FormLabel component="legend">Call parameters</FormLabel> - <FormGroup row> - <FormControlLabel - control={ - <Checkbox - checked={videoEnabled} - color="primary" - onChange={(e) => { - setVideoEnabled(e.target.checked); - handleUpdatePermissions( - "videoEnabled", - e.target.checked - ); - }} - name="videoEnabled" + <Grid container spacing={2}> + <Grid item xs={12} sm={12} md={12}> + <FormLabel component="legend"> + Call parameters + </FormLabel> + <FormGroup row> + <FormControlLabel + control={ + <Checkbox + checked={videoEnabled} + color="primary" + onChange={(e) => { + setVideoEnabled(e.target.checked); + handleUpdatePermissions( + "videoEnabled", + e.target.checked + ); + }} + name="videoEnabled" + /> + } + label={i18next.t( + "allow_video_calls", + "Allow video calls" + )} /> - } - label={i18next.t("allow_video_calls", "Allow video calls")} - /> - <CustomPopupState message={i18next.t("allow_incoming_calls_from_unknown_allow_video_calls_info", "If this option is disabled, only audio calls are allowed.")} /> - </FormGroup> - <FormGroup row> - <FormControlLabel - control={ - <Checkbox - checked={publicInCalls} - color="primary" - onChange={(e) => { - setPublicInCalls(e.target.checked); - handleUpdatePermissions( - "publicInCalls", - e.target.checked - ); - }} - name="publicInCalls" + <CustomPopupState + message={i18next.t( + "allow_incoming_calls_from_unknown_allow_video_calls_info", + "If this option is disabled, only audio calls are allowed." + )} /> - } - label={i18next.t("allow_incoming_calls_from_unknown_contacts", "Allow incoming calls from unknown contacts")} - /> - <CustomPopupState message={i18next.t("allow_incoming_calls_from_unknown_contacts_info", "If this option is disabled, only contacts from your list can contact you.")} /> - </FormGroup> - <FormGroup row> - <FormControlLabel - control={ - <Checkbox - checked={autoAnswer} - color="primary" - onChange={(e) => { - setAutoAnswer(e.target.checked); - handleUpdatePermissions( - "autoAnswer", - e.target.checked - ); - }} - name="autoAnswer" + </FormGroup> + <FormGroup row> + <FormControlLabel + control={ + <Checkbox + checked={publicInCalls} + color="primary" + onChange={(e) => { + setPublicInCalls(e.target.checked); + handleUpdatePermissions( + "publicInCalls", + e.target.checked + ); + }} + name="publicInCalls" + /> + } + label={i18next.t( + "allow_incoming_calls_from_unknown_contacts", + "Allow incoming calls from unknown contacts" + )} /> - } - label={i18next.t("auto_answer_calss", "Auto answer calls")} - /> - <CustomPopupState message={i18next.t("auto_answer_calls_info", "If this option is enabled, incoming calls are automatically answered. This option can be useful to monitor your house or a particular room when you are away from home for example.")} /> - </FormGroup> - </Grid> - <Grid item xs={12} sm={12} md={12}> - <FormLabel component="legend">{i18next.t("local_lan","Local LAN")}</FormLabel> - <FormGroup row> - <FormControlLabel - control={ - <Checkbox - checked={peerDiscovery} - color="primary" - onChange={(e) => { - setPeerDiscovery(e.target.checked); - handleUpdatePermissions( - "peerDiscovery", - e.target.checked - ); - }} - name="peerDiscovery" + <CustomPopupState + message={i18next.t( + "allow_incoming_calls_from_unknown_contacts_info", + "If this option is disabled, only contacts from your list can contact you." + )} /> - } - label={i18next.t("allow_use_of_jami_in_local_lan", "Allow discovery of other peers on a local network")} - /> - <CustomPopupState message={i18next.t("local_lan_info", "If this option is enabled, you can communicate with connected contacts on you local lan, even if your lan is disconnected from the Internet.")} /> - </FormGroup> - </Grid> - <Grid item xs={12} sm={12} md={12}> - <FormLabel component="legend">{i18next.t("contact_management", "Contact management")}</FormLabel> - <FormGroup row> - <FormControlLabel - control={ - <Checkbox - checked={allowLookup} - color="primary" - onChange={(e) => { - setAllowLookup(e.target.checked); - handleUpdatePermissions( - "allowLookup", - e.target.checked - ); - }} - name="allowLookup" + </FormGroup> + <FormGroup row> + <FormControlLabel + control={ + <Checkbox + checked={autoAnswer} + color="primary" + onChange={(e) => { + setAutoAnswer(e.target.checked); + handleUpdatePermissions( + "autoAnswer", + e.target.checked + ); + }} + name="autoAnswer" + /> + } + label={i18next.t( + "auto_answer_calss", + "Auto answer calls" + )} /> - } - label={i18next.t("allow_jami_user_to_search_for_other_contacts", "Allow user to add new contacts")} - /> - <CustomPopupState message={i18next.t("lookup_info", "If this option is disabled, user can not search and add new contacts")} /> - </FormGroup> - </Grid> - <Grid item xs={12} sm={12} md={12}> - + <CustomPopupState + message={i18next.t( + "auto_answer_calls_info", + "If this option is enabled, incoming calls are automatically answered. This option can be useful to monitor your house or a particular room when you are away from home for example." + )} + /> + </FormGroup> + </Grid> + <Grid item xs={12} sm={12} md={12}> + <FormLabel component="legend"> + {i18next.t("local_lan", "Local LAN")} + </FormLabel> + <FormGroup row> + <FormControlLabel + control={ + <Checkbox + checked={peerDiscovery} + color="primary" + onChange={(e) => { + setPeerDiscovery(e.target.checked); + handleUpdatePermissions( + "peerDiscovery", + e.target.checked + ); + }} + name="peerDiscovery" + /> + } + label={i18next.t( + "allow_use_of_jami_in_local_lan", + "Allow discovery of other peers on a local network" + )} + /> + <CustomPopupState + message={i18next.t( + "local_lan_info", + "If this option is enabled, you can communicate with connected contacts on you local lan, even if your lan is disconnected from the Internet." + )} + /> + </FormGroup> + </Grid> + <Grid item xs={12} sm={12} md={12}> + <FormLabel component="legend"> + {i18next.t( + "contact_management", + "Contact management" + )} + </FormLabel> + <FormGroup row> + <FormControlLabel + control={ + <Checkbox + checked={allowLookup} + color="primary" + onChange={(e) => { + setAllowLookup(e.target.checked); + handleUpdatePermissions( + "allowLookup", + e.target.checked + ); + }} + name="allowLookup" + /> + } + label={i18next.t( + "allow_jami_user_to_search_for_other_contacts", + "Allow user to add new contacts" + )} + /> + <CustomPopupState + message={i18next.t( + "lookup_info", + "If this option is disabled, user can not search and add new contacts" + )} + /> + </FormGroup> + </Grid> + <Grid item xs={12} sm={12} md={12}></Grid> </Grid> </Grid> </Grid> - </Grid> </div> </CardBody> </Card> </GridItem> <GridItem xs={12} sm={12} md={12}> - <h3>Rendezvous mode</h3> - - <FormGroup row> - <FormControlLabel - control={ - <Switch - checked={rendezVous} - color="primary" - onChange={(e) => { - setRendezVous(e.target.checked); - handleUpdatePermissions( - "rendezVous", - e.target.checked - ); - }} - name="rendezVous" - inputProps={{ "aria-label": "secondary checkbox" }} - /> - } - label={i18next.t("convert_your_account_into_a_rendezvous_point", "Set the account as a Rendezvous point")} - /> - <CustomPopupState message={i18next.t("rendezvous_info", "If this option is enabled, incoming calls are automatically added to a conference room.")}/> - <Button disabled={!rendezVous} color="primary" onClick={() => {setOpenDrawer(true)}}><AddCircleOutlineIcon /> {i18next.t("add_moderator_to", "Add moderator to")} {props.blueprintName}</Button> - <CustomPopupState message={i18next.t("rendezvous_moderators_info", "Moderators can manage the Rendezvous point.")} /> - </FormGroup> - <Table className={classes.table}> - <TableHead> - <TableRow> - <TableCell align="left"></TableCell> - <TableCell align="left">{i18next.t("username", "Username")}</TableCell> - <TableCell align="left">{i18next.t("first_name", "First name")}</TableCell> - <TableCell align="left">{i18next.t("last_name", "Last name")}</TableCell> - <TableCell align="right">{i18next.t("action", "Action")}</TableCell> - </TableRow> - </TableHead> - <TableBody> - {blueprintModerators.map(user => - <TableRow key={user.username} className={classes.tableRow}> - <TableCell className={tableCellClasses}> - <Link to={`/user/${user.username}`}> - <Avatar - style={{ marginRight: "10px" }} - alt={user.username} - src={ - user.profilePicture - ? "data:image/png;base64, " + user.profilePicture - : noProfilePicture - } - /> - </Link> - </TableCell> - <TableCell className={tableCellClasses}> - <Link to={`/user/${user.username}`}>{user.username}</Link> - </TableCell> - <TableCell className={tableCellClasses}> - <Link to={`/user/${user.username}`}>{user.firstName}</Link> - </TableCell> - <TableCell className={tableCellClasses}> - <Link to={`/user/${user.username}`}>{user.lastName}</Link> - </TableCell> - <TableCell align="right" className={classes.tableActions}> - <Button disabled={!rendezVous} color="primary" onClick={() => removeModeratorFromBlueprint(user)}>{i18next.t("remove_moderator", "Remove moderator")}</Button> - </TableCell> - </TableRow> - )} - </TableBody> - </Table> - </GridItem> + <h3>Rendezvous mode</h3> + + <FormGroup row> + <FormControlLabel + control={ + <Switch + checked={rendezVous} + color="primary" + onChange={(e) => { + setRendezVous(e.target.checked); + handleUpdatePermissions("rendezVous", e.target.checked); + }} + name="rendezVous" + inputProps={{ "aria-label": "secondary checkbox" }} + /> + } + label={i18next.t( + "convert_your_account_into_a_rendezvous_point", + "Set the account as a Rendezvous point" + )} + /> + <CustomPopupState + message={i18next.t( + "rendezvous_info", + "If this option is enabled, incoming calls are automatically added to a conference room." + )} + /> + <Button + disabled={!rendezVous} + color="primary" + onClick={() => { + setOpenDrawer(true); + }} + > + <AddCircleOutlineIcon />{" "} + {i18next.t("add_moderator_to", "Add moderator to")}{" "} + {props.blueprintName} + </Button> + <CustomPopupState + message={i18next.t( + "rendezvous_moderators_info", + "Moderators can manage the Rendezvous point." + )} + /> + </FormGroup> + <Table className={classes.table}> + <TableHead> + <TableRow> + <TableCell align="left"></TableCell> + <TableCell align="left"> + {i18next.t("username", "Username")} + </TableCell> + <TableCell align="left"> + {i18next.t("first_name", "First name")} + </TableCell> + <TableCell align="left"> + {i18next.t("last_name", "Last name")} + </TableCell> + <TableCell align="right"> + {i18next.t("action", "Action")} + </TableCell> + </TableRow> + </TableHead> + <TableBody> + {blueprintModerators.map((user) => ( + <TableRow key={user.username} className={classes.tableRow}> + <TableCell className={tableCellClasses}> + <Link to={`/user/${user.username}`}> + <Avatar + style={{ marginRight: "10px" }} + alt={user.username} + src={ + user.profilePicture + ? "data:image/png;base64, " + user.profilePicture + : noProfilePicture + } + /> + </Link> + </TableCell> + <TableCell className={tableCellClasses}> + <Link to={`/user/${user.username}`}>{user.username}</Link> + </TableCell> + <TableCell className={tableCellClasses}> + <Link to={`/user/${user.username}`}>{user.firstName}</Link> + </TableCell> + <TableCell className={tableCellClasses}> + <Link to={`/user/${user.username}`}>{user.lastName}</Link> + </TableCell> + <TableCell align="right" className={classes.tableActions}> + <Button + disabled={!rendezVous} + color="primary" + onClick={() => removeModeratorFromBlueprint(user)} + > + {i18next.t("remove_moderator", "Remove moderator")} + </Button> + </TableCell> + </TableRow> + ))} + </TableBody> + </Table> + </GridItem> </GridContainer> </div> ); diff --git a/jams-react-client/src/views/Blueprints/Blueprints.js b/jams-react-client/src/views/Blueprints/Blueprints.js index dc9ffcd0..a3a81a95 100644 --- a/jams-react-client/src/views/Blueprints/Blueprints.js +++ b/jams-react-client/src/views/Blueprints/Blueprints.js @@ -18,7 +18,7 @@ import Input from "@material-ui/core/Input"; import InputAdornment from "@material-ui/core/InputAdornment"; import GroupIcon from "@material-ui/icons/Group"; -import PersonIcon from '@material-ui/icons/Person'; +import PersonIcon from "@material-ui/icons/Person"; import Search from "@material-ui/icons/Search"; import DeleteOutlineIcon from "@material-ui/icons/DeleteOutline"; import InfoIcon from "@material-ui/icons/Info"; @@ -81,7 +81,7 @@ const styles = { }, whiteButtonText: { color: "white", - } + }, }; const useStyles = makeStyles(styles); @@ -239,7 +239,6 @@ export default function Blueprints() { history.push("/blueprints"); }; - return ( <div> <Dialog @@ -249,7 +248,7 @@ export default function Blueprints() { aria-describedby="alert-dialog-description" > <DialogTitle id="alert-dialog-title"> - {i18next.t("create_blueprint", "Create blueprint")} + {i18next.t("create_blueprint", "Create blueprint")} </DialogTitle> <DialogContent> <DialogContentText id="alert-dialog-description"> @@ -259,7 +258,7 @@ export default function Blueprints() { error={blueprintNameExits} > <InputLabel htmlFor="blueprintName"> - {i18next.t("blueprint_name", "Blueprint name")} + {i18next.t("blueprint_name", "Blueprint name")} </InputLabel> <Input id="blueprintName" @@ -276,15 +275,29 @@ export default function Blueprints() { /> </FormControl> {disableCreate && blueprintName.length > 0 && ( - <p>{i18next.t("blueprint_name_already_exists", "Blueprint name already exists!")}</p> + <p> + {i18next.t( + "blueprint_name_already_exists", + "Blueprint name already exists!" + )} + </p> )} {disableCreate && blueprintName.length === 0 && ( - <p>{i18next.t("blueprint_name_is_empty", "Blueprint name is empty")}</p> + <p> + {i18next.t( + "blueprint_name_is_empty", + "Blueprint name is empty" + )} + </p> )} </DialogContentText> </DialogContent> <DialogActions> - <Button onClick={handleClose} color="info" className={classes.whiteButtonText}> + <Button + onClick={handleClose} + color="info" + className={classes.whiteButtonText} + > Cancel </Button> <Button @@ -304,23 +317,23 @@ export default function Blueprints() { aria-describedby="alert-dialog-description" > <DialogTitle id="alert-dialog-title"> - {i18next.t("remove_blueprint", "Remove blueprint")} + {i18next.t("remove_blueprint", "Remove blueprint")} </DialogTitle> <DialogContent> <DialogContentText id="alert-dialog-description"> - {i18next.t("are_you_sure_you_want_to_delete", "Are you sure you want to delete")}{" "} + {i18next.t( + "are_you_sure_you_want_to_delete", + "Are you sure you want to delete" + )}{" "} <strong>{removedBlueprint}</strong> ? </DialogContentText> </DialogContent> <DialogActions> - <Button - onClick={() => setOpenRemoveDialog(false)} - color="primary" - > + <Button onClick={() => setOpenRemoveDialog(false)} color="primary"> {i18next.t("cancel", "Cancel")} </Button> <Button onClick={removeBlueprint} color="info" autoFocus> - {i18next.t("remove", "Remove")} + {i18next.t("remove", "Remove")} </Button> </DialogActions> </Dialog> @@ -332,7 +345,8 @@ export default function Blueprints() { href="#contained-buttons" onClick={(e) => setOpen(true)} > - <AddCircleOutlineIcon /> {i18next.t("create_blueprint", "Create blueprint")} + <AddCircleOutlineIcon />{" "} + {i18next.t("create_blueprint", "Create blueprint")} </Button> <div className={classes.searchWrapper}> {!zeroBlueprint && ( @@ -341,9 +355,15 @@ export default function Blueprints() { className: classes.margin + " " + classes.search, }} inputProps={{ - placeholder: i18next.t("search_blueprints_placeholder", "Search blueprints…"), + placeholder: i18next.t( + "search_blueprints_placeholder", + "Search blueprints…" + ), inputProps: { - "aria-label": i18next.t("search_blueprints", "Search blueprints"), + "aria-label": i18next.t( + "search_blueprints", + "Search blueprints" + ), }, onKeyUp: (e) => setSearchValue(e.target.value), }} @@ -360,17 +380,13 @@ export default function Blueprints() { {zeroBlueprint ? ( <div className={classes.blueprintsNotFound}> <InfoIcon /> - <p style={{ marginLeft: "10px" }}>{i18next.t("no_blueprints_found", "No blueprints found")}</p> + <p style={{ marginLeft: "10px" }}> + {i18next.t("no_blueprints_found", "No blueprints found")} + </p> </div> ) : ( blueprints.map((blueprint) => ( - <GridItem - xs={12} - sm={6} - md={3} - lg={2} - xl={2} - key={blueprint.name}> + <GridItem xs={12} sm={6} md={3} lg={2} xl={2} key={blueprint.name}> <Card profile> <Link to={`/blueprint/${blueprint.name}`}> <CardBody profile> @@ -381,18 +397,27 @@ export default function Blueprints() { </h3> <ul> <li> - {JSON.parse(blueprint.policyData).rendezVous == true ? (<p><GroupIcon - fontSize="small" - style={{ marginRight: "10px" }} - />{i18next.t("rendezvous", "Rendezvous")}</p>) : <p><PersonIcon - fontSize="small" - style={{ marginRight: "10px" }} - />{i18next.t("standalone", "Standalone")}</p> - } + {JSON.parse(blueprint.policyData).rendezVous == true ? ( + <p> + <GroupIcon + fontSize="small" + style={{ marginRight: "10px" }} + /> + {i18next.t("rendezvous", "Rendezvous")} + </p> + ) : ( + <p> + <PersonIcon + fontSize="small" + style={{ marginRight: "10px" }} + /> + {i18next.t("standalone", "Standalone")} + </p> + )} </li> </ul> - </CardBody> - </Link> + </CardBody> + </Link> <CardFooter> <IconButton color="secondary" diff --git a/jams-react-client/src/views/Dashboard/Dashboard.js b/jams-react-client/src/views/Dashboard/Dashboard.js index 0678d244..d696cc51 100755 --- a/jams-react-client/src/views/Dashboard/Dashboard.js +++ b/jams-react-client/src/views/Dashboard/Dashboard.js @@ -34,7 +34,7 @@ import { bugs, website, server } from "variables/general.js"; import { dailySalesChart, emailsSubscriptionChart, - completedTasksChart + completedTasksChart, } from "variables/charts.js"; import styles from "assets/jss/material-dashboard-react/views/dashboardStyle.js"; @@ -62,7 +62,7 @@ export default function Dashboard() { <Danger> <Warning /> </Danger> - <a href="#pablo" onClick={e => e.preventDefault()}> + <a href="#pablo" onClick={(e) => e.preventDefault()}> Get more space </a> </div> @@ -210,7 +210,7 @@ export default function Dashboard() { tasksIndexes={[0, 1, 2, 3]} tasks={bugs} /> - ) + ), }, { tabName: "Website", @@ -221,7 +221,7 @@ export default function Dashboard() { tasksIndexes={[0, 1]} tasks={website} /> - ) + ), }, { tabName: "Server", @@ -232,8 +232,8 @@ export default function Dashboard() { tasksIndexes={[0, 1, 2]} tasks={server} /> - ) - } + ), + }, ]} /> </GridItem> @@ -253,7 +253,7 @@ export default function Dashboard() { ["1", "Dakota Rice", "$36,738", "Niger"], ["2", "Minerva Hooper", "$23,789", "Curaçao"], ["3", "Sage Rodriguez", "$56,142", "Netherlands"], - ["4", "Philip Chaney", "$38,735", "Korea, South"] + ["4", "Philip Chaney", "$38,735", "Korea, South"], ]} /> </CardBody> diff --git a/jams-react-client/src/views/Groups/EditGroup.js b/jams-react-client/src/views/Groups/EditGroup.js index a957259a..540020f2 100644 --- a/jams-react-client/src/views/Groups/EditGroup.js +++ b/jams-react-client/src/views/Groups/EditGroup.js @@ -6,7 +6,7 @@ import classnames from "classnames"; import { makeStyles } from "@material-ui/core/styles"; // core components -import Grid from '@material-ui/core/Grid'; +import Grid from "@material-ui/core/Grid"; import GridItem from "components/Grid/GridItem.js"; import GridContainer from "components/Grid/GridContainer.js"; import Button from "components/CustomButtons/Button.js"; @@ -14,40 +14,39 @@ 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 FormControl from '@material-ui/core/FormControl'; -import Input from '@material-ui/core/Input'; -import InputAdornment from '@material-ui/core/InputAdornment'; +import FormControl from "@material-ui/core/FormControl"; +import Input from "@material-ui/core/Input"; +import InputAdornment from "@material-ui/core/InputAdornment"; import Table from "@material-ui/core/Table"; -import TableHead from '@material-ui/core/TableHead'; +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 InputLabel from "@material-ui/core/InputLabel"; - import Select from "@material-ui/core/Select"; -import AddCircleOutlineIcon from '@material-ui/icons/AddCircleOutline'; -import EditIcon from '@material-ui/icons/Edit'; -import PeopleOutlineIcon from '@material-ui/icons/PeopleOutline'; +import AddCircleOutlineIcon from "@material-ui/icons/AddCircleOutline"; +import EditIcon from "@material-ui/icons/Edit"; +import PeopleOutlineIcon from "@material-ui/icons/PeopleOutline"; -import IconButton from '@material-ui/core/IconButton'; -import SaveIcon from '@material-ui/icons/Save'; +import IconButton from "@material-ui/core/IconButton"; +import SaveIcon from "@material-ui/icons/Save"; -import axios from "axios" -import configApiCall from "../../api" +import axios from "axios"; +import configApiCall from "../../api"; import { - api_path_get_list_group, - api_path_get_group, - api_path_put_update_group, - api_path_get_user_directory_search, - api_path_get_user_profile, - api_path_blueprints, - api_path_get_group_members, - api_path_post_group_member, - api_path_delete_group_member -} from "../../globalUrls" + api_path_get_list_group, + api_path_get_group, + api_path_put_update_group, + api_path_get_user_directory_search, + api_path_get_user_profile, + api_path_blueprints, + api_path_get_group_members, + api_path_post_group_member, + api_path_delete_group_member, +} from "../../globalUrls"; import dashboardStyle from "assets/jss/material-dashboard-react/views/dashboardStyle.js"; import devicesStyle from "assets/jss/material-dashboard-react/components/devicesStyle.js"; @@ -55,7 +54,7 @@ import Avatar from "@material-ui/core/Avatar"; import noProfilePicture from "assets/img/faces/no-profile-picture.png"; -import TemporaryDrawer from "components/Drawer/Drawer" +import TemporaryDrawer from "components/Drawer/Drawer"; import * as tool from "../../tools"; import i18next from "i18next"; @@ -65,402 +64,472 @@ import auth from "auth.js"; import { debounce } from "lodash"; const useStyles = makeStyles((theme) => ({ - ...devicesStyle, - ...dashboardStyle, - root: { - flexGrow: 1 - }, - cardCategoryWhite: { - color: "rgba(255,255,255,.62)", - margin: "0", - fontSize: "14px", - marginTop: "0", - marginBottom: "0" - }, - cardTitleWhite: { - color: "#FFFFFF", - marginTop: "0px", - minHeight: "auto", - fontWeight: "300", - fontFamily: "'Roboto', 'Helvetica', 'Arial', sans-serif", - marginBottom: "3px", - textDecoration: "none" - }, - input: { - display: 'none', - }, - profileAsBackground: { - backgroundSize: "100% 100%", - width: "80px", - height: "80px", - }, - centerIconMiddle: { - position:"relative", - top: "20px", - left: "15px" - }, - dialogPaper: { - minHeight: '60vh', - maxHeight: '60vh', - minWidth: '80vh', - maxWidth: '80vh' - }, - inputBottomMargin: { - marginBottom: "1rem" - } + ...devicesStyle, + ...dashboardStyle, + root: { + flexGrow: 1, + }, + cardCategoryWhite: { + color: "rgba(255,255,255,.62)", + margin: "0", + fontSize: "14px", + marginTop: "0", + marginBottom: "0", + }, + cardTitleWhite: { + color: "#FFFFFF", + marginTop: "0px", + minHeight: "auto", + fontWeight: "300", + fontFamily: "'Roboto', 'Helvetica', 'Arial', sans-serif", + marginBottom: "3px", + textDecoration: "none", + }, + input: { + display: "none", + }, + profileAsBackground: { + backgroundSize: "100% 100%", + width: "80px", + height: "80px", + }, + centerIconMiddle: { + position: "relative", + top: "20px", + left: "15px", + }, + dialogPaper: { + minHeight: "60vh", + maxHeight: "60vh", + minWidth: "80vh", + maxWidth: "80vh", + }, + inputBottomMargin: { + marginBottom: "1rem", + }, })); export default function EditGroup(props) { - const classes = useStyles(); - const history = useHistory(); - - const [name, setName] = React.useState(""); - const [newName, setNewName] = React.useState(""); - const [blueprints, setBlueprints] = React.useState([]); - const [selectedBlueprint, setSelectedBlueprint] = React.useState({ - value: 0, - label: "No blueprint", - }); - const [groupMembers, setGroupMembers] = React.useState([]); - const [openDrawer, setOpenDrawer] = React.useState(false); - const [groupNameExits, setGroupNameExits] = React.useState(false); - const [users, setUsers] = React.useState([]); - - const getUserInfo = username => new Promise((resolve, reject) => { - axios( - configApiCall( - api_path_get_user_profile + username, - "GET", - null, - null - ) - ) - .then((response) => { - resolve(response.data); - }) - .catch((error) => { - reject(error); - }); - }) - - const getGroup = () => { - axios(configApiCall(api_path_get_group + props.groupid, 'GET', null, null)).then((response) => { - let group = response.data; - - axios(configApiCall(api_path_blueprints + "?name=*", "GET", null, null)) - .then((response) => { - setBlueprints(response.data); - let index = 0; - response.data.map((blueprint) => { - if(blueprint.name == group["blueprint"]) - setSelectedBlueprint({ value: index, label: blueprint.name }); - index += 1; - }); - }) - .catch((error) => { - if (error.response.status === 401) { - auth.authenticated = false; - history.push("/signin"); - } - if (error.response.status === 500) { - setBlueprints([]); - } - }); - - axios(configApiCall(api_path_get_group_members + props.groupid, 'GET', null, null)).then((response) => { - let members = response.data; - members.forEach((member) => { - getUserInfo(member.username).then((userInfo) => { - let newGroupMembers = groupMembers; - newGroupMembers.push(userInfo); - setGroupMembers(newGroupMembers); - - //This state update is added to force the groupMembers to displayed on first page loading - setOpenDrawer(true); - setOpenDrawer(false); -  }) - }) - }).catch((error) => { - if (error.response.status === 404) { - setGroupMembers([]); - } - if (error.response.status === 401) { - auth.authenticated = false; - history.push("/signin"); - } - }) - - - setName(group.name); - setNewName(group.name); - - }).catch((error) => { - console.log("Error fetching group members of: " + props.name + " " + error) + const classes = useStyles(); + const history = useHistory(); + + const [name, setName] = React.useState(""); + const [newName, setNewName] = React.useState(""); + const [blueprints, setBlueprints] = React.useState([]); + const [selectedBlueprint, setSelectedBlueprint] = React.useState({ + value: 0, + label: "No blueprint", + }); + const [groupMembers, setGroupMembers] = React.useState([]); + const [openDrawer, setOpenDrawer] = React.useState(false); + const [groupNameExits, setGroupNameExits] = React.useState(false); + const [users, setUsers] = React.useState([]); + + const getUserInfo = (username) => + new Promise((resolve, reject) => { + axios( + configApiCall(api_path_get_user_profile + username, "GET", null, null) + ) + .then((response) => { + resolve(response.data); }) - } - - const getBlueprintsOptions = (inputs) => { - let blueprintsOptions = []; - let index = 0; - if (blueprints.length === 0) - blueprintsOptions.push({ value: index, label: "No blueprint found" }); - else { - blueprints.map((blueprint) => { - blueprintsOptions.push({ value: index, label: blueprint.name }); - index += 1; - }); - } - return blueprintsOptions; - }; - - const blueprintsOptionsItems = tool.buildSelectMenuItems(getBlueprintsOptions(blueprints)); - - React.useEffect(()=>{ - getGroup(); - searchUsers(); - }, []) + .catch((error) => { + reject(error); + }); + }); - const updateGroup = (blueprintValue) => { + const getGroup = () => { + axios(configApiCall(api_path_get_group + props.groupid, "GET", null, null)) + .then((response) => { + let group = response.data; - let data = { - "name": newName, - "blueprint": blueprintValue ? blueprintValue : selectedBlueprint.label - } - - axios(configApiCall(api_path_put_update_group + props.groupid, 'PUT', data, null)).then((response) => { - setName(newName); - }).catch((error) => { - console.log("Error updating group: " + error) - }) - } - - const searchUsers = (value) => { - axios( - configApiCall( - api_path_get_user_directory_search, - "GET", - { queryString: value ? value : "*", page: "1" }, - null - ) - ) + axios(configApiCall(api_path_blueprints + "?name=*", "GET", null, null)) .then((response) => { - let profiles = []; - const profilesResults = response.data.profiles; - profilesResults.forEach((profile) =>{ - let existingUser = false; - users.forEach((user)=>{ - if(profile.username === user.username) existingUser = true; - }) - if(!existingUser) profiles.push(profile); - }) - setUsers(profiles); + setBlueprints(response.data); + let index = 0; + response.data.map((blueprint) => { + if (blueprint.name == group["blueprint"]) + setSelectedBlueprint({ value: index, label: blueprint.name }); + index += 1; + }); }) .catch((error) => { - setUsers([]); if (error.response.status === 401) { auth.authenticated = false; history.push("/signin"); } - }); - }; - - const addUserInGroup = (user) => { - let data = { - "username": user.username - } - axios(configApiCall(api_path_post_group_member + props.groupid, 'POST', data, null)).then((response) => { - let newGroupMembers = groupMembers; - newGroupMembers.push(user); - setGroupMembers(newGroupMembers); - - //This state update is added to force the groupMembers to refreshed displayed - setOpenDrawer(true); - setOpenDrawer(false); - }).catch((error) => { - if (error.response.status === 409) { - alert(`${user.username} is already part of ${name}`); + if (error.response.status === 500) { + setBlueprints([]); } - else - console.log("Error updating group: " + error) - }) - } - - const deleteUserFromGroup = (user) => { - let data = { - "username": user.username - } - axios(configApiCall(api_path_delete_group_member + props.groupid, 'DELETE', data, null)).then((response) => { - let newGroupMembers = groupMembers; - newGroupMembers.splice(newGroupMembers.indexOf(user), 1); - setGroupMembers(newGroupMembers); - - //This state update is added to force the groupMembers to refreshed displayed - setOpenDrawer(true); - setOpenDrawer(false); - }).catch((error) => { - console.log("Error updating group: " + error) - }) - } - - const handleBlueprintsChange = (e) => { - updateGroup(getBlueprintsOptions()[e.target.value].label !== "No blueprint found" ? getBlueprintsOptions()[e.target.value].label : ""); - setSelectedBlueprint(getBlueprintsOptions()[e.target.value]); - } - - const initCheckGroupNameExists = useCallback( - debounce( - (searchGroupNameValue) => - handleCheckGroupNameExists(searchGroupNameValue), - 500 - ), - [] - ); - - - const handleCheckGroupNameExists = (searchGroupNameValue) => { + }); axios( configApiCall( - api_path_get_list_group + "?groupName=" + searchGroupNameValue, + api_path_get_group_members + props.groupid, "GET", null, null ) ) .then((response) => { - setGroupNameExits(false); - response.data.forEach((group) => { - if(searchGroupNameValue === group.name){ - setGroupNameExits(true); - } + let members = response.data; + members.forEach((member) => { + getUserInfo(member.username).then((userInfo) => { + let newGroupMembers = groupMembers; + newGroupMembers.push(userInfo); + setGroupMembers(newGroupMembers); + + //This state update is added to force the groupMembers to displayed on first page loading + setOpenDrawer(true); + setOpenDrawer(false); + }); }); }) .catch((error) => { - setGroupNameExits(false); + if (error.response.status === 404) { + setGroupMembers([]); + } + if (error.response.status === 401) { + auth.authenticated = false; + history.push("/signin"); + } + }); + + setName(group.name); + setNewName(group.name); + }) + .catch((error) => { + console.log( + "Error fetching group members of: " + props.name + " " + error + ); + }); + }; + + const getBlueprintsOptions = (inputs) => { + let blueprintsOptions = []; + let index = 0; + if (blueprints.length === 0) + blueprintsOptions.push({ value: index, label: "No blueprint found" }); + else { + blueprints.map((blueprint) => { + blueprintsOptions.push({ value: index, label: blueprint.name }); + index += 1; + }); + } + return blueprintsOptions; + }; + + const blueprintsOptionsItems = tool.buildSelectMenuItems( + getBlueprintsOptions(blueprints) + ); + + React.useEffect(() => { + getGroup(); + searchUsers(); + }, []); + + const updateGroup = (blueprintValue) => { + let data = { + name: newName, + blueprint: blueprintValue ? blueprintValue : selectedBlueprint.label, + }; + + axios( + configApiCall( + api_path_put_update_group + props.groupid, + "PUT", + data, + null + ) + ) + .then((response) => { + setName(newName); + }) + .catch((error) => { + console.log("Error updating group: " + error); + }); + }; + + const searchUsers = (value) => { + axios( + configApiCall( + api_path_get_user_directory_search, + "GET", + { queryString: value ? value : "*", page: "1" }, + null + ) + ) + .then((response) => { + let profiles = []; + const profilesResults = response.data.profiles; + profilesResults.forEach((profile) => { + let existingUser = false; + users.forEach((user) => { + if (profile.username === user.username) existingUser = true; }); - }; - - const tableCellClasses = classnames(classes.tableCell); - - return( - <div> - <TemporaryDrawer - openDrawer={openDrawer} - setOpenDrawer={setOpenDrawer} - direction="right" - placeholder={i18next.t("add_user_to_group", "Add user to group ...")} - searchTargets={searchUsers} - targets={users} - existingTargets={groupMembers} - addElementToTarget={addUserInGroup} - targetName={name} - type="user" - /> - <GridContainer> - <GridItem xs={12} sm={12} md={6}> - <Card profile> - <CardHeader color="info" stats icon> - <CardIcon color="info"> - <EditIcon /> - </CardIcon> - <p className={classes.cardCategory}>{i18next.t("edit_group", "Edit group")}</p> - <h3 className={classes.cardTitle}>{name}</h3> - </CardHeader> - <CardBody profile> - <div className={classes.root}> - <Grid container spacing={2}> - <Grid item xs={12} sm={12} md={12}> - <FormControl className={classes.margin} size="medium" error={groupNameExits}> - <Input - id="name" - placeholder={name} - startAdornment={ - <InputAdornment position="start"> - <PeopleOutlineIcon /> - </InputAdornment> - } - endAdornment={ - <IconButton color="primary" aria-label="update name" component="span" - onClick={() => { - updateGroup(); - }} - disabled={groupNameExits || name == newName} - > - <SaveIcon /> - </IconButton> - } - onChange={e => { - setNewName(e.target.value); - initCheckGroupNameExists(e.target.value) - }} - /> - </FormControl> - </Grid> - <Grid item xs={12} sm={12} md={12}> - <InputLabel className={classes.inputBottomMargin} htmlFor="blueprint">{i18next.t("select_blueprint", "Select a blueprint")}</InputLabel> - <FormControl className={classes.margin} fullWidth> - <Select - labelId="demo-simple-select-label" - fullWidth - value={selectedBlueprint.value} - onChange={handleBlueprintsChange} - variant="outlined" - children={blueprintsOptionsItems} - disabled={blueprints.length === 0} - /> - </FormControl> - </Grid> - </Grid> - </div> - </CardBody> - </Card> - </GridItem> - <GridItem xs={12} sm={12} md={12}> - <Button color="primary" onClick={() => {setOpenDrawer(true)}}><AddCircleOutlineIcon /> {i18next.t("add_user_to", "Add user to")} {name}</Button> - <Table className={classes.table}> - <TableHead> - <TableRow> - <TableCell align="left"></TableCell> - <TableCell align="left">{i18next.t("username", "Username")}</TableCell> - <TableCell align="left">{i18next.t("first_name", "First name")}</TableCell> - <TableCell align="left">{i18next.t("last_name", "Last name")}</TableCell> - <TableCell align="right">{i18next.t("action", "Action")}</TableCell> - </TableRow> - </TableHead> - <TableBody> - {groupMembers.map(user => - <TableRow key={user.username} className={classes.tableRow}> - <TableCell className={tableCellClasses}> - <Link to={`/user/${user.username}`}> - <Avatar - style={{ marginRight: "10px" }} - alt={user.username} - src={ - user.profilePicture - ? "data:image/png;base64, " + user.profilePicture - : noProfilePicture - } - /> - </Link> - </TableCell> - <TableCell className={tableCellClasses}> - <Link to={`/user/${user.username}`}>{user.username}</Link> - </TableCell> - <TableCell className={tableCellClasses}> - <Link to={`/user/${user.username}`}>{user.firstName}</Link> - </TableCell> - <TableCell className={tableCellClasses}> - <Link to={`/user/${user.username}`}>{user.lastName}</Link> - </TableCell> - <TableCell align="right" className={classes.tableActions}> - <Button color="primary" onClick={() => deleteUserFromGroup(user)}>{i18next.t("remove_user", "Remove user")}</Button> - </TableCell> - </TableRow> - )} - </TableBody> - </Table> - </GridItem> - </GridContainer> - </div> + if (!existingUser) profiles.push(profile); + }); + setUsers(profiles); + }) + .catch((error) => { + setUsers([]); + if (error.response.status === 401) { + auth.authenticated = false; + history.push("/signin"); + } + }); + }; + + const addUserInGroup = (user) => { + let data = { + username: user.username, + }; + axios( + configApiCall( + api_path_post_group_member + props.groupid, + "POST", + data, + null + ) + ) + .then((response) => { + let newGroupMembers = groupMembers; + newGroupMembers.push(user); + setGroupMembers(newGroupMembers); + + //This state update is added to force the groupMembers to refreshed displayed + setOpenDrawer(true); + setOpenDrawer(false); + }) + .catch((error) => { + if (error.response.status === 409) { + alert(`${user.username} is already part of ${name}`); + } else console.log("Error updating group: " + error); + }); + }; + + const deleteUserFromGroup = (user) => { + let data = { + username: user.username, + }; + axios( + configApiCall( + api_path_delete_group_member + props.groupid, + "DELETE", + data, + null + ) + ) + .then((response) => { + let newGroupMembers = groupMembers; + newGroupMembers.splice(newGroupMembers.indexOf(user), 1); + setGroupMembers(newGroupMembers); + + //This state update is added to force the groupMembers to refreshed displayed + setOpenDrawer(true); + setOpenDrawer(false); + }) + .catch((error) => { + console.log("Error updating group: " + error); + }); + }; + + const handleBlueprintsChange = (e) => { + updateGroup( + getBlueprintsOptions()[e.target.value].label !== "No blueprint found" + ? getBlueprintsOptions()[e.target.value].label + : "" ); -} \ No newline at end of file + setSelectedBlueprint(getBlueprintsOptions()[e.target.value]); + }; + + const initCheckGroupNameExists = useCallback( + debounce( + (searchGroupNameValue) => + handleCheckGroupNameExists(searchGroupNameValue), + 500 + ), + [] + ); + + const handleCheckGroupNameExists = (searchGroupNameValue) => { + axios( + configApiCall( + api_path_get_list_group + "?groupName=" + searchGroupNameValue, + "GET", + null, + null + ) + ) + .then((response) => { + setGroupNameExits(false); + response.data.forEach((group) => { + if (searchGroupNameValue === group.name) { + setGroupNameExits(true); + } + }); + }) + .catch((error) => { + setGroupNameExits(false); + }); + }; + + const tableCellClasses = classnames(classes.tableCell); + + return ( + <div> + <TemporaryDrawer + openDrawer={openDrawer} + setOpenDrawer={setOpenDrawer} + direction="right" + placeholder={i18next.t("add_user_to_group", "Add user to group ...")} + searchTargets={searchUsers} + targets={users} + existingTargets={groupMembers} + addElementToTarget={addUserInGroup} + targetName={name} + type="user" + /> + <GridContainer> + <GridItem xs={12} sm={12} md={6}> + <Card profile> + <CardHeader color="info" stats icon> + <CardIcon color="info"> + <EditIcon /> + </CardIcon> + <p className={classes.cardCategory}> + {i18next.t("edit_group", "Edit group")} + </p> + <h3 className={classes.cardTitle}>{name}</h3> + </CardHeader> + <CardBody profile> + <div className={classes.root}> + <Grid container spacing={2}> + <Grid item xs={12} sm={12} md={12}> + <FormControl + className={classes.margin} + size="medium" + error={groupNameExits} + > + <Input + id="name" + placeholder={name} + startAdornment={ + <InputAdornment position="start"> + <PeopleOutlineIcon /> + </InputAdornment> + } + endAdornment={ + <IconButton + color="primary" + aria-label="update name" + component="span" + onClick={() => { + updateGroup(); + }} + disabled={groupNameExits || name == newName} + > + <SaveIcon /> + </IconButton> + } + onChange={(e) => { + setNewName(e.target.value); + initCheckGroupNameExists(e.target.value); + }} + /> + </FormControl> + </Grid> + <Grid item xs={12} sm={12} md={12}> + <InputLabel + className={classes.inputBottomMargin} + htmlFor="blueprint" + > + {i18next.t("select_blueprint", "Select a blueprint")} + </InputLabel> + <FormControl className={classes.margin} fullWidth> + <Select + labelId="demo-simple-select-label" + fullWidth + value={selectedBlueprint.value} + onChange={handleBlueprintsChange} + variant="outlined" + children={blueprintsOptionsItems} + disabled={blueprints.length === 0} + /> + </FormControl> + </Grid> + </Grid> + </div> + </CardBody> + </Card> + </GridItem> + <GridItem xs={12} sm={12} md={12}> + <Button + color="primary" + onClick={() => { + setOpenDrawer(true); + }} + > + <AddCircleOutlineIcon /> {i18next.t("add_user_to", "Add user to")}{" "} + {name} + </Button> + <Table className={classes.table}> + <TableHead> + <TableRow> + <TableCell align="left"></TableCell> + <TableCell align="left"> + {i18next.t("username", "Username")} + </TableCell> + <TableCell align="left"> + {i18next.t("first_name", "First name")} + </TableCell> + <TableCell align="left"> + {i18next.t("last_name", "Last name")} + </TableCell> + <TableCell align="right"> + {i18next.t("action", "Action")} + </TableCell> + </TableRow> + </TableHead> + <TableBody> + {groupMembers.map((user) => ( + <TableRow key={user.username} className={classes.tableRow}> + <TableCell className={tableCellClasses}> + <Link to={`/user/${user.username}`}> + <Avatar + style={{ marginRight: "10px" }} + alt={user.username} + src={ + user.profilePicture + ? "data:image/png;base64, " + user.profilePicture + : noProfilePicture + } + /> + </Link> + </TableCell> + <TableCell className={tableCellClasses}> + <Link to={`/user/${user.username}`}>{user.username}</Link> + </TableCell> + <TableCell className={tableCellClasses}> + <Link to={`/user/${user.username}`}>{user.firstName}</Link> + </TableCell> + <TableCell className={tableCellClasses}> + <Link to={`/user/${user.username}`}>{user.lastName}</Link> + </TableCell> + <TableCell align="right" className={classes.tableActions}> + <Button + color="primary" + onClick={() => deleteUserFromGroup(user)} + > + {i18next.t("remove_user", "Remove user")} + </Button> + </TableCell> + </TableRow> + ))} + </TableBody> + </Table> + </GridItem> + </GridContainer> + </div> + ); +} diff --git a/jams-react-client/src/views/Groups/Groups.js b/jams-react-client/src/views/Groups/Groups.js index 161f44ba..472fd01c 100644 --- a/jams-react-client/src/views/Groups/Groups.js +++ b/jams-react-client/src/views/Groups/Groups.js @@ -32,7 +32,7 @@ import { api_path_get_list_group, api_path_delete_group, api_path_blueprints, - api_path_get_group_members + api_path_get_group_members, } from "globalUrls"; import AddCircleOutlineIcon from "@material-ui/icons/AddCircleOutline"; @@ -89,8 +89,8 @@ const styles = { color: "white", }, inputBottomMargin: { - marginBottom: "1rem" - } + marginBottom: "1rem", + }, }; const useStyles = makeStyles(styles); @@ -111,8 +111,8 @@ export default function Groups() { const [groupNameExits, setGroupNameExits] = React.useState(false); const [removedGroup, setRemovedGroup] = React.useState({ - "id": 0, - "name": "groupeName" + id: 0, + name: "groupeName", }); const [openRemoveDialog, setOpenRemoveDialog] = React.useState(); @@ -160,20 +160,20 @@ export default function Groups() { const getBlueprints = () => { axios(configApiCall(api_path_blueprints + "?name=*", "GET", null, null)) - .then((response) => { - setBlueprints(response.data); - setSelectedBlueprint(getBlueprintsOptions()[0]); - }) - .catch((error) => { - if (error.response.status === 401) { - auth.authenticated = false; - history.push("/signin"); - } - if (error.response.status === 500) { - setBlueprints([]); - } - }); - } + .then((response) => { + setBlueprints(response.data); + setSelectedBlueprint(getBlueprintsOptions()[0]); + }) + .catch((error) => { + if (error.response.status === 401) { + auth.authenticated = false; + history.push("/signin"); + } + if (error.response.status === 500) { + setBlueprints([]); + } + }); + }; useEffect(() => { setLoading(true); @@ -187,25 +187,32 @@ export default function Groups() { }); }, 500); - axios( - configApiCall(api_path_get_list_group, "GET", null, null) - ) + axios(configApiCall(api_path_get_list_group, "GET", null, null)) .then((response) => { let allGroups = response.data; - allGroups.forEach((group)=> { - axios(configApiCall(api_path_get_group_members + group.id, 'GET', null, null)).then((response) => { - group["groupMembersLength"] = response.data.length; - }).catch((error) => { - if (error.response.status === 401) { - auth.authenticated = false; - history.push("/"); - } - if (error.response.status === 404) { - group["groupMembersLength"] = 0; - } - }); - }) + allGroups.forEach((group) => { + axios( + configApiCall( + api_path_get_group_members + group.id, + "GET", + null, + null + ) + ) + .then((response) => { + group["groupMembersLength"] = response.data.length; + }) + .catch((error) => { + if (error.response.status === 401) { + auth.authenticated = false; + history.push("/"); + } + if (error.response.status === 404) { + group["groupMembersLength"] = 0; + } + }); + }); setGroups(allGroups); getBlueprints(); setLoading(false); @@ -215,7 +222,7 @@ export default function Groups() { auth.authenticated = false; history.push("/signin"); } - if (error.response.status === 404){ + if (error.response.status === 404) { getBlueprints(); setZeroGroup(true); } @@ -240,7 +247,7 @@ export default function Groups() { setDisableCreate(false); setGroupNameExits(false); allGroups.forEach((group) => { - if(searchGroupNameValue === group.name){ + if (searchGroupNameValue === group.name) { setDisableCreate(true); setGroupNameExits(true); } @@ -310,12 +317,14 @@ export default function Groups() { return ( <div> <h4> - {i18next.t("you_are_not_allowed_to_access_this_section", "You are not allowed to access this section. Please contact your administrator to get administrator privileges.")} + {i18next.t( + "you_are_not_allowed_to_access_this_section", + "You are not allowed to access this section. Please contact your administrator to get administrator privileges." + )} </h4> </div> ); - } - else { + } else { return ( <div> <Dialog @@ -324,7 +333,9 @@ export default function Groups() { aria-labelledby="alert-dialog-title" aria-describedby="alert-dialog-description" > - <DialogTitle id="alert-dialog-title">{i18next.t("create_group", "Create group")}</DialogTitle> + <DialogTitle id="alert-dialog-title"> + {i18next.t("create_group", "Create group")} + </DialogTitle> <DialogContent> <DialogContentText id="alert-dialog-description"> <Grid container spacing={2}> @@ -334,7 +345,9 @@ export default function Groups() { error={groupNameExits} fullWidth > - <InputLabel htmlFor="groupName">{i18next.t("group_name", "Group name")}</InputLabel> + <InputLabel htmlFor="groupName"> + {i18next.t("group_name", "Group name")} + </InputLabel> <Input id="groupName" placeholder={i18next.t("group_name", "Group name")} @@ -350,14 +363,26 @@ export default function Groups() { /> </FormControl> {disableCreate && groupName.length > 0 && ( - <p>{i18next.t("group_name_already_exists", "Group name already exists!")}</p> + <p> + {i18next.t( + "group_name_already_exists", + "Group name already exists!" + )} + </p> )} {disableCreate && groupName.length === 0 && ( - <p>{i18next.t("group_name_is_empty", "Group name is empty")}</p> + <p> + {i18next.t("group_name_is_empty", "Group name is empty")} + </p> )} </Grid> <Grid item xs={12} sm={12} md={12}> - <InputLabel className={classes.inputBottomMargin} htmlFor="blueprint">{i18next.t("select_blueprint", "Select a blueprint")}</InputLabel> + <InputLabel + className={classes.inputBottomMargin} + htmlFor="blueprint" + > + {i18next.t("select_blueprint", "Select a blueprint")} + </InputLabel> <Select labelId="demo-simple-select-label" fullWidth @@ -372,7 +397,11 @@ export default function Groups() { </DialogContentText> </DialogContent> <DialogActions> - <Button onClick={handleCloseCreate} color="info" className={classes.whiteButtonText}> + <Button + onClick={handleCloseCreate} + color="info" + className={classes.whiteButtonText} + > Cancel </Button> <Button @@ -391,10 +420,16 @@ export default function Groups() { aria-labelledby="alert-dialog-title" aria-describedby="alert-dialog-description" > - <DialogTitle id="alert-dialog-title">{i18next.t("remove_group", "Remove group")}</DialogTitle> + <DialogTitle id="alert-dialog-title"> + {i18next.t("remove_group", "Remove group")} + </DialogTitle> <DialogContent> <DialogContentText id="alert-dialog-description"> - {i18next.t("are_you_sure_you_want_to_delete", "Are you sure you want to delete")} <strong>{removedGroup.name}</strong> ? + {i18next.t( + "are_you_sure_you_want_to_delete", + "Are you sure you want to delete" + )}{" "} + <strong>{removedGroup.name}</strong> ? </DialogContentText> </DialogContent> <DialogActions> @@ -415,7 +450,8 @@ export default function Groups() { href="#contained-buttons" onClick={(e) => setOpenCreate(true)} > - <AddCircleOutlineIcon /> {i18next.t("create_group", "Create group")} + <AddCircleOutlineIcon />{" "} + {i18next.t("create_group", "Create group")} </Button> } <div className={classes.searchWrapper}> @@ -425,7 +461,10 @@ export default function Groups() { className: classes.margin + " " + classes.search, }} inputProps={{ - placeholder: i18next.t("search_groups_placeholder", "Search groups…"), + placeholder: i18next.t( + "search_groups_placeholder", + "Search groups…" + ), inputProps: { "aria-label": i18next.t("search_groups", "Search groups"), }, @@ -435,7 +474,7 @@ export default function Groups() { )} {!zeroGroup && <Search />} <div className={classes.loading}> - {!zeroGroup && loading && ( + {!zeroGroup && loading && ( <LinearProgress variant="determinate" value={progress} /> )} </div> @@ -443,7 +482,10 @@ export default function Groups() { </GridItem> {zeroGroup ? ( <div className={classes.groupsNotFound}> - <InfoIcon /> <p style={{ marginLeft: "10px" }}>{i18next.t("no_groups_found", "No groups Found")}</p> + <InfoIcon />{" "} + <p style={{ marginLeft: "10px" }}> + {i18next.t("no_groups_found", "No groups Found")} + </p> </div> ) : ( groups @@ -457,13 +499,7 @@ export default function Groups() { } }) .map((group) => ( - <GridItem - xs={12} - sm={6} - md={3} - lg={2} - xl={2} - key={group.name}> + <GridItem xs={12} sm={6} md={3} lg={2} xl={2} key={group.name}> <Card profile> <Link to={`/group/${group.id}`}> <CardBody profile> diff --git a/jams-react-client/src/views/Maps/Maps.js b/jams-react-client/src/views/Maps/Maps.js index e33aba91..e37f3d1c 100755 --- a/jams-react-client/src/views/Maps/Maps.js +++ b/jams-react-client/src/views/Maps/Maps.js @@ -3,7 +3,7 @@ import { withScriptjs, withGoogleMap, GoogleMap, - Marker + Marker, } from "react-google-maps"; const CustomSkinMap = withScriptjs( @@ -20,8 +20,8 @@ const CustomSkinMap = withScriptjs( stylers: [ { saturation: 43 }, { lightness: -11 }, - { hue: "#0088ff" } - ] + { hue: "#0088ff" }, + ], }, { featureType: "road", @@ -29,51 +29,51 @@ const CustomSkinMap = withScriptjs( stylers: [ { hue: "#ff0000" }, { saturation: -100 }, - { lightness: 99 } - ] + { lightness: 99 }, + ], }, { featureType: "road", elementType: "geometry.stroke", - stylers: [{ color: "#808080" }, { lightness: 54 }] + stylers: [{ color: "#808080" }, { lightness: 54 }], }, { featureType: "landscape.man_made", elementType: "geometry.fill", - stylers: [{ color: "#ece2d9" }] + stylers: [{ color: "#ece2d9" }], }, { featureType: "poi.park", elementType: "geometry.fill", - stylers: [{ color: "#ccdca1" }] + stylers: [{ color: "#ccdca1" }], }, { featureType: "road", elementType: "labels.text.fill", - stylers: [{ color: "#767676" }] + stylers: [{ color: "#767676" }], }, { featureType: "road", elementType: "labels.text.stroke", - stylers: [{ color: "#ffffff" }] + stylers: [{ color: "#ffffff" }], }, { featureType: "poi", stylers: [{ visibility: "off" }] }, { featureType: "landscape.natural", elementType: "geometry.fill", - stylers: [{ visibility: "on" }, { color: "#b8cb93" }] + stylers: [{ visibility: "on" }, { color: "#b8cb93" }], }, { featureType: "poi.park", stylers: [{ visibility: "on" }] }, { featureType: "poi.sports_complex", - stylers: [{ visibility: "on" }] + stylers: [{ visibility: "on" }], }, { featureType: "poi.medical", stylers: [{ visibility: "on" }] }, { featureType: "poi.business", - stylers: [{ visibility: "simplified" }] - } - ] + stylers: [{ visibility: "simplified" }], + }, + ], }} > <Marker position={{ lat: 40.748817, lng: -73.985428 }} /> diff --git a/jams-react-client/src/views/Notifications/Notifications.js b/jams-react-client/src/views/Notifications/Notifications.js index b10db293..bb8ed858 100755 --- a/jams-react-client/src/views/Notifications/Notifications.js +++ b/jams-react-client/src/views/Notifications/Notifications.js @@ -23,11 +23,11 @@ const styles = { margin: "0", fontSize: "14px", marginTop: "0", - marginBottom: "0" + marginBottom: "0", }, "& a,& a:hover,& a:focus": { - color: "#FFFFFF" - } + color: "#FFFFFF", + }, }, cardTitleWhite: { color: "#FFFFFF", @@ -41,9 +41,9 @@ const styles = { color: "#777", fontSize: "65%", fontWeight: "400", - lineHeight: "1" - } - } + lineHeight: "1", + }, + }, }; const useStyles = makeStyles(styles); @@ -66,12 +66,12 @@ export default function Notifications() { } }; }); - const showNotification = place => { + const showNotification = (place) => { switch (place) { case "tl": if (!tl) { setTL(true); - setTimeout(function() { + setTimeout(function () { setTL(false); }, 6000); } @@ -79,7 +79,7 @@ export default function Notifications() { case "tc": if (!tc) { setTC(true); - setTimeout(function() { + setTimeout(function () { setTC(false); }, 6000); } @@ -87,7 +87,7 @@ export default function Notifications() { case "tr": if (!tr) { setTR(true); - setTimeout(function() { + setTimeout(function () { setTR(false); }, 6000); } @@ -95,7 +95,7 @@ export default function Notifications() { case "bl": if (!bl) { setBL(true); - setTimeout(function() { + setTimeout(function () { setBL(false); }, 6000); } @@ -103,7 +103,7 @@ export default function Notifications() { case "bc": if (!bc) { setBC(true); - setTimeout(function() { + setTimeout(function () { setBC(false); }, 6000); } @@ -111,7 +111,7 @@ export default function Notifications() { case "br": if (!br) { setBR(true); - setTimeout(function() { + setTimeout(function () { setBR(false); }, 6000); } diff --git a/jams-react-client/src/views/RTLPage/RTLPage.js b/jams-react-client/src/views/RTLPage/RTLPage.js index eca4168e..e6d12796 100644 --- a/jams-react-client/src/views/RTLPage/RTLPage.js +++ b/jams-react-client/src/views/RTLPage/RTLPage.js @@ -36,7 +36,7 @@ import SnackbarContent from "components/Snackbar/SnackbarContent.js"; import { dailySalesChart, emailsSubscriptionChart, - completedTasksChart + completedTasksChart, } from "variables/charts.js"; import styles from "assets/jss/material-dashboard-react/views/rtlStyle.js"; @@ -47,16 +47,16 @@ let bugs = [ "Ø·Ø±Ø§Ø Ú¯Ø±Ø§Ùیک از این متن به عنوان عنصری از ترکیب بندی برای پر کردن؟", " نخست از متن‌های آزمایشی Ùˆ بی‌معنی استÙاده می‌کنند تا صرÙا به مشتری یا صاØب کار خود نشان دهند؟", "همان Øال کار آنها به نوعی وابسته به متن می‌باشد", - " آنها با استÙاده از Ù…Øتویات ساختگی، صÙØÙ‡ گراÙیکی خود را صÙØه‌آرایی می‌کنند" + " آنها با استÙاده از Ù…Øتویات ساختگی، صÙØÙ‡ گراÙیکی خود را صÙØه‌آرایی می‌کنند", ]; let website = [ "بعد از اینکه متن در آن قرار گیرد چگونه به نظر می‌رسد Ùˆ قلم‌ها Ùˆ اندازه‌بندی‌ها چگونه در نظر گرÙته", - "اولیه Ø´Ú©Ù„ ظاهری Ùˆ Ú©Ù„ÛŒ Ø·Ø±Ø Ø³Ùارش گرÙته شده استÙاده Ù…ÛŒ نماید؟" + "اولیه Ø´Ú©Ù„ ظاهری Ùˆ Ú©Ù„ÛŒ Ø·Ø±Ø Ø³Ùارش گرÙته شده استÙاده Ù…ÛŒ نماید؟", ]; let server = [ "گراÙیکی نشانگر چگونگی نوع Ùˆ اندازه Ùونت Ùˆ ظاهر متن باشد. معمولا طراØان گراÙیک برای صÙØه‌آرایی، نخست از متن‌های آزمایشی؟", "از این متن به عنوان عنصری از ترکیب بندی برای پر کردن صÙØÙ‡ Ùˆ ارایه اولیه Ø´Ú©Ù„ ظاهری Ùˆ Ú©Ù„ÛŒ Ø·Ø±Ø Ø³Ùارش گرÙته شده استÙاده Ù…ÛŒ نماید، تا از نظر گراÙیکی نشانگر چگونگی نوع Ùˆ اندازه Ùونت Ùˆ ظاهر متن باشد. معمولا طراØان گراÙیک برای صÙØه‌آرایی، نخست از متن‌های آزمایشی ØŸ", - "از متن‌های آزمایشی Ùˆ بی‌معنی استÙاده می‌کنند تا صرÙا به مشتری یا صاØب کار خود نشان دهند؟" + "از متن‌های آزمایشی Ùˆ بی‌معنی استÙاده می‌کنند تا صرÙا به مشتری یا صاØب کار خود نشان دهند؟", ]; const useStyles = makeStyles(styles); @@ -82,7 +82,7 @@ export default function RTLPage() { <Danger> <Warning /> </Danger> - <a href="#pablo" onClick={e => e.preventDefault()}> + <a href="#pablo" onClick={(e) => e.preventDefault()}> Ùضای بیشتری داشته باشید... </a> </div> @@ -232,7 +232,7 @@ export default function RTLPage() { tasks={bugs} rtlActive /> - ) + ), }, { tabName: "وبسایت", @@ -244,7 +244,7 @@ export default function RTLPage() { tasks={website} rtlActive /> - ) + ), }, { tabName: "سرور", @@ -256,8 +256,8 @@ export default function RTLPage() { tasks={server} rtlActive /> - ) - } + ), + }, ]} /> </GridItem> @@ -277,7 +277,7 @@ export default function RTLPage() { ["1", "اØمد Øسینی ", "$36,738", "مازندران"], ["2", "مینا رضایی ", "$23,789", "گلستان"], ["3", "مبینا اØمدپور ", "$56,142", "تهران"], - ["4", "جلال آقایی ", "$38,735", "شهرکرد"] + ["4", "جلال آقایی ", "$38,735", "شهرکرد"], ]} /> </CardBody> @@ -340,7 +340,7 @@ export default function RTLPage() { <GridItem xs={12} sm={12} md={6}> <Card profile> <CardAvatar profile> - <a href="#pablo" onClick={e => e.preventDefault()}> + <a href="#pablo" onClick={(e) => e.preventDefault()}> <img src={avatar} alt="..." /> </a> </CardAvatar> diff --git a/jams-react-client/src/views/Settings/General.js b/jams-react-client/src/views/Settings/General.js index 3c5fea31..4e4bfcfc 100644 --- a/jams-react-client/src/views/Settings/General.js +++ b/jams-react-client/src/views/Settings/General.js @@ -30,7 +30,7 @@ import i18next from "i18next"; import LanguagePicker from "../../components/LanguagePicker/LanguagePicker"; -const pjson = require('../../../package.json'); +const pjson = require("../../../package.json"); let generator = require("generate-password"); @@ -71,7 +71,12 @@ export default function General(props) { axios(configApiCall(api_path_put_update_user, "PUT", data, null)) .then(() => { props.setSeverity("success"); - props.setErrorMessage(i18next.t("admin_password_updated_successfully", "Administrator password successfully updated.")); + props.setErrorMessage( + i18next.t( + "admin_password_updated_successfully", + "Administrator password successfully updated." + ) + ); props.setError(true); }) .catch((error) => { @@ -100,7 +105,9 @@ export default function General(props) { */ const passwordSchema = Yup.object().shape({ - password: Yup.string().required(i18next.t("password_is_required", "Password is required!")), + password: Yup.string().required( + i18next.t("password_is_required", "Password is required!") + ), passwordConfirmation: Yup.string().oneOf( [Yup.ref("password"), null], i18next.t("password_must_match", "Passwords must match") @@ -116,168 +123,192 @@ export default function General(props) { return ( <GridContainer> - <Grid item xs={12} sm={12} md={6}> - <Card profile> - <CardHeader color="info" stats icon></CardHeader> - <CardBody profile> - <Formik - initialValues={{ - password: "", - confirmPassword: "", - }} - validationSchema={passwordSchema} - onSubmit={changePassword} - > - {({ - isValid, - dirty, - handleSubmit, - values, - setFieldValue, - touched, - errors, - }) => ( - <form onSubmit={handleSubmit} className={classes.form}> - <Grid container spacing={2}> - <Grid item lg={6} style={{ display: "flex"}}> - <Typography variant="p" gutterBottom color="primary"> - {i18next.t("change_language", "Change language")} - </Typography> - </Grid> - <Grid item lg={6} ><LanguagePicker navigationTarget={"/admin/settings"} /></Grid> - <Grid item lg={6} > - <Typography variant="p" gutterBottom color="primary"> - {i18next.t("enter_the_following_information_below_to_change_your_admin_password", "Enter the following information to change your admin password.")} - </Typography> - </Grid> - <Grid item lg={6} > - <FormikField - name="password" - label={i18next.t("password", "Password")} - placeholder={i18next.t("password", "Password")} - type={passwordVisible ? "text" : "password"} - startAdornment={ - <InputAdornment position="start"> - <VpnKeyIcon /> - </InputAdornment> - } - endAdornment={ - <IconButton - aria-label="toggle password visibility" - onMouseDown={handleMouseDownPassword} - onMouseUp={handleMouseUpPassword} - > - {passwordVisible ? ( - <VisibilityIcon /> - ) : ( - <VisibilityOffIcon /> - )} - </IconButton> - } - handleChange={() => {}} - onKeyUpError={false} - onKeyUpErrorMessage="" - /> - {touched.password && errors.password ? ( - <span>{errors.password}</span> - ) : null} - - <FormikField - name="confirmPassword" - label={i18next.t("Confirm password", "Confirm password")} - placeholder={i18next.t("Confirm password", "Confirm password")} - type={passwordVisible ? "text" : "password"} - startAdornment={ - <InputAdornment position="start"> - <VpnKeyIcon /> - </InputAdornment> - } - endAdornment={ - <IconButton - aria-label="toggle password visibility" - onMouseDown={handleMouseDownPassword} - onMouseUp={handleMouseUpPassword} - > - {passwordVisible ? ( - <VisibilityIcon /> - ) : ( - <VisibilityOffIcon /> - )} - </IconButton> - } - handleChange={() => {}} - onKeyUpError={false} - onKeyUpErrorMessage="" - /> - {touched.confirmPassword && errors.confirmPassword ? ( - <span>{errors.confirmPassword}</span> - ) : null} - - <Button - variant="contained" - color="info" - size="large" - className={classes.button} - startIcon={<RefreshIcon />} - onClick={() => { - const newGeneratedPassword = passwordGenerator(); - setFieldValue("password", newGeneratedPassword, false); - setFieldValue("confirmPassword", newGeneratedPassword, false); - setCopied(false); - setGenerated(true); - }} - > - {i18next.t("generate", "Generate")} - </Button> - <CopyToClipboard - text={values.password} - onCopy={() => { - setCopied(true); - setGenerated(false); - }} - > - <Button - variant="contained" - color="info" - size="large" - className={classes.button} - startIcon={<FileCopyIcon />} - > - {i18next.t("copy_to_clipboard", "Copy to clipboard")} - </Button> - </CopyToClipboard> - {copied ? ( - <span style={{ marginLeft: "10px" }}>{i18next.t("copied", "Copied")}</span> - ) : null} - {generated ? ( - <span style={{ marginLeft: "10px" }}>{i18next.t("generated", "Generated")}</span> - ) : null} + <Grid item xs={12} sm={12} md={6}> + <Card profile> + <CardHeader color="info" stats icon></CardHeader> + <CardBody profile> + <Formik + initialValues={{ + password: "", + confirmPassword: "", + }} + validationSchema={passwordSchema} + onSubmit={changePassword} + > + {({ + isValid, + dirty, + handleSubmit, + values, + setFieldValue, + touched, + errors, + }) => ( + <form onSubmit={handleSubmit} className={classes.form}> + <Grid container spacing={2}> + <Grid item lg={6} style={{ display: "flex" }}> + <Typography variant="p" gutterBottom color="primary"> + {i18next.t("change_language", "Change language")} + </Typography> + </Grid> + <Grid item lg={6}> + <LanguagePicker navigationTarget={"/admin/settings"} /> + </Grid> + <Grid item lg={6}> + <Typography variant="p" gutterBottom color="primary"> + {i18next.t( + "enter_the_following_information_below_to_change_your_admin_password", + "Enter the following information to change your admin password." + )} + </Typography> + </Grid> + <Grid item lg={6}> + <FormikField + name="password" + label={i18next.t("password", "Password")} + placeholder={i18next.t("password", "Password")} + type={passwordVisible ? "text" : "password"} + startAdornment={ + <InputAdornment position="start"> + <VpnKeyIcon /> + </InputAdornment> + } + endAdornment={ + <IconButton + aria-label="toggle password visibility" + onMouseDown={handleMouseDownPassword} + onMouseUp={handleMouseUpPassword} + > + {passwordVisible ? ( + <VisibilityIcon /> + ) : ( + <VisibilityOffIcon /> + )} + </IconButton> + } + handleChange={() => {}} + onKeyUpError={false} + onKeyUpErrorMessage="" + /> + {touched.password && errors.password ? ( + <span>{errors.password}</span> + ) : null} - </Grid> - <Grid item lg={6}></Grid> - <Grid item lg={6}> - <Button - type="submit" - variant="contained" - color="primary" - fullWidth - disable={!isValid && !dirty} - className={classes.submit} - > - {i18next.t("change_admin_password", "Change administrator password")} - </Button> - </Grid> - <Grid item lg={6}> - Version {pjson.version.slice(0, 3)} - </Grid> - </Grid> + <FormikField + name="confirmPassword" + label={i18next.t( + "Confirm password", + "Confirm password" + )} + placeholder={i18next.t( + "Confirm password", + "Confirm password" + )} + type={passwordVisible ? "text" : "password"} + startAdornment={ + <InputAdornment position="start"> + <VpnKeyIcon /> + </InputAdornment> + } + endAdornment={ + <IconButton + aria-label="toggle password visibility" + onMouseDown={handleMouseDownPassword} + onMouseUp={handleMouseUpPassword} + > + {passwordVisible ? ( + <VisibilityIcon /> + ) : ( + <VisibilityOffIcon /> + )} + </IconButton> + } + handleChange={() => {}} + onKeyUpError={false} + onKeyUpErrorMessage="" + /> + {touched.confirmPassword && errors.confirmPassword ? ( + <span>{errors.confirmPassword}</span> + ) : null} - </form> - )} - </Formik> - </CardBody> - </Card> - </Grid> + <Button + variant="contained" + color="info" + size="large" + className={classes.button} + startIcon={<RefreshIcon />} + onClick={() => { + const newGeneratedPassword = passwordGenerator(); + setFieldValue( + "password", + newGeneratedPassword, + false + ); + setFieldValue( + "confirmPassword", + newGeneratedPassword, + false + ); + setCopied(false); + setGenerated(true); + }} + > + {i18next.t("generate", "Generate")} + </Button> + <CopyToClipboard + text={values.password} + onCopy={() => { + setCopied(true); + setGenerated(false); + }} + > + <Button + variant="contained" + color="info" + size="large" + className={classes.button} + startIcon={<FileCopyIcon />} + > + {i18next.t("copy_to_clipboard", "Copy to clipboard")} + </Button> + </CopyToClipboard> + {copied ? ( + <span style={{ marginLeft: "10px" }}> + {i18next.t("copied", "Copied")} + </span> + ) : null} + {generated ? ( + <span style={{ marginLeft: "10px" }}> + {i18next.t("generated", "Generated")} + </span> + ) : null} + </Grid> + <Grid item lg={6}></Grid> + <Grid item lg={6}> + <Button + type="submit" + variant="contained" + color="primary" + fullWidth + disable={!isValid && !dirty} + className={classes.submit} + > + {i18next.t( + "change_admin_password", + "Change administrator password" + )} + </Button> + </Grid> + <Grid item lg={6}> + Version {pjson.version.slice(0, 3)} + </Grid> + </Grid> + </form> + )} + </Formik> + </CardBody> + </Card> + </Grid> </GridContainer> ); } diff --git a/jams-react-client/src/views/Settings/Settings.js b/jams-react-client/src/views/Settings/Settings.js index e8dde972..7b0852c0 100644 --- a/jams-react-client/src/views/Settings/Settings.js +++ b/jams-react-client/src/views/Settings/Settings.js @@ -74,7 +74,6 @@ const styles = { }; export default function Settings(props) { - const [value, setValue] = React.useState(0); const [error, setError] = React.useState(false); const [severity, setSeverity] = React.useState("error"); @@ -87,7 +86,10 @@ export default function Settings(props) { return ( <div> <h4> - {i18next.t("you_are_not_allowed_to_access_this_section", "You are not allowed to access this section. Please contact your administrator to get administrator privileges.")} + {i18next.t( + "you_are_not_allowed_to_access_this_section", + "You are not allowed to access this section. Please contact your administrator to get administrator privileges." + )} </h4> </div> ); @@ -101,7 +103,10 @@ export default function Settings(props) { aria-label="simple tabs example" > <Tab label={i18next.t("general", "General")} {...a11yProps(0)} /> - <Tab label={i18next.t("subscription", "Subscription")} {...a11yProps(1)} /> + <Tab + label={i18next.t("subscription", "Subscription")} + {...a11yProps(1)} + /> </Tabs> </AppBar> <TabPanel value={value} index={0}> diff --git a/jams-react-client/src/views/Settings/Subscription.js b/jams-react-client/src/views/Settings/Subscription.js index a5ab8a6b..1dbfa96f 100644 --- a/jams-react-client/src/views/Settings/Subscription.js +++ b/jams-react-client/src/views/Settings/Subscription.js @@ -1,141 +1,200 @@ -import React, {useEffect} from "react"; -import { useFormik } from 'formik'; -import * as Yup from 'yup'; -import Button from '@material-ui/core/Button'; -import TextField from '@material-ui/core/TextField'; -import Grid from '@material-ui/core/Grid'; -import Typography from '@material-ui/core/Typography'; -import { makeStyles } from '@material-ui/core/styles'; +import React, { useEffect } from "react"; +import { useFormik } from "formik"; +import * as Yup from "yup"; +import Button from "@material-ui/core/Button"; +import TextField from "@material-ui/core/TextField"; +import Grid from "@material-ui/core/Grid"; +import Typography from "@material-ui/core/Typography"; +import { makeStyles } from "@material-ui/core/styles"; import GridContainer from "components/Grid/GridContainer.js"; import Card from "components/Card/Card.js"; import CardHeader from "components/Card/CardHeader.js"; import CardBody from "components/Card/CardBody.js"; -import axios from 'axios'; -import configApiCall from '../../api' -import { api_path_post_configuration_register_license } from '../../globalUrls' +import axios from "axios"; +import configApiCall from "../../api"; +import { api_path_post_configuration_register_license } from "../../globalUrls"; import i18next from "i18next"; const useStyles = makeStyles((theme) => ({ - paper: { - marginTop: theme.spacing(8), - display: 'flex', - flexDirection: 'column', - alignItems: 'center', - }, - avatar: { - margin: theme.spacing(1), - backgroundColor: theme.palette.secondary.main, - }, - form: { - width: '100%', // Fix IE 11 issue. - marginTop: theme.spacing(1), - }, - submit: { - margin: theme.spacing(3, 0, 2), - }, + paper: { + marginTop: theme.spacing(8), + display: "flex", + flexDirection: "column", + alignItems: "center", + }, + avatar: { + margin: theme.spacing(1), + backgroundColor: theme.palette.secondary.main, + }, + form: { + width: "100%", // Fix IE 11 issue. + marginTop: theme.spacing(1), + }, + submit: { + margin: theme.spacing(3, 0, 2), + }, })); export default function Subscription(props) { - const classes = useStyles(); - const [activated, setActivated] = React.useState(false); + const classes = useStyles(); + const [activated, setActivated] = React.useState(false); - useEffect(()=>{ - axios(configApiCall(api_path_post_configuration_register_license, "GET", null, null)).then((response)=>{ - if(response.data["activated"] === true) setActivated(true); - }).catch((error)=>{ - if(error.response.status === 500){ - props.setErrorMessage(i18next.t("an_error_occured_while_getting_license_information", "An error occurred while getting subscription information!")); - props.setSeverity("error"); - props.setError(true); - } - }) - }) + useEffect(() => { + axios( + configApiCall( + api_path_post_configuration_register_license, + "GET", + null, + null + ) + ) + .then((response) => { + if (response.data["activated"] === true) setActivated(true); + }) + .catch((error) => { + if (error.response.status === 500) { + props.setErrorMessage( + i18next.t( + "an_error_occured_while_getting_license_information", + "An error occurred while getting subscription information!" + ) + ); + props.setSeverity("error"); + props.setError(true); + } + }); + }); - /** - * Formik Validation Fields - */ - const formik = useFormik({ - initialValues: { - subscriptionCode: '', - }, - validationSchema: Yup.object({ - subscriptionCode: Yup.string().required(i18next.t("subscription_code_is_required", "Subscription code is required.")), - }), + /** + * Formik Validation Fields + */ + const formik = useFormik({ + initialValues: { + subscriptionCode: "", + }, + validationSchema: Yup.object({ + subscriptionCode: Yup.string().required( + i18next.t( + "subscription_code_is_required", + "Subscription code is required." + ) + ), + }), - onSubmit: values => { - handleSubmit(values); - }, - }); + onSubmit: (values) => { + handleSubmit(values); + }, + }); - function handleSubmit(values) { - //e.preventDefault(); - const jsonData = { - "base64License": values.subscriptionCode - } + function handleSubmit(values) { + //e.preventDefault(); + const jsonData = { + base64License: values.subscriptionCode, + }; - axios(configApiCall(api_path_post_configuration_register_license, "POST", jsonData, null)).then(()=>{ - props.setErrorMessage(i18next.t("license_registred_successfully", "Subscription successfully registered.")); - props.setSeverity("success"); - props.setError(true); - }).catch((error)=>{ - if(error.response.status === 500){ - props.setErrorMessage(i18next.t("a_generic_occured_while_trying_to_load_license_or_license_could_not_be_found", "A generic occurred while trying to load your subscription or your subscription could not be found!")); - props.setSeverity("error"); - props.setError(true); - } - }) - } + axios( + configApiCall( + api_path_post_configuration_register_license, + "POST", + jsonData, + null + ) + ) + .then(() => { + props.setErrorMessage( + i18next.t( + "license_registred_successfully", + "Subscription successfully registered." + ) + ); + props.setSeverity("success"); + props.setError(true); + }) + .catch((error) => { + if (error.response.status === 500) { + props.setErrorMessage( + i18next.t( + "a_generic_occured_while_trying_to_load_license_or_license_could_not_be_found", + "A generic occurred while trying to load your subscription or your subscription could not be found!" + ) + ); + props.setSeverity("error"); + props.setError(true); + } + }); + } - if(!activated){ - return ( - <GridContainer> - <Grid item xs={12} sm={12} md={6}> - <Card profile> + if (!activated) { + return ( + <GridContainer> + <Grid item xs={12} sm={12} md={6}> + <Card profile> <CardHeader color="info" stats icon></CardHeader> <CardBody profile> - <form className={classes.form} noValidate onSubmit={formik.handleSubmit}> + <form + className={classes.form} + noValidate + onSubmit={formik.handleSubmit} + > <Grid container spacing={3}> - <Grid item lg={6}> - <Typography variant="p" gutterBottom color="primary">{i18next.t("paste_your_jams_enterprise_subscription_code_received_from_jami", "Paste your JAMS Enterprise subscription code received from the Jami store.")}</Typography> - </Grid> - <Grid item lg={6}> - <TextField - variant="outlined" - margin="normal" - required - fullWidth - id="subscriptionCode" - label={i18next.t("subscription_code", "Subscription Code")} - name="subscriptionCode" - autoComplete="subscriptionCode" - autoFocus - {...formik.getFieldProps('subscriptionCode')} - /> - {formik.touched.subscriptionCode && formik.errors.subscriptionCode ? (<span>{formik.errors.subscriptionCode}</span>) : null} - <Button - type="submit" - fullWidth - variant="contained" - color="primary" - className={classes.submit} - > - {i18next.t("register", "Register")} - </Button> - </Grid> - </Grid> - </form> + <Grid item lg={6}> + <Typography variant="p" gutterBottom color="primary"> + {i18next.t( + "paste_your_jams_enterprise_subscription_code_received_from_jami", + "Paste your JAMS Enterprise subscription code received from the Jami store." + )} + </Typography> + </Grid> + <Grid item lg={6}> + <TextField + variant="outlined" + margin="normal" + required + fullWidth + id="subscriptionCode" + label={i18next.t( + "subscription_code", + "Subscription Code" + )} + name="subscriptionCode" + autoComplete="subscriptionCode" + autoFocus + {...formik.getFieldProps("subscriptionCode")} + /> + {formik.touched.subscriptionCode && + formik.errors.subscriptionCode ? ( + <span>{formik.errors.subscriptionCode}</span> + ) : null} + <Button + type="submit" + fullWidth + variant="contained" + color="primary" + className={classes.submit} + > + {i18next.t("register", "Register")} + </Button> + </Grid> + </Grid> + </form> </CardBody> - </Card> - </Grid> - </GridContainer> - ); - }else{ - return( - <div><p>{i18next.t("your_license_is_already_activated", "Your subscription is already activated!")}</p></div> - ); - } - -} \ No newline at end of file + </Card> + </Grid> + </GridContainer> + ); + } else { + return ( + <div> + <p> + {i18next.t( + "your_license_is_already_activated", + "Your subscription is already activated!" + )} + </p> + </div> + ); + } +} diff --git a/jams-react-client/src/views/TableList/TableList.js b/jams-react-client/src/views/TableList/TableList.js index 5182022e..de569d14 100755 --- a/jams-react-client/src/views/TableList/TableList.js +++ b/jams-react-client/src/views/TableList/TableList.js @@ -16,11 +16,11 @@ const styles = { margin: "0", fontSize: "14px", marginTop: "0", - marginBottom: "0" + marginBottom: "0", }, "& a,& a:hover,& a:focus": { - color: "#FFFFFF" - } + color: "#FFFFFF", + }, }, cardTitleWhite: { color: "#FFFFFF", @@ -34,9 +34,9 @@ const styles = { color: "#777", fontSize: "65%", fontWeight: "400", - lineHeight: "1" - } - } + lineHeight: "1", + }, + }, }; const useStyles = makeStyles(styles); @@ -63,7 +63,7 @@ export default function TableList() { ["Sage Rodriguez", "Netherlands", "Baileux", "$56,142"], ["Philip Chaney", "Korea, South", "Overland Park", "$38,735"], ["Doris Greene", "Malawi", "Feldkirchen in Kärnten", "$63,542"], - ["Mason Porter", "Chile", "Gloucester", "$78,615"] + ["Mason Porter", "Chile", "Gloucester", "$78,615"], ]} /> </CardBody> @@ -92,16 +92,16 @@ export default function TableList() { "Philip Chaney", "$38,735", "Korea, South", - "Overland Park" + "Overland Park", ], [ "5", "Doris Greene", "$63,542", "Malawi", - "Feldkirchen in Kärnten" + "Feldkirchen in Kärnten", ], - ["6", "Mason Porter", "$78,615", "Chile", "Gloucester"] + ["6", "Mason Porter", "$78,615", "Chile", "Gloucester"], ]} /> </CardBody> diff --git a/jams-react-client/src/views/Typography/Typography.js b/jams-react-client/src/views/Typography/Typography.js index 09822a2b..98b595b7 100755 --- a/jams-react-client/src/views/Typography/Typography.js +++ b/jams-react-client/src/views/Typography/Typography.js @@ -17,7 +17,7 @@ const styles = { typo: { paddingLeft: "25%", marginBottom: "40px", - position: "relative" + position: "relative", }, note: { fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif', @@ -30,14 +30,14 @@ const styles = { left: "0", marginLeft: "20px", position: "absolute", - width: "260px" + width: "260px", }, cardCategoryWhite: { color: "rgba(255,255,255,.62)", margin: "0", fontSize: "14px", marginTop: "0", - marginBottom: "0" + marginBottom: "0", }, cardTitleWhite: { color: "#FFFFFF", @@ -46,8 +46,8 @@ const styles = { fontWeight: "300", fontFamily: "'Roboto', 'Helvetica', 'Arial', sans-serif", marginBottom: "3px", - textDecoration: "none" - } + textDecoration: "none", + }, }; const useStyles = makeStyles(styles); diff --git a/jams-react-client/src/views/UpgradeToPro/UpgradeToPro.js b/jams-react-client/src/views/UpgradeToPro/UpgradeToPro.js index fd6d2af0..1376e00c 100644 --- a/jams-react-client/src/views/UpgradeToPro/UpgradeToPro.js +++ b/jams-react-client/src/views/UpgradeToPro/UpgradeToPro.js @@ -21,11 +21,11 @@ const styles = { margin: "0", fontSize: "14px", marginTop: "0", - marginBottom: "0" + marginBottom: "0", }, "& a,& a:hover,& a:focus": { - color: "#FFFFFF" - } + color: "#FFFFFF", + }, }, cardTitleWhite: { color: "#FFFFFF", @@ -39,15 +39,15 @@ const styles = { color: "#777", fontSize: "65%", fontWeight: "400", - lineHeight: "1" - } + lineHeight: "1", + }, }, tableUpgradeWrapper: { display: "block", width: "100%", overflowX: "auto", WebkitOverflowScrolling: "touch", - MsOverflowStyle: "-ms-autohiding-scrollbar" + MsOverflowStyle: "-ms-autohiding-scrollbar", }, table: { width: "100%", @@ -65,20 +65,20 @@ const styles = { fontWeight: "300", borderTopWidth: "0", borderBottom: "1px solid rgba(0, 0, 0, 0.06)", - textAlign: "inherit" + textAlign: "inherit", }, "& tbody tr td": { padding: "12px 8px", verticalAlign: "middle", - borderTop: "1px solid rgba(0, 0, 0, 0.06)" + borderTop: "1px solid rgba(0, 0, 0, 0.06)", }, "& td, & th": { - display: "table-cell" - } + display: "table-cell", + }, }, center: { - textAlign: "center" - } + textAlign: "center", + }, }; const useStyles = makeStyles(styles); diff --git a/jams-react-client/src/views/UserProfile/DisplayUserProfile.js b/jams-react-client/src/views/UserProfile/DisplayUserProfile.js index 03b3b457..2a258d5c 100644 --- a/jams-react-client/src/views/UserProfile/DisplayUserProfile.js +++ b/jams-react-client/src/views/UserProfile/DisplayUserProfile.js @@ -19,10 +19,10 @@ import DialogContentText from "@material-ui/core/DialogContentText"; import DialogTitle from "@material-ui/core/DialogTitle"; import EditIcon from "@material-ui/icons/Edit"; import DeleteIcon from "@material-ui/icons/Delete"; -import AddCircleOutlineIcon from '@material-ui/icons/AddCircleOutline'; +import AddCircleOutlineIcon from "@material-ui/icons/AddCircleOutline"; import Table from "@material-ui/core/Table"; -import TableHead from '@material-ui/core/TableHead'; +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"; @@ -36,7 +36,6 @@ import SmartphoneOutlinedIcon from "@material-ui/icons/SmartphoneOutlined"; import LocalPrintshopOutlinedIcon from "@material-ui/icons/LocalPrintshopOutlined"; import PhoneForwardedOutlinedIcon from "@material-ui/icons/PhoneForwardedOutlined"; - import Avatar from "@material-ui/core/Avatar"; import Chip from "@material-ui/core/Chip"; import CardAvatar from "components/Card/CardAvatar"; @@ -61,7 +60,7 @@ import { api_path_get_group, api_path_post_group_member, api_path_get_admin_user_groups, - api_path_delete_group_member + api_path_delete_group_member, } from "globalUrls"; import dashboardStyle from "assets/jss/material-dashboard-react/views/dashboardStyle.js"; @@ -69,10 +68,9 @@ import dashboardStyle from "assets/jss/material-dashboard-react/views/dashboardS import { hexToRgb, blackColor } from "assets/jss/material-dashboard-react.js"; import axios from "axios"; - import PasswordDialog from "components/PasswordDialog/PasswordDialog"; -import TemporaryDrawer from "components/Drawer/Drawer" +import TemporaryDrawer from "components/Drawer/Drawer"; import i18next from "i18next"; @@ -133,25 +131,25 @@ const styles = (theme) => ({ [theme.breakpoints.down("md")]: { display: "flex", flexDirection: "column", - } + }, }, - footerActionButtons:{ + footerActionButtons: { display: "flex", flexDirection: "row", alignItems: "end", "& button": { - marginRight: "1rem" + marginRight: "1rem", }, [theme.breakpoints.down("md")]: { flexDirection: "column", alignItems: "stretch", "& button": { marginRight: "0", - width: "100%" + width: "100%", }, - } + }, }, - footerActionButtonsRight:{ + footerActionButtonsRight: { display: "flex", justifyContent: "flex-end", alignItems: "end", @@ -161,9 +159,9 @@ const styles = (theme) => ({ alignItems: "stretch", "& button": { marginRight: "0", - width: "100%" + width: "100%", }, - } + }, }, userProfileHeader: { display: "flex", @@ -184,7 +182,7 @@ const styles = (theme) => ({ }, cardAvatarMobile: { [theme.breakpoints.down("md")]: { - textAlign: "center" + textAlign: "center", }, }, loading: { @@ -192,7 +190,7 @@ const styles = (theme) => ({ }, whiteButtonText: { color: "white", - } + }, }); const useStyles = makeStyles(styles); @@ -212,7 +210,7 @@ export default function DisplayUserProfile(props) { const [openDrawer, setOpenDrawer] = React.useState(false); const searchGroups = (value) => { - if(value === "") value = "*"; + if (value === "") value = "*"; axios( configApiCall( api_path_get_list_group + "?groupName=" + value, @@ -224,16 +222,16 @@ export default function DisplayUserProfile(props) { .then((response) => { let availableGroups = []; const groupResults = response.data; - groupResults.forEach((possibleGroup) =>{ - let existingGroup = false; - groups.forEach((actualGroup)=>{ - if(actualGroup === possibleGroup.name) { - existingGroup = true; - return; - } - }) - if(!existingGroup) availableGroups.push(possibleGroup); - }) + groupResults.forEach((possibleGroup) => { + let existingGroup = false; + groups.forEach((actualGroup) => { + if (actualGroup === possibleGroup.name) { + existingGroup = true; + return; + } + }); + if (!existingGroup) availableGroups.push(possibleGroup); + }); setGroups(availableGroups); }) .catch((error) => { @@ -241,21 +239,19 @@ export default function DisplayUserProfile(props) { if (error.response.status === 401) { auth.authenticated = false; history.push("/"); - }else { + } else { setGroups([]); } } else { setGroups([]); } - }); - } + }; const removeUserFromGroup = (group) => { - let data = { - "username": props.username - } + username: props.username, + }; axios( configApiCall( @@ -264,38 +260,36 @@ export default function DisplayUserProfile(props) { data, null ) - ).then((response)=>{ + ) + .then((response) => { let newGroupMemberships = groupMemberships; newGroupMemberships.splice(newGroupMemberships.indexOf(group), 1); setGroupMemberships(newGroupMemberships); - }).catch((error)=>{console.log(error)}) - + }) + .catch((error) => { + console.log(error); + }); }; const addUserToGroup = (group) => { - let data = { - "username": props.username - } + username: props.username, + }; axios( - configApiCall( - api_path_post_group_member + group.id, - "POST", - data, - null - ) - ).then((response)=>{ + configApiCall(api_path_post_group_member + group.id, "POST", data, null) + ) + .then((response) => { let newGroupMemberships = groupMemberships; - newGroupMemberships.push( - { - "groupId": group.id, - "name": group.name - } - ); + newGroupMemberships.push({ + groupId: group.id, + name: group.name, + }); setGroupMemberships(newGroupMemberships); - }).catch((error)=>{console.log(error)}) - + }) + .catch((error) => { + console.log(error); + }); }; useEffect(() => { @@ -330,28 +324,40 @@ export default function DisplayUserProfile(props) { ) .then((response) => { setUser(response.data); - axios(configApiCall(api_path_get_admin_user_groups + props.username, - "GET", - null, - null - )).then((userGroups) => { - let userGroupsData = userGroups.data; - userGroupsData.forEach((group) => { - axios(configApiCall(api_path_get_group + group.groupId, 'GET', null, null)).then((groupInfo) =>{ - group["name"] = groupInfo.data.name; + axios( + configApiCall( + api_path_get_admin_user_groups + props.username, + "GET", + null, + null + ) + ) + .then((userGroups) => { + let userGroupsData = userGroups.data; + userGroupsData.forEach((group) => { + axios( + configApiCall( + api_path_get_group + group.groupId, + "GET", + null, + null + ) + ).then((groupInfo) => { + group["name"] = groupInfo.data.name; + }); }); + setGroupMemberships(userGroupsData); + }) + .catch((error) => { + if (error.response.status === 401) { + auth.authenticated = false; + history.push("/signin"); + } + if (error.response.status === 404) { + setGroupMemberships([]); + } }); - setGroupMemberships(userGroupsData); - }).catch((error) => { - if (error.response.status === 401) { - auth.authenticated = false; - history.push("/signin"); - } - if (error.response.status === 404) { - setGroupMemberships([]); - } - }) - searchGroups("*") + searchGroups("*"); setLoading(false); }) .catch((error) => { @@ -391,27 +397,39 @@ export default function DisplayUserProfile(props) { ) .then((response) => { setUser(response.data); - axios(configApiCall(api_path_get_admin_user_groups + props.username, - "GET", - null, - null - )).then((userGroups) => { - let userGroupsData = userGroups.data; - userGroupsData.forEach((group) => { - axios(configApiCall(api_path_get_group + group.groupId, 'GET', null, null)).then((groupInfo) =>{ - group["name"] = groupInfo.data.name; + axios( + configApiCall( + api_path_get_admin_user_groups + props.username, + "GET", + null, + null + ) + ) + .then((userGroups) => { + let userGroupsData = userGroups.data; + userGroupsData.forEach((group) => { + axios( + configApiCall( + api_path_get_group + group.groupId, + "GET", + null, + null + ) + ).then((groupInfo) => { + group["name"] = groupInfo.data.name; + }); }); + setGroupMemberships(userGroupsData); + }) + .catch((error) => { + if (error.response.status === 401) { + auth.authenticated = false; + history.push("/signin"); + } + if (error.response.status === 404) { + setGroupMemberships([]); + } }); - setGroupMemberships(userGroupsData); - }).catch((error) => { - if (error.response.status === 401) { - auth.authenticated = false; - history.push("/signin"); - } - if (error.response.status === 404) { - setGroupMemberships([]); - } - }) setLoading(false); }) .catch((error) => { @@ -490,16 +508,15 @@ export default function DisplayUserProfile(props) { }; const tableCellClasses = classnames(classes.tableCell); - + const canEdit = () => { - if(auth.isLocalDirectory()) { - if(!auth.hasAdminScope() && auth.getUsername() !== user.username) { - return false + if (auth.isLocalDirectory()) { + if (!auth.hasAdminScope() && auth.getUsername() !== user.username) { + return false; } return true; - } - else return false; - } + } else return false; + }; return ( <div> @@ -514,14 +531,23 @@ export default function DisplayUserProfile(props) { </DialogTitle> <DialogContent> <DialogContentText id="alert-dialog-description"> - {i18next.t("are_you_sure_want_revoke", "Are you sure you want to revoke")} <strong>{revokedUser}</strong> ? + {i18next.t( + "are_you_sure_want_revoke", + "Are you sure you want to revoke" + )}{" "} + <strong>{revokedUser}</strong> ? </DialogContentText> </DialogContent> <DialogActions> <Button onClick={handleClose} color="primary"> {i18next.t("cancel", "Cancel")} </Button> - <Button onClick={revokeUser} color="info" className={classes.whiteButtonText} autoFocus> + <Button + onClick={revokeUser} + color="info" + className={classes.whiteButtonText} + autoFocus + > {i18next.t("revoke", "Revoke")} </Button> </DialogActions> @@ -533,206 +559,231 @@ export default function DisplayUserProfile(props) { handleClosechangePassword={handleClosechangePassword} /> <div className={classes.loading}> - {loading && ( - <LinearProgress variant="determinate" value={progress} /> - )} + {loading && <LinearProgress variant="determinate" value={progress} />} </div> - <TemporaryDrawer - openDrawer={openDrawer} - setOpenDrawer={setOpenDrawer} - direction="right" - placeholder={i18next.t("add_user_to_group", "Add user to group ...")} - searchTargets={searchGroups} - targets={groups} - existingTargets={groupMemberships} - addElementToTarget={addUserToGroup} - targetName={props.username} - type="group" + <TemporaryDrawer + openDrawer={openDrawer} + setOpenDrawer={setOpenDrawer} + direction="right" + placeholder={i18next.t("add_user_to_group", "Add user to group ...")} + searchTargets={searchGroups} + targets={groups} + existingTargets={groupMemberships} + addElementToTarget={addUserToGroup} + targetName={props.username} + type="group" /> - {!loading && (<GridContainer> - <Grid item xs={12} sm={12} md={6}> - <Card profile> - <CardBody profile> - <div className={classes.root}> - <Grid container spacing={2}> - <Grid item xs={12} sm={12} md={6}> - <CardAvatar - displayProfile - className={classes.cardAvatarMobile} - > - <img - src={ - user.profilePicture - ? "data:image/png;base64, " + user.profilePicture - : noProfilePicture - } - className={classes.editProfilePicture} - alt="..." - /> - </CardAvatar> - </Grid> - <Grid item xs={12} sm={12} md={6}> - <div className={classes.userProfileHeader}> - <div> - <h3 className={classes.cardTitle}> - {user.username} - </h3> - {getUserStatus()} + {!loading && ( + <GridContainer> + <Grid item xs={12} sm={12} md={6}> + <Card profile> + <CardBody profile> + <div className={classes.root}> + <Grid container spacing={2}> + <Grid item xs={12} sm={12} md={6}> + <CardAvatar + displayProfile + className={classes.cardAvatarMobile} + > + <img + src={ + user.profilePicture + ? "data:image/png;base64, " + user.profilePicture + : noProfilePicture + } + className={classes.editProfilePicture} + alt="..." + /> + </CardAvatar> + </Grid> + <Grid item xs={12} sm={12} md={6}> + <div className={classes.userProfileHeader}> + <div> + <h3 className={classes.cardTitle}>{user.username}</h3> + {getUserStatus()} + </div> </div> - </div> + </Grid> + <Grid item xs={12} sm={12} md={6}> + <List dense={false}> + {(user.firstName || user.lastName) && ( + <ListItem> + <ListItemAvatar> + <Avatar> + <PersonIcon /> + </Avatar> + </ListItemAvatar> + <ListItemText + primary={`${user.firstName} ${user.lastName}`} + /> + </ListItem> + )} + {user.phoneNumber && ( + <ListItem> + <ListItemAvatar> + <Avatar> + <PhoneInTalkOutlinedIcon /> + </Avatar> + </ListItemAvatar> + <ListItemText primary={user.phoneNumber} /> + </ListItem> + )} + {user.organization && ( + <ListItem> + <ListItemAvatar> + <Avatar> + <BusinessCenterOutlinedIcon /> + </Avatar> + </ListItemAvatar> + <ListItemText primary={user.organization} /> + </ListItem> + )} + </List> + + <List dense={false}> + {user.email && ( + <ListItem> + <ListItemAvatar> + <Avatar> + <AlternateEmailOutlinedIcon /> + </Avatar> + </ListItemAvatar> + <ListItemText primary={user.email} /> + </ListItem> + )} + {user.phoneNumberExtension && ( + <ListItem> + <ListItemAvatar> + <Avatar> + <PhoneForwardedOutlinedIcon /> + </Avatar> + </ListItemAvatar> + <ListItemText primary={user.phoneNumberExtension} /> + </ListItem> + )} + {user.mobileNumber && ( + <ListItem> + <ListItemAvatar> + <Avatar> + <SmartphoneOutlinedIcon /> + </Avatar> + </ListItemAvatar> + <ListItemText primary={user.mobileNumber} /> + </ListItem> + )} + {user.faxNumber && ( + <ListItem> + <ListItemAvatar> + <Avatar> + <LocalPrintshopOutlinedIcon /> + </Avatar> + </ListItemAvatar> + <ListItemText primary={user.faxNumber} /> + </ListItem> + )} + </List> + </Grid> </Grid> - <Grid item xs={12} sm={12} md={6}> - <List dense={false}> - {(user.firstName || user.lastName) && ( - <ListItem> - <ListItemAvatar> - <Avatar> - <PersonIcon /> - </Avatar> - </ListItemAvatar> - <ListItemText primary={`${user.firstName} ${user.lastName}`} /> - </ListItem> - )} - {user.phoneNumber && ( - <ListItem> - <ListItemAvatar> - <Avatar> - <PhoneInTalkOutlinedIcon /> - </Avatar> - </ListItemAvatar> - <ListItemText primary={user.phoneNumber} /> - </ListItem> - )} - {user.organization && ( - <ListItem> - <ListItemAvatar> - <Avatar> - <BusinessCenterOutlinedIcon /> - </Avatar> - </ListItemAvatar> - <ListItemText primary={user.organization} /> - </ListItem> - )} - </List> - - <List dense={false}> - {user.email && ( - <ListItem> - <ListItemAvatar> - <Avatar> - <AlternateEmailOutlinedIcon /> - </Avatar> - </ListItemAvatar> - <ListItemText primary={user.email} /> - </ListItem> - )} - {user.phoneNumberExtension && ( - <ListItem> - <ListItemAvatar> - <Avatar> - <PhoneForwardedOutlinedIcon /> - </Avatar> - </ListItemAvatar> - <ListItemText primary={user.phoneNumberExtension} /> - </ListItem> - )} - {user.mobileNumber && ( - <ListItem> - <ListItemAvatar> - <Avatar> - <SmartphoneOutlinedIcon /> - </Avatar> - </ListItemAvatar> - <ListItemText primary={user.mobileNumber} /> - </ListItem> - )} - {user.faxNumber && ( - <ListItem> - <ListItemAvatar> - <Avatar> - <LocalPrintshopOutlinedIcon /> - </Avatar> - </ListItemAvatar> - <ListItemText primary={user.faxNumber} /> - </ListItem> - )} - </List> + </div> + </CardBody> + <CardFooter className={classes.profileFooter}> + <Grid container className={classes.footerActionButtons}> + <Grid item> + {canEdit() && ( + <Button + color="info" + className={classes.whiteButtonText} + onClick={() => props.setDisplayUser(false)} + > + <EditIcon /> {i18next.t("edit_profile", "Edit profile")} + </Button> + )} </Grid> - </Grid> - </div> - </CardBody> - <CardFooter className={classes.profileFooter}> - <Grid container className={classes.footerActionButtons}> - <Grid item > - {canEdit() && ( - <Button - color="info" - className={classes.whiteButtonText} - onClick={() => props.setDisplayUser(false)} - > - <EditIcon /> {i18next.t("edit_profile", "Edit profile")} - </Button> - )} + <Grid item> + {auth.isLocalDirectory() && auth.hasAdminScope() && ( + <Button + color="info" + className={classes.whiteButtonText} + onClick={() => { + setChangePasswordOpen(true); + }} + > + <VpnKeyIcon />{" "} + {i18next.t("change_password", "Change password")} + </Button> + )} </Grid> - <Grid item > - {auth.isLocalDirectory() && auth.hasAdminScope() && ( - <Button - color="info" - className={classes.whiteButtonText} - onClick={() => { - setChangePasswordOpen(true); - }} - > - <VpnKeyIcon /> {i18next.t("change_password", "Change password")} - </Button> - )} + </Grid> + + <Grid container className={classes.footerActionButtonsRight}> + <Grid item> + {auth.hasAdminScope() && revoked === false && ( + <Button + color="info" + className={classes.whiteButtonText} + onClick={() => handleClickOpen(user.username)} + > + <DeleteIcon fontSize="small" />{" "} + {i18next.t("revoke_user", "Revoke user")} + </Button> + )} </Grid> - </Grid> - - <Grid container className={classes.footerActionButtonsRight}> - <Grid item> - {auth.hasAdminScope() && revoked === false && ( - <Button - color="info" - className={classes.whiteButtonText} - onClick={() => handleClickOpen(user.username)} - > - <DeleteIcon fontSize="small" /> {i18next.t("revoke_user", "Revoke user")} - </Button> - )} </Grid> - </Grid> - </CardFooter> - </Card> - </Grid> + </CardFooter> + </Card> + </Grid> {auth.hasAdminScope() && ( <GridItem xs={12} sm={12} md={12}> - <Button color="primary" onClick={() => {setOpenDrawer(true)}}><AddCircleOutlineIcon /> {i18next.t("add_user_to_a_group", "Add user to a group")}</Button> - <Table className={classes.table}> - <TableHead> - <TableRow> - <TableCell align="left">{i18next.t("group_name", "Group name")}</TableCell> - <TableCell align="right">{i18next.t("action", "Action")}</TableCell> - </TableRow> - </TableHead> - <TableBody> - {groupMemberships !== [] && groupMemberships.map(group => - <TableRow key={group} className={classes.tableRow}> - <TableCell className={tableCellClasses}> - <Link to={`/group/${group.groupId}`}> - {group.name} - </Link> - </TableCell> - <TableCell align="right" className={classes.tableActions}> - <Button color="primary" onClick={() => removeUserFromGroup(group)}>{i18next.t("remove_from_group", "Remove from group")}</Button> - </TableCell> - </TableRow> - ) } - </TableBody> - </Table> + <Button + color="primary" + onClick={() => { + setOpenDrawer(true); + }} + > + <AddCircleOutlineIcon />{" "} + {i18next.t("add_user_to_a_group", "Add user to a group")} + </Button> + <Table className={classes.table}> + <TableHead> + <TableRow> + <TableCell align="left"> + {i18next.t("group_name", "Group name")} + </TableCell> + <TableCell align="right"> + {i18next.t("action", "Action")} + </TableCell> + </TableRow> + </TableHead> + <TableBody> + {groupMemberships !== [] && + groupMemberships.map((group) => ( + <TableRow key={group} className={classes.tableRow}> + <TableCell className={tableCellClasses}> + <Link to={`/group/${group.groupId}`}> + {group.name} + </Link> + </TableCell> + <TableCell + align="right" + className={classes.tableActions} + > + <Button + color="primary" + onClick={() => removeUserFromGroup(group)} + > + {i18next.t( + "remove_from_group", + "Remove from group" + )} + </Button> + </TableCell> + </TableRow> + ))} + </TableBody> + </Table> </GridItem> )} - </GridContainer> + </GridContainer> )} </div> ); diff --git a/jams-react-client/src/views/UserProfile/EditCreateUserProfile.js b/jams-react-client/src/views/UserProfile/EditCreateUserProfile.js index 84d3f239..58832b73 100644 --- a/jams-react-client/src/views/UserProfile/EditCreateUserProfile.js +++ b/jams-react-client/src/views/UserProfile/EditCreateUserProfile.js @@ -140,8 +140,8 @@ const styles = (theme) => ({ display: "flex", flexDirection: "column", "& button": { - width: "100%" - } + width: "100%", + }, }, }, button: { @@ -194,28 +194,28 @@ const styles = (theme) => ({ [theme.breakpoints.down("xs")]: { display: "flex", flexDirection: "column", - alignItems: "center" - } + alignItems: "center", + }, }, profileEditAvatarMobile: { [theme.breakpoints.down("xs")]: { display: "flex", flexDirection: "column", alignItems: "center", - marginTop: 10 - } + marginTop: 10, + }, }, profileEditAvatarInputMobile: { [theme.breakpoints.down("xs")]: { - display: "flex", + display: "flex", flexDirection: "row", - justifyContent: "center", - alignItems: "center" - } + justifyContent: "center", + alignItems: "center", + }, }, whiteButtonText: { color: "white", - } + }, }); const useStyles = makeStyles(styles); @@ -270,7 +270,6 @@ export default function EditCreateUserProfile(props) { }); React.useEffect(() => { - if (!props.createUser) { setLoading(true); const timer = setInterval(() => { @@ -293,7 +292,7 @@ export default function EditCreateUserProfile(props) { ) .then((response) => { const user = response.data; - const values ={ + const values = { username: user.username, firstName: user.firstName, lastName: user.lastName, @@ -304,7 +303,7 @@ export default function EditCreateUserProfile(props) { phoneNumber: user.phoneNumber, phoneNumberExtension: user.phoneNumberExtension, mobileNumber: user.mobileNumber, - } + }; setInitialValues(values); setProfilePicture(user.profilePicture); if (user.profilePicture !== "") { @@ -470,18 +469,41 @@ export default function EditCreateUserProfile(props) { .min(3, i18next.t("minimum_3_characters", "Minimum 3 characters!")) .max(32, i18next.t("maximum_32_characters", "Maximum 32 characters!")) .required(i18next.t("username_is_required", "Username is required!")) - .matches(/^[A-Za-z_][A-Za-z0-9_]*$/, i18next.t("only_alphanumeric_characters", "Only alphanumeric characters!")), + .matches( + /^[A-Za-z_][A-Za-z0-9_]*$/, + i18next.t( + "only_alphanumeric_characters", + "Only alphanumeric characters!" + ) + ), password: props.createUser - ? Yup.string().required(i18next.t("password_is_required", "Password is required!")) + ? Yup.string().required( + i18next.t("password_is_required", "Password is required!") + ) : null, confirmPassword: props.createUser - ? Yup.string().oneOf([Yup.ref("password"), null], i18next.t("password_must_match", "Passwords must match")) + ? Yup.string().oneOf( + [Yup.ref("password"), null], + i18next.t("password_must_match", "Passwords must match") + ) : null, - firstName: Yup.string().min(2, i18next.t("first_name_is_too_short", "First name is too short!")), - lastName: Yup.string().min(2, i18next.t("last_name_is_too_short", "Last Name is too short!")), + firstName: Yup.string().min( + 2, + i18next.t("first_name_is_too_short", "First name is too short!") + ), + lastName: Yup.string().min( + 2, + i18next.t("last_name_is_too_short", "Last Name is too short!") + ), email: Yup.string().email(i18next.t("invalid_email", "Invalid email!")), profilePicture: Yup.string(), - organization: Yup.string().min(2, i18next.t("organization_name_too_short", "Organization name is too short!")), + organization: Yup.string().min( + 2, + i18next.t( + "organization_name_too_short", + "Organization name is too short!" + ) + ), faxNumber: Yup.string().matches( /^(\+\d{1,2}\s?)?1?\-?\.?\s?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4}$/, i18next.t("fax_not_valid", "Fax number not valid!") @@ -506,7 +528,9 @@ export default function EditCreateUserProfile(props) { aria-describedby="alert-dialog-description" classes={{ paper: classes.dialogPaper }} > - <DialogTitle id="alert-dialog-title">{i18next.t("crop_image", "Crop image")}</DialogTitle> + <DialogTitle id="alert-dialog-title"> + {i18next.t("crop_image", "Crop image")} + </DialogTitle> <DialogContent> <div className={classes.cropContainer}> <Cropper @@ -560,386 +584,444 @@ export default function EditCreateUserProfile(props) { </div> </DialogContent> <DialogActions> - <Button onClick={cropProfilePicture} color="info" className={classes.whiteButtonText} autoFocus> + <Button + onClick={cropProfilePicture} + color="info" + className={classes.whiteButtonText} + autoFocus + > {i18next.t("validate", "Validate")} </Button> </DialogActions> </Dialog> <div className={classes.loading}> - {loading && ( - <LinearProgress variant="determinate" value={progress} /> - )} + {loading && <LinearProgress variant="determinate" value={progress} />} </div> - {!loading && (<GridContainer> - <GridItem xs={12} sm={12} md={8}> - <Formik - initialValues={initialValues} - onSubmit={handleFormikSubmit} - validationSchema={EditCreateSchema} - > - {({ isValid, dirty, handleSubmit, setFieldValue, values }) => ( - <form onSubmit={handleSubmit}> - <Card profile> - <CardHeader color="info" stats icon className={classes.profileEditHeaderMobile}> - <p className={classes.cardCategory}> - {props.createUser ? i18next.t("create_new_profile", "Create new profile") : i18next.t("edit_profile", "Edit profile")} - </p> - {props.createUser ? ( - "" - ) : ( - <h3 className={classes.cardTitle}>{userName}</h3> - )} - </CardHeader> - <CardBody profile> - <CardAvatar editProfile className={classes.profileEditAvatarMobile}> - <img - src={profilePicturePreview} - alt="..." - className={classes.editProfilePicture} - onClick={() => { - let pictureChange = document.getElementById( - "change-profile-picture" - ); - pictureChange.click(); - }} - /> - </CardAvatar> - <div className={classes.root}> - <Grid container spacing={5}> - <Grid item xs={12} sm={12} md={12} className={classes.profileEditAvatarInputMobile} > - <input - accept="image/*" - className={classes.input} - id="icon-button-file" - type="file" - onChange={handleProfilePictureChange} - /> - <label htmlFor="icon-button-file"> - <IconButton - id="change-profile-picture" - color="info" - aria-label="upload picture" - component="span" - > - <PhotoCamera /> - </IconButton>{" "} - {i18next.t("change_profile_image", "Change profile image")} - </label> - </Grid> - {props.createUser && ( - <Grid item xs={12} sm={12} md={6}> + {!loading && ( + <GridContainer> + <GridItem xs={12} sm={12} md={8}> + <Formik + initialValues={initialValues} + onSubmit={handleFormikSubmit} + validationSchema={EditCreateSchema} + > + {({ isValid, dirty, handleSubmit, setFieldValue, values }) => ( + <form onSubmit={handleSubmit}> + <Card profile> + <CardHeader + color="info" + stats + icon + className={classes.profileEditHeaderMobile} + > + <p className={classes.cardCategory}> + {props.createUser + ? i18next.t( + "create_new_profile", + "Create new profile" + ) + : i18next.t("edit_profile", "Edit profile")} + </p> + {props.createUser ? ( + "" + ) : ( + <h3 className={classes.cardTitle}>{userName}</h3> + )} + </CardHeader> + <CardBody profile> + <CardAvatar + editProfile + className={classes.profileEditAvatarMobile} + > + <img + src={profilePicturePreview} + alt="..." + className={classes.editProfilePicture} + onClick={() => { + let pictureChange = document.getElementById( + "change-profile-picture" + ); + pictureChange.click(); + }} + /> + </CardAvatar> + <div className={classes.root}> + <Grid container spacing={5}> + <Grid + item + xs={12} + sm={12} + md={12} + className={classes.profileEditAvatarInputMobile} + > + <input + accept="image/*" + className={classes.input} + id="icon-button-file" + type="file" + onChange={handleProfilePictureChange} + /> + <label htmlFor="icon-button-file"> + <IconButton + id="change-profile-picture" + color="info" + aria-label="upload picture" + component="span" + > + <PhotoCamera /> + </IconButton>{" "} + {i18next.t( + "change_profile_image", + "Change profile image" + )} + </label> + </Grid> + {props.createUser && ( + <Grid item xs={12} sm={12} md={6}> + <FormikField + name="username" + label={i18next.t("username", "Username")} + placeholder={i18next.t("username", "Username")} + startAdornment={ + <InputAdornment position="start"> + <AccountCircleIcon /> + </InputAdornment> + } + endAdornment={ + values.username === "" ? ( + "" + ) : userExists ? ( + <CancelIcon style={{ color: "#cc0000" }} /> + ) : ( + <CheckCircleIcon + style={{ color: "#99cc00" }} + /> + ) + } + required + autoComplete="off" + handleChange={checkUserExists} + onKeyUpError={userExists} + onKeyUpErrorMessage={i18next.t( + "username_already_taken", + "Username already taken" + )} + /> + </Grid> + )} + {props.createUser && ( + <Grid item xs={12} sm={12} md={6}></Grid> + )} + {props.createUser && ( + <Grid item xs={12} sm={12} md={6}> + <FormikField + type={passwordVisible ? "text" : "password"} + name="password" + label={i18next.t("password", "Password")} + placeholder={i18next.t("password", "Password")} + startAdornment={ + <InputAdornment position="start"> + <VpnKeyIcon /> + </InputAdornment> + } + endAdornment={ + <IconButton + aria-label="toggle password visibility" + onMouseDown={handleMouseDownPassword} + onMouseUp={handleMouseUpPassword} + > + {passwordVisible ? ( + <VisibilityIcon /> + ) : ( + <VisibilityOffIcon /> + )} + </IconButton> + } + required + autoComplete="off" + handleChange={() => {}} + onKeyUpError={false} + onKeyUpErrorMessage="" + /> + </Grid> + )} + {props.createUser && ( + <Grid item xs={12} sm={12} md={6}> + <FormikField + type={passwordVisible ? "text" : "password"} + name="confirmPassword" + label={i18next.t( + "confirm_password", + "Confirm password" + )} + placeholder={i18next.t( + "confirm_password", + "Confirm password" + )} + startAdornment={ + <InputAdornment position="start"> + <VpnKeyIcon /> + </InputAdornment> + } + endAdornment={ + <IconButton + aria-label="toggle password visibility" + onMouseDown={handleMouseDownPassword} + onMouseUp={handleMouseUpPassword} + > + {passwordVisible ? ( + <VisibilityIcon /> + ) : ( + <VisibilityOffIcon /> + )} + </IconButton> + } + required + autoComplete="off" + handleChange={() => {}} + onKeyUpError={false} + onKeyUpErrorMessage="" + /> + </Grid> + )} + {props.createUser && ( + <Grid + item + align="left" + xs={12} + sm={12} + md={6} + ></Grid> + )} + {props.createUser && ( + <Grid item align="left" xs={12} sm={12} md={6}> + <Button + variant="contained" + color="primary" + size="large" + className={classes.button} + startIcon={<RefreshIcon />} + onClick={() => { + const newGeneratedPassword = passwordGenerator(); + setFieldValue( + "password", + newGeneratedPassword, + false + ); + setFieldValue( + "confirmPassword", + newGeneratedPassword, + false + ); + setCopied(false); + setGenerated(true); + }} + > + {i18next.t("generate", "Generate")} + </Button> + <CopyToClipboard + text={values.password} + onCopy={() => { + setCopied(true); + setGenerated(false); + }} + > + <Button + variant="contained" + color="primary" + size="large" + className={classes.button} + startIcon={<FileCopyIcon />} + > + {i18next.t( + "copy_to_clipboard", + "Copy to clipboard" + )} + </Button> + </CopyToClipboard> + {copied ? ( + <span style={{ marginLeft: "10px" }}> + {i18next.t("copied", "Copied")} + </span> + ) : null} + {generated ? ( + <span style={{ marginLeft: "10px" }}> + {i18next.t("generated", "Generated")} + </span> + ) : null} + </Grid> + )} + <Grid item align="center" xs={12} sm={12} md={6}> <FormikField - name="username" - label={i18next.t("username", "Username")} - placeholder={i18next.t("username", "Username")} + name="firstName" + label={i18next.t("first_name", "First name")} + placeholder={i18next.t( + "first_name", + "First name" + )} startAdornment={ <InputAdornment position="start"> - <AccountCircleIcon /> + <PersonIcon /> </InputAdornment> } - endAdornment={ - values.username === "" ? ( - "" - ) : userExists ? ( - <CancelIcon style={{ color: "#cc0000" }} /> - ) : ( - <CheckCircleIcon - style={{ color: "#99cc00" }} - /> - ) + handleChange={() => {}} + onKeyUpError={false} + onKeyUpErrorMessage="" + /> + </Grid> + <Grid item align="center" xs={12} sm={12} md={6}> + <FormikField + name="lastName" + label={i18next.t("last_name", "Last name")} + placeholder={i18next.t("last_name", "Last name")} + startAdornment={ + <InputAdornment position="start"> + <PersonOutlinedIcon /> + </InputAdornment> } - required - autoComplete="off" - handleChange={checkUserExists} - onKeyUpError={userExists} - onKeyUpErrorMessage={i18next.t("username_already_taken", "Username already taken")} + handleChange={() => {}} + onKeyUpError={false} + onKeyUpErrorMessage="" /> </Grid> - )} - {props.createUser && ( - <Grid item xs={12} sm={12} md={6}></Grid> - )} - {props.createUser && ( - <Grid item xs={12} sm={12} md={6}> + <Grid item align="center" xs={12} sm={12} md={6}> <FormikField - type={passwordVisible ? "text" : "password"} - name="password" - label={i18next.t("password", "Password")} - placeholder={i18next.t("password", "Password")} + name="email" + label={i18next.t("email", "Email")} + placeholder={i18next.t("email", "Email")} startAdornment={ <InputAdornment position="start"> - <VpnKeyIcon /> + <AlternateEmailOutlinedIcon /> </InputAdornment> } - endAdornment={ - <IconButton - aria-label="toggle password visibility" - onMouseDown={handleMouseDownPassword} - onMouseUp={handleMouseUpPassword} - > - {passwordVisible ? ( - <VisibilityIcon /> - ) : ( - <VisibilityOffIcon /> - )} - </IconButton> + handleChange={() => {}} + onKeyUpError={false} + onKeyUpErrorMessage="" + /> + </Grid> + <Grid item align="center" xs={12} sm={12} md={6}> + <FormikField + name="organization" + label={i18next.t("organization", "Organization")} + placeholder={i18next.t( + "organization", + "Organization" + )} + startAdornment={ + <InputAdornment position="start"> + <BusinessCenterOutlinedIcon /> + </InputAdornment> } - required - autoComplete="off" handleChange={() => {}} onKeyUpError={false} onKeyUpErrorMessage="" /> </Grid> - )} - {props.createUser && ( - <Grid item xs={12} sm={12} md={6}> + <Grid item align="center" xs={12} sm={12} md={6}> <FormikField - type={passwordVisible ? "text" : "password"} - name="confirmPassword" - label={i18next.t("confirm_password", "Confirm password")} - placeholder={i18next.t("confirm_password", "Confirm password")} + name="faxNumber" + label={i18next.t("fax_number", "Fax number")} + placeholder={i18next.t( + "fax_number", + "Fax number" + )} startAdornment={ <InputAdornment position="start"> - <VpnKeyIcon /> + <LocalPrintshopOutlinedIcon /> </InputAdornment> } - endAdornment={ - <IconButton - aria-label="toggle password visibility" - onMouseDown={handleMouseDownPassword} - onMouseUp={handleMouseUpPassword} - > - {passwordVisible ? ( - <VisibilityIcon /> - ) : ( - <VisibilityOffIcon /> - )} - </IconButton> + handleChange={() => {}} + onKeyUpError={false} + onKeyUpErrorMessage="" + /> + </Grid> + <Grid item align="center" xs={12} sm={12} md={6}> + <FormikField + name="phoneNumber" + label={i18next.t("phone_number", "Phone number")} + placeholder={i18next.t( + "phone_number", + "Phone number" + )} + startAdornment={ + <InputAdornment position="start"> + <PhoneInTalkOutlinedIcon /> + </InputAdornment> } - required - autoComplete="off" handleChange={() => {}} onKeyUpError={false} onKeyUpErrorMessage="" /> </Grid> - )} - {props.createUser && ( - <Grid item align="left" xs={12} sm={12} md={6}></Grid> - )} - {props.createUser && ( - <Grid item align="left" xs={12} sm={12} md={6}> - <Button - variant="contained" - color="primary" - size="large" - className={classes.button} - startIcon={<RefreshIcon />} - onClick={() => { - const newGeneratedPassword = passwordGenerator(); - setFieldValue( - "password", - newGeneratedPassword, - false - ); - setFieldValue( - "confirmPassword", - newGeneratedPassword, - false - ); - setCopied(false); - setGenerated(true); - }} - > - {i18next.t("generate", "Generate")} - </Button> - <CopyToClipboard - text={values.password} - onCopy={() => { - setCopied(true); - setGenerated(false); - }} - > - <Button - variant="contained" - color="primary" - size="large" - className={classes.button} - startIcon={<FileCopyIcon />} - > - {i18next.t("copy_to_clipboard", "Copy to clipboard")} - </Button> - </CopyToClipboard> - {copied ? ( - <span style={{ marginLeft: "10px" }}>{i18next.t("copied", "Copied")}</span> - ) : null} - {generated ? ( - <span style={{ marginLeft: "10px" }}> - {i18next.t("generated", "Generated")} - </span> - ) : null} + <Grid item align="center" xs={12} sm={12} md={6}> + <FormikField + name="phoneNumberExtension" + label={i18next.t("extension", "Extension")} + placeholder={i18next.t("extension", "Extension")} + startAdornment={ + <InputAdornment position="start"> + <PhoneForwardedOutlinedIcon /> + </InputAdornment> + } + handleChange={() => {}} + onKeyUpError={false} + onKeyUpErrorMessage="" + /> + </Grid> + <Grid item align="center" xs={12} sm={12} md={6}> + <FormikField + name="mobileNumber" + label={i18next.t("mobile", "Mobile")} + placeholder={i18next.t("mobile", "Mobile")} + startAdornment={ + <InputAdornment position="start"> + <SmartphoneOutlinedIcon /> + </InputAdornment> + } + handleChange={() => {}} + onKeyUpError={false} + onKeyUpErrorMessage="" + /> </Grid> - )} - <Grid item align="center" xs={12} sm={12} md={6}> - <FormikField - name="firstName" - label={i18next.t("first_name", "First name")} - placeholder={i18next.t("first_name", "First name")} - startAdornment={ - <InputAdornment position="start"> - <PersonIcon /> - </InputAdornment> - } - handleChange={() => {}} - onKeyUpError={false} - onKeyUpErrorMessage="" - /> - </Grid> - <Grid item align="center" xs={12} sm={12} md={6}> - <FormikField - name="lastName" - label={i18next.t("last_name", "Last name")} - placeholder={i18next.t("last_name", "Last name")} - startAdornment={ - <InputAdornment position="start"> - <PersonOutlinedIcon /> - </InputAdornment> - } - handleChange={() => {}} - onKeyUpError={false} - onKeyUpErrorMessage="" - /> - </Grid> - <Grid item align="center" xs={12} sm={12} md={6}> - <FormikField - name="email" - label={i18next.t("email", "Email")} - placeholder={i18next.t("email", "Email")} - startAdornment={ - <InputAdornment position="start"> - <AlternateEmailOutlinedIcon /> - </InputAdornment> - } - handleChange={() => {}} - onKeyUpError={false} - onKeyUpErrorMessage="" - /> - </Grid> - <Grid item align="center" xs={12} sm={12} md={6}> - <FormikField - name="organization" - label={i18next.t("organization", "Organization")} - placeholder={i18next.t("organization", "Organization")} - startAdornment={ - <InputAdornment position="start"> - <BusinessCenterOutlinedIcon /> - </InputAdornment> - } - handleChange={() => {}} - onKeyUpError={false} - onKeyUpErrorMessage="" - /> - </Grid> - <Grid item align="center" xs={12} sm={12} md={6}> - <FormikField - name="faxNumber" - label={i18next.t("fax_number", "Fax number")} - placeholder={i18next.t("fax_number", "Fax number")} - startAdornment={ - <InputAdornment position="start"> - <LocalPrintshopOutlinedIcon /> - </InputAdornment> - } - handleChange={() => {}} - onKeyUpError={false} - onKeyUpErrorMessage="" - /> - </Grid> - <Grid item align="center" xs={12} sm={12} md={6}> - <FormikField - name="phoneNumber" - label={i18next.t("phone_number", "Phone number")} - placeholder={i18next.t("phone_number", "Phone number")} - startAdornment={ - <InputAdornment position="start"> - <PhoneInTalkOutlinedIcon /> - </InputAdornment> - } - handleChange={() => {}} - onKeyUpError={false} - onKeyUpErrorMessage="" - /> - </Grid> - <Grid item align="center" xs={12} sm={12} md={6}> - <FormikField - name="phoneNumberExtension" - label={i18next.t("extension", "Extension")} - placeholder={i18next.t("extension", "Extension")} - startAdornment={ - <InputAdornment position="start"> - <PhoneForwardedOutlinedIcon /> - </InputAdornment> - } - handleChange={() => {}} - onKeyUpError={false} - onKeyUpErrorMessage="" - /> - </Grid> - <Grid item align="center" xs={12} sm={12} md={6}> - <FormikField - name="mobileNumber" - label={i18next.t("mobile", "Mobile")} - placeholder={i18next.t("mobile", "Mobile")} - startAdornment={ - <InputAdornment position="start"> - <SmartphoneOutlinedIcon /> - </InputAdornment> - } - handleChange={() => {}} - onKeyUpError={false} - onKeyUpErrorMessage="" - /> </Grid> - </Grid> - </div> - </CardBody> - <CardFooter className={classes.alignRight}> - {!props.createUser && ( - <Button - color="info" - className={classes.whiteButtonText} - onClick={handleCancelUpdate} - > - {i18next.t("cancel", "Cancel")} - </Button> - )} - {props.createUser ? ( - <Button - type="submit" - disabled={!isValid || !dirty || userExists} - color="info" - className={classes.whiteButtonText} - > - {i18next.t("create_profile", "Create Profile")} - </Button> - ) : ( - <Button - type="submit" - disabled={!isValid} - color="info" - className={classes.whiteButtonText} - > - {i18next.t("save_profile", "Save Profile")} - </Button> - )} - </CardFooter> - </Card> - </form> - )} - </Formik> - </GridItem> - </GridContainer> + </div> + </CardBody> + <CardFooter className={classes.alignRight}> + {!props.createUser && ( + <Button + color="info" + className={classes.whiteButtonText} + onClick={handleCancelUpdate} + > + {i18next.t("cancel", "Cancel")} + </Button> + )} + {props.createUser ? ( + <Button + type="submit" + disabled={!isValid || !dirty || userExists} + color="info" + className={classes.whiteButtonText} + > + {i18next.t("create_profile", "Create Profile")} + </Button> + ) : ( + <Button + type="submit" + disabled={!isValid} + color="info" + className={classes.whiteButtonText} + > + {i18next.t("save_profile", "Save Profile")} + </Button> + )} + </CardFooter> + </Card> + </form> + )} + </Formik> + </GridItem> + </GridContainer> )} </div> ); diff --git a/jams-react-client/src/views/UserProfile/UserProfile.js b/jams-react-client/src/views/UserProfile/UserProfile.js index abf8477f..62cc5dc8 100755 --- a/jams-react-client/src/views/UserProfile/UserProfile.js +++ b/jams-react-client/src/views/UserProfile/UserProfile.js @@ -65,7 +65,7 @@ export default function UserProfile(props) { }; React.useEffect(() => { - if(props.username === "null") { + if (props.username === "null") { history.push("/"); } }, []); diff --git a/jams-react-client/src/views/UserProfile/cropImage.js b/jams-react-client/src/views/UserProfile/cropImage.js index bf3a9e6a..1bd5b8de 100644 --- a/jams-react-client/src/views/UserProfile/cropImage.js +++ b/jams-react-client/src/views/UserProfile/cropImage.js @@ -1,14 +1,14 @@ -const createImage = url => +const createImage = (url) => new Promise((resolve, reject) => { - const image = new Image() - image.addEventListener('load', () => resolve(image)) - image.addEventListener('error', error => reject(error)) - image.setAttribute('crossOrigin', 'anonymous') // needed to avoid cross-origin issues on CodeSandbox - image.src = url - }) + const image = new Image(); + image.addEventListener("load", () => resolve(image)); + image.addEventListener("error", (error) => reject(error)); + image.setAttribute("crossOrigin", "anonymous"); // needed to avoid cross-origin issues on CodeSandbox + image.src = url; + }); function getRadianAngle(degreeValue) { - return (degreeValue * Math.PI) / 180 + return (degreeValue * Math.PI) / 180; } /** @@ -18,49 +18,49 @@ function getRadianAngle(degreeValue) { * @param {number} rotation - optional rotation parameter */ export default async function getCroppedImg(imageSrc, pixelCrop, rotation = 0) { - const image = await createImage(imageSrc) - const canvas = document.createElement('canvas') - const ctx = canvas.getContext('2d') + const image = await createImage(imageSrc); + const canvas = document.createElement("canvas"); + const ctx = canvas.getContext("2d"); - const maxSize = Math.max(image.width, image.height) - const safeArea = 2 * ((maxSize / 2) * Math.sqrt(2)) + const maxSize = Math.max(image.width, image.height); + const safeArea = 2 * ((maxSize / 2) * Math.sqrt(2)); // set each dimensions to double largest dimension to allow for a safe area for the // image to rotate in without being clipped by canvas context - canvas.width = safeArea - canvas.height = safeArea + canvas.width = safeArea; + canvas.height = safeArea; // translate canvas context to a central location on image to allow rotating around the center. - ctx.translate(safeArea / 2, safeArea / 2) - ctx.rotate(getRadianAngle(rotation)) - ctx.translate(-safeArea / 2, -safeArea / 2) + ctx.translate(safeArea / 2, safeArea / 2); + ctx.rotate(getRadianAngle(rotation)); + ctx.translate(-safeArea / 2, -safeArea / 2); // draw rotated image and store data. ctx.drawImage( image, safeArea / 2 - image.width * 0.5, safeArea / 2 - image.height * 0.5 - ) - const data = ctx.getImageData(0, 0, safeArea, safeArea) + ); + const data = ctx.getImageData(0, 0, safeArea, safeArea); // set canvas width to final desired crop size - this will clear existing context - canvas.width = pixelCrop.width - canvas.height = pixelCrop.height + canvas.width = pixelCrop.width; + canvas.height = pixelCrop.height; // paste generated rotate image with correct offsets for x,y crop values. ctx.putImageData( data, 0 - safeArea / 2 + image.width * 0.5 - pixelCrop.x, 0 - safeArea / 2 + image.height * 0.5 - pixelCrop.y - ) + ); // As Base64 string - return canvas.toDataURL('image/jpeg'); + return canvas.toDataURL("image/jpeg"); // As a blob -// return new Promise(resolve => { -// canvas.toBlob(file => { -// resolve(URL.createObjectURL(file)) -// }, 'image/jpeg') -// }) + // return new Promise(resolve => { + // canvas.toBlob(file => { + // resolve(URL.createObjectURL(file)) + // }, 'image/jpeg') + // }) } diff --git a/jams-react-client/src/views/Users/Users.js b/jams-react-client/src/views/Users/Users.js index 90baa046..59ce0c9f 100644 --- a/jams-react-client/src/views/Users/Users.js +++ b/jams-react-client/src/views/Users/Users.js @@ -1,5 +1,5 @@ import React, { useState, useEffect, useCallback } from "react"; -import { Link } from 'react-router-dom' +import { Link } from "react-router-dom"; import { useHistory } from "react-router-dom"; // @material-ui/core components import { makeStyles } from "@material-ui/core/styles"; @@ -18,9 +18,9 @@ import UserProfile from "views/UserProfile/UserProfile.js"; import InfoIcon from "@material-ui/icons/Info"; import BusinessOutlinedIcon from "@material-ui/icons/BusinessOutlined"; import Search from "@material-ui/icons/Search"; -import Checkbox from '@material-ui/core/Checkbox'; -import FormGroup from '@material-ui/core/FormGroup'; -import FormControlLabel from '@material-ui/core/FormControlLabel'; +import Checkbox from "@material-ui/core/Checkbox"; +import FormGroup from "@material-ui/core/FormGroup"; +import FormControlLabel from "@material-ui/core/FormControlLabel"; import axios from "axios"; import configApiCall from "api.js"; import auth from "auth.js"; @@ -68,9 +68,8 @@ const styles = { alignItems: "center", }, cardBodyContent: { - - wordWrap: "break-word" - } + wordWrap: "break-word", + }, }; const useStyles = makeStyles(styles); export default function Users(props) { @@ -83,7 +82,7 @@ export default function Users(props) { const [createUser, setCreateUser] = React.useState(false); const [loading, setLoading] = React.useState(false); const [progress, setProgress] = React.useState(0); - const [showRevokedUsers, setShowRevokedUsers] = React.useState(false) + const [showRevokedUsers, setShowRevokedUsers] = React.useState(false); const [searchValue, setSearchValue] = React.useState(""); @@ -181,24 +180,22 @@ export default function Users(props) { <GridItem xs={12} sm={12} md={12}> {auth.isLocalDirectory() && auth.hasAdminScope() && ( <Link to={"/createuser"}> - <Button - variant="contained" - color="primary" - > + <Button variant="contained" color="primary"> <AddCircleOutlineIcon />{" "} {i18next.t("create_user", "Create user")} </Button> </Link> )} <FormControlLabel - control={ - <Checkbox - checked={showRevokedUsers} - onChange={() => setShowRevokedUsers(!showRevokedUsers)} - inputProps={{ 'aria-label': 'primary checkbox' }} - color="primary" - />} - style={{marginLeft: "1rem"}} + control={ + <Checkbox + checked={showRevokedUsers} + onChange={() => setShowRevokedUsers(!showRevokedUsers)} + inputProps={{ "aria-label": "primary checkbox" }} + color="primary" + /> + } + style={{ marginLeft: "1rem" }} label="Display revoked users" /> @@ -210,8 +207,10 @@ export default function Users(props) { className: classes.margin + " " + classes.search, }} inputProps={{ - placeholder: - i18next.t("search_users_using", "Search users using (username, first name, last name)"), + placeholder: i18next.t( + "search_users_using", + "Search users using (username, first name, last name)" + ), inputProps: { "aria-label": i18next.t("search_users", "Search users"), }, @@ -242,7 +241,9 @@ export default function Users(props) { <div className={classes.usersNotFound}> <InfoIcon /> - <p style={{ marginLeft: "10px" }}>{i18next.t("no_users_found", "No users found")}</p> + <p style={{ marginLeft: "10px" }}> + {i18next.t("no_users_found", "No users found")} + </p> </div> )} </GridItem> @@ -258,64 +259,60 @@ export default function Users(props) { return 0; }) .map((user) => ( - <GridItem - xs={12} - sm={6} - md={3} - lg={2} - xl={2} - - key={user.username} - > - <Card profile > + <GridItem xs={12} sm={6} md={3} lg={2} xl={2} key={user.username}> + <Card profile> <Link to={`/user/${user.username}`}> <CardBody profile> <CardAvatar profile> <img src={ user.profilePicture - ? "data:image/png;base64, " + - user.profilePicture + ? "data:image/png;base64, " + user.profilePicture : noProfilePicture } alt="..." /> </CardAvatar> - + <GridContainer - container - direction="column" - justify="flex-end" - alignItems="flex-start" - > - <GridItem style={{ minHeight:"50px"}}> - <h4 className={classes.cardTitle}> + container + direction="column" + justify="flex-end" + alignItems="flex-start" + > + <GridItem style={{ minHeight: "50px" }}> + <h4 className={classes.cardTitle}> {`${user.firstName} ${user.lastName}`} </h4> </GridItem> <GridItem> <ul className={classes.cardBodyContent}> - <li> - <img - src={jami} - width="20px" - alt="Jami" - style={{ minWidth:"20px", marginRight: "10px" }} - />{" "} - {user.username} - </li> - <li> - {user.organization && <BusinessOutlinedIcon - fontSize="small" - style={{ marginRight: "10px" }} - />}{" "} - {user.organization} - </li> - </ul> + <li> + <img + src={jami} + width="20px" + alt="Jami" + style={{ + minWidth: "20px", + marginRight: "10px", + }} + />{" "} + {user.username} + </li> + <li> + {user.organization && ( + <BusinessOutlinedIcon + fontSize="small" + style={{ marginRight: "10px" }} + /> + )}{" "} + {user.organization} + </li> + </ul> </GridItem> </GridContainer> - </CardBody> - </Link> + </CardBody> + </Link> </Card> </GridItem> ))} @@ -324,7 +321,10 @@ export default function Users(props) { <InfoIcon /> <p style={{ marginLeft: "10px" }}> - {i18next.t("no_users_found_matching", "No users found matching search value!")} + {i18next.t( + "no_users_found_matching", + "No users found matching search value!" + )} </p> </div> )} -- GitLab